Subject: 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: port-sparc64
Date: 02/22/2001 00:56:11
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.

--
I think there are two solutions for this problem.
1) change sizeof(int) -> sizeof(size_t)

e.g.
  if (size != sizeof (int))
    {
	.
	.
	.
	|
	V

  if (size != sizeof (size_t))
    {

and related stuffs(including unwind_protect_int() macro).

This cause always alloc memory for each unwind_protect_int().
This would be the performace problem.

2)change macro for unwind_prot_int()

#define unwind_protect_int(X) \
	unwind_protect_var(&(X), (char *)(X), sizeof(int))

This is dirty hack. Many warning would be issued. But work faster and
easier to fix.

Which fix is better?

There are same kind of bugs in other programs.
AFAIK, perl and GNU m4 have problem like this.

taya