[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
taya@turtle10.m2g.org:/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)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- some code assumes sizeof(char *) == sizeof(int),
taya <=