Subject: Re: some code assumes sizeof(char *) == sizeof(int)
To: None <port-sparc64@netbsd.org, tech-pkg@netbsd.org>
From: Shin'ichiro TAYA <taya@sm.sony.co.jp>
List: tech-pkg
Date: 02/23/2001 01:36:38
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)