bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

some code assumes sizeof(char *) == sizeof(int)


From: taya
Subject: some code assumes sizeof(char *) == sizeof(int)
Date: Tue, 10 Apr 2001 23:42:27 +0900 (JST)

Configuration Information [Automatically generated, do not change]:
Machine: sparc64
OS: netbsd
Compiler: cc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='sparc64' 
-DCONF_OSTYPE='netbsd' -DCONF_MACHTYPE='sparc64--netbsd' -DCONF_VENDOR='' 
-DSHELL  -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib -I/usr/pkg/include -O
uname output: NetBSD turtle10.m2g.org 1.5T NetBSD 1.5T (SUN-ULTRA1) #4: Sun Mar 
25 19:55:09 JST 2001     
address@hidden:/export/NetBSD/NetBSD-current/src/sys/arch/sparc64/compile/SUN-ULTRA1
 sparc64
Machine Type: sparc64--netbsd

Bash Version: 2.04
Patch Level: 0
Release Status: release

Description:

unwind_prot.[ch] of bash-2.04 assumes sizeof(char *) == sizeof(int).
This cause problem on sparc64(LP64, big endian arch).

unwind_prot.h:
/* Try to force correct alignment on machines where pointers and ints
   differ in size. */
typedef union {
  char *s;
  int i;
} UWP;

/* How to protect an integer. */
#define unwind_protect_int(X) \
        do \
          { \
            UWP u; \
            u.i = (X); \
            unwind_protect_var (&(X), u.s, sizeof (int)); \
          } \
        while (0)


unwind_prot.c:
void
unwind_protect_var (var, value, size)
     int *var;
     char *value;
     int size;
{
  SAVED_VAR *s = (SAVED_VAR *)xmalloc (sizeof (SAVED_VAR));

  s->variable = var;
  if (size != sizeof (int))
    {
        .
        .
        .
  else
    s->desired_setting = value;
        .
        .
        .


static void
restore_variable (sv)
     SAVED_VAR *sv;
{
  if (sv->size != sizeof (int))
    {
      FASTCOPY ((char *)sv->desired_setting, (char *)sv->variable, sv->size);
      free (sv->desired_setting);
    }
  else
    *(sv->variable) = (int)sv->desired_setting;

  free (sv);
}

---
This means..
1) if i call unwind_protect_int() as follows,

   int   a = 0x12345678;
   unwind_protect_int(a);

acutual 'value' passed to unwind_protect_var (var, value, size) would
be "0x12345678XXXXXXXX"(Xs are garbage) and this value is saved to
sv->desired-settings.

2) if i call restore_variable (sv), lower 32bit(0xXXXXXXXX) would be
restored to the variable.
This is a problem.

Repeat-By:

Fix:
I made a patch for bash to solve unwind_protect problem on sparc64.
How about this?
I tested on sparc64 & i386.

diff -ru ../../Orig/bash-2.04/lib/malloc/malloc.c ./lib/malloc/malloc.c
--- ../../Orig/bash-2.04/lib/malloc/malloc.c    Sat Oct  2 04:39:32 1999
+++ ./lib/malloc/malloc.c       Fri Feb 23 00:49:09 2001
@@ -796,10 +796,10 @@
   if (ptr == 0)
     return 0;
   /* If entire block has the desired alignment, just accept it.  */
-  if (((int) ptr & (alignment - 1)) == 0)
+  if (((size_t) ptr & (alignment - 1)) == 0)
     return ptr;
   /* Otherwise, get address of byte in the block that has that alignment.  */
-  aligned = (char *) (((int) ptr + alignment - 1) & -alignment);
+  aligned = (char *) (((size_t) ptr + alignment - 1) & -alignment);
 
   /* Store a suitable indication of how to free the block,
      so that free can find the true beginning of it.  */
diff -ru ../../Orig/bash-2.04/unwind_prot.c ./unwind_prot.c
--- ../../Orig/bash-2.04/unwind_prot.c  Thu Aug  5 20:23:32 1999
+++ ./unwind_prot.c     Fri Feb 23 00:50:57 2001
@@ -51,7 +51,7 @@
    points to this. */
 typedef struct {
   int *variable;
-  char *desired_setting;
+  UWP desired_setting;
   int size;
 } SAVED_VAR;
 
