Closed McDutchie closed 2 years ago
This crash was introduced in ksh93u+ 2012-05-15 by this change (2012-05-15 diff):
diff --git a/src/cmd/ksh93/sh/nvtype.c b/src/cmd/ksh93/sh/nvtype.c
index f526ffea..851ca380 100644
--- a/src/cmd/ksh93/sh/nvtype.c
+++ b/src/cmd/ksh93/sh/nvtype.c
@@ -125,6 +125,8 @@ typedef struct
short _dshort;
char _cpointer;
char *_dpointer;
+ int32_t _cint32_t;
+ int32_t *_dint32_t;
} _Align_;
#define alignof(t) ((char*)&((_Align_*)0)->_d##t-(char*)&((_Align_*)0)->_c##t)
@@ -188,8 +190,8 @@ size_t nv_datasize(Namval_t *np, size_t *offset)
}
else
{
- a = alignof(long);
- s = sizeof(long);
+ a = alignof(int32_t);
+ s = sizeof(int32_t);
}
}
}
It might be one of the valgrind fixes noted in the changelog for this version (although the note is vague): https://github.com/ksh93/ksh/blob/0fcaff5f1d4aad044abf1c23d61d2e91a06db944/src/cmd/ksh93/RELEASE#L111 Reverting it fixes the crash when running the reproducer, but introduces another crash in types.sh when run under ASan:
$ ASAN_OPTIONS='detect_leaks=0' bin/shtests -p types
#### Regression-testing /home/johno/GitRepos/KornShell/ksh/arch/linux.i386-64/bin/ksh ####
test types begins at 2022-09-23+14:09:00
=================================================================
==300503==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000ff4 at pc 0x556183af45ee bp 0x7fff2a977370 sp 0x7fff2a976b30
READ of size 8 at 0x602000000ff4 thread T0
#0 0x556183af45ed in __asan_memcpy (/home/johno/GitRepos/KornShell/ksh/arch/linux.i386-64/bin/ksh+0x1525ed)
#1 0x556183b5f399 in nv_mktype /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/nvtype.c:1139:6
#2 0x556183c2e60c in nv_setlist /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/name.c:619:9
#3 0x556183cad7e8 in sh_exec /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/xec.c:1051:7
#4 0x556183b46b04 in exfile /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/main.c:604:4
#5 0x556183b42e10 in sh_main /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/main.c:369:2
#6 0x556183b40585 in main /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/pmain.c:41:9
#7 0x7fcd5bb4528f (/usr/lib/libc.so.6+0x2328f) (BuildId: 26c81e7e05ebaf40bac3523b7d76be0cd71fad82)
#8 0x7fcd5bb45349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 26c81e7e05ebaf40bac3523b7d76be0cd71fad82)
#9 0x556183a388d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
0x602000000ff4 is located 0 bytes to the right of 4-byte region [0x602000000ff0,0x602000000ff4)
allocated by thread T0 here:
#0 0x556183af66a9 in __interceptor_malloc (/home/johno/GitRepos/KornShell/ksh/arch/linux.i386-64/bin/ksh+0x1546a9)
#1 0x556183ba9984 in sh_malloc /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/init.c:241:13
#2 0x556183c3e54d in nv_putval /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/name.c:1781:16
#3 0x556183c4af97 in nv_newattr /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/name.c:3008:5
#4 0x556183d4b8ae in setall /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/bltins/typeset.c:954:7
#5 0x556183d511ae in b_typeset /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/bltins/typeset.c:567:9
#6 0x556183cb09a7 in sh_exec /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/xec.c:1261:21
#7 0x556183cb8c44 in sh_exec /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/xec.c:1944:4
#8 0x556183c2cfb2 in nv_setlist /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/name.c:523:5
#9 0x556183cad7e8 in sh_exec /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/xec.c:1051:7
#10 0x556183b46b04 in exfile /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/main.c:604:4
#11 0x556183b42e10 in sh_main /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/main.c:369:2
#12 0x556183b40585 in main /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/pmain.c:41:9
#13 0x7fcd5bb4528f (/usr/lib/libc.so.6+0x2328f) (BuildId: 26c81e7e05ebaf40bac3523b7d76be0cd71fad82)
Thanks for finding and isolating that diff!
OK, I don't understand what's going on at all, except that _Align_
seems to be a dummy struct that is used to calculate alignment offsets in nv_datasize()
via the alignof
macro. And I've noticed that the entries added in the 2012-05-15 diff do not match the pattern of the pre-existing entries.
The _c members are all of type char. And none of the _d members except pointer
are pointers, but the new _dint32_t
member is a pointer. Which does not match the size of int32_t
which is actually what's being queried on the line s = sizeof(int32_t);
.
So, the following patch makes the new dummy struct entries match the pattern, and just like that, the crash seems to be gone.
diff --git a/src/cmd/ksh93/sh/nvtype.c b/src/cmd/ksh93/sh/nvtype.c
index 00f5b6cda..e7e43d98b 100644
--- a/src/cmd/ksh93/sh/nvtype.c
+++ b/src/cmd/ksh93/sh/nvtype.c
@@ -112,8 +112,8 @@ typedef struct
short _dshort;
char _cpointer;
char *_dpointer;
- int32_t _cint32_t;
- int32_t *_dint32_t;
+ char _cint32_t;
+ int32_t _dint32_t;
} _Align_;
#define alignof(t) ((char*)&((_Align_*)0)->_d##t-(char*)&((_Align_*)0)->_c##t)
There is another inconsistency. Short integers (typeset -si
) are typed in C as int16_t
, not short
. On most (all?) current systems those are the same size, but it's not guaranteed.
Plus, if short
and long
are no longer used for calculating alignment we can delete those entries from the _Align_
struct.
So here is a slightly more comprehensive patch:
diff --git a/src/cmd/ksh93/sh/nvtype.c b/src/cmd/ksh93/sh/nvtype.c
index 00f5b6cda..d273d6455 100644
--- a/src/cmd/ksh93/sh/nvtype.c
+++ b/src/cmd/ksh93/sh/nvtype.c
@@ -106,14 +106,12 @@ typedef struct
float _dfloat;
char _cSflong_t;
Sflong_t _dSflong_t;
- char _clong;
- long _dlong;
- char _cshort;
- short _dshort;
+ char _cint32_t;
+ int32_t _dint32_t;
+ char _cint16_t;
+ int16_t _dint16_t;
char _cpointer;
char *_dpointer;
- int32_t _cint32_t;
- int32_t *_dint32_t;
} _Align_;
#define alignof(t) ((char*)&((_Align_*)0)->_d##t-(char*)&((_Align_*)0)->_c##t)
@@ -169,8 +167,8 @@ size_t nv_datasize(Namval_t *np, size_t *offset)
}
else if(nv_isattr(np, NV_SHORT))
{
- a = alignof(short);
- s = sizeof(short);
+ a = alignof(int16_t);
+ s = sizeof(int16_t);
}
else
{
Fix confirmed by the original bug reporter.
Original report on comp.unix.shell (Usenet)
Minimal reproducer:
This segfaults on the second
job.set_pos
call. To trigger the bug, the fist member ofJob_t
must be a short integer type (including an enum type, which is just a short unsigned integer with syntactic sugar). In addition, that short integer type must be the first-listed member; if it is moved to the second position, the bug vanishes.The stack trace (below) tells me that it crashes due to an invalid pointer on line 603 in nvdisc.c. Somehow, one of the pointers in the
bnames
array became invalid.