@@ -250,8 +250,9 @@
 discard_saved_var (sv)
      SAVED_VAR *sv;
 {
-  if (sv->size != sizeof (int))
-    free (sv->desired_setting);
+  if (sv->size != sizeof (int) && sv->size != sizeof (short) &&
+       sv->size != sizeof (char *))
+    free (sv->desired_setting.p);
   free (sv);
 }
 
@@ -263,13 +264,16 @@
 restore_variable (sv)
      SAVED_VAR *sv;
 {
-  if (sv->size != sizeof (int))
-    {
-      FASTCOPY ((char *)sv->desired_setting, (char *)sv->variable, sv->size);
-      free (sv->desired_setting);
-    }
-  else
-    *(sv->variable) = (int)sv->desired_setting;
+  if (sv->size == sizeof (int))
+    *(int *)(sv->variable) = sv->desired_setting.i;
+  else if (sv->size == sizeof (short))
+    *(short *)(sv->variable) = sv->desired_setting.s;
+  else if (sv->size == sizeof (char *))
+    *(char **)(sv->variable) = sv->desired_setting.p;
+  else {
+      FASTCOPY ((char *)sv->desired_setting.p, (char *)sv->variable, sv->size);
+      free (sv->desired_setting.p);
+  }
 
   free (sv);
 }
@@ -282,28 +286,32 @@
 void
 unwind_protect_var (var, value, size)
      int *var;
-     char *value;
+     UWP *value;
      int size;
 {
   SAVED_VAR *s = (SAVED_VAR *)xmalloc (sizeof (SAVED_VAR));
 
   s->variable = var;
-  if (size != sizeof (int))
-    {
+  if (size == sizeof (int)) {
+    s->desired_setting.i = value->i;
+  } else if (size == sizeof (short)) {
+    s->desired_setting.s = value->s;
+  } else if (size == sizeof (char *)) {
+    s->desired_setting.p = value->p;
+  } else {
       /* There is a problem here when VALUE is 0.  This tries to copy the
          first SIZE bytes starting at memory location 0 into
          s->desired_setting.  There is no guarantee that these bytes are
          0, or make a valid null pointer.  We can try to bzero the space,
          or just save it as 0 (or (void *)0).  If we do the latter, make
          sure restore_variable is changed to understand it. */
-      s->desired_setting = (char *)xmalloc (size);
+      s->desired_setting.p = (char *)xmalloc (size);
       if (value == 0)
-       bzero ((char *)s->desired_setting, size);
+       bzero ((char *)s->desired_setting.p, size);
       else
-       FASTCOPY (value, (char *)s->desired_setting, size);
-    }
-  else
-    s->desired_setting = value;
+       FASTCOPY (value, (char *)s->desired_setting.p, size);
+  }
+
   s->size = size;
   add_unwind_protect ((Function *)restore_variable, (char *)s);
 }
diff -ru ../../Orig/bash-2.04/unwind_prot.h ./unwind_prot.h
--- ../../Orig/bash-2.04/unwind_prot.h  Thu Aug  5 20:15:52 1999
+++ ./unwind_prot.h     Fri Feb 23 00:51:19 2001
@@ -33,8 +33,9 @@
 /* Try to force correct alignment on machines where pointers and ints
    differ in size. */
 typedef union {
-  char *s;
+  char *p;
   int i;
+  int s;
 } UWP;
 
 /* Define for people who like their code to look a certain way. */
@@ -46,16 +47,28 @@
          { \
            UWP u; \
            u.i = (X); \
-           unwind_protect_var (&(X), u.s, sizeof (int)); \
+           unwind_protect_var (&(X), &u, sizeof (int)); \
          } \
        while (0)
 
 #define unwind_protect_short(X) \
-  unwind_protect_var ((int *)&(X), (char *)&(X), sizeof (short))
+       do \
+         { \
+           UWP u; \
+           u.s = (X); \
+           unwind_protect_var (&(X), &u, sizeof (short)); \
+         } \
+       while (0)
 
 /* How to protect a pointer to a string. */
 #define unwind_protect_string(X) \
-  unwind_protect_var ((int *)&(X), (X), sizeof (char *))
+       do \
+         { \
+           UWP u; \
+           u.p = (X); \
+           unwind_protect_var (&(X), &u, sizeof (char *)); \
+         } \
+       while (0)
 
 /* How to protect any old pointer. */
 #define unwind_protect_pointer(X) unwind_protect_string (X)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]