From d9d3c2af206d1dc97d4a08c791cc28ddbbe2d76e Mon Sep 17 00:00:00 2001 From: Cody Boone Ferguson <53008573+xexyl@users.noreply.github.com> Date: Tue, 2 May 2023 09:45:30 -0700 Subject: [PATCH] More progress with 2011/richards in macOS I have found a problem that shows itself in both linux and macOS. In linux it happens with both 32-bit and 64-bit but the sizes are naturally different. It does not crash in linux however where it does in macOS. I changed some variable types a bit as well but this still does not fix it with macOS though they types changed are more consistent with what they are used as. The bugs.md has more information on what I discovered (noted above) - an overflow. More will have to be done on this another time in order to get it to work with macOS. --- 2011/richards/Makefile | 4 +-- 2011/richards/richards.c | 18 +++++----- bugs.md | 76 +++++++++++++++++++++++++++++++++------- 3 files changed, 74 insertions(+), 24 deletions(-) diff --git a/2011/richards/Makefile b/2011/richards/Makefile index f7164801f..1ead51cb3 100644 --- a/2011/richards/Makefile +++ b/2011/richards/Makefile @@ -61,11 +61,11 @@ CDEFINE= # Include files that are needed to compile # -CINCLUDE= -include stdlib.h -include string.h -include stdio.h -include ctype.h +CINCLUDE= -include stdlib.h -include string.h -include stdio.h -include ctype.h -include sys/mman.h -include setjmp.h # Optimization # -OPT= -O3 +OPT= # Default flags for ANSI C compilation # diff --git a/2011/richards/richards.c b/2011/richards/richards.c index 40a4fddb8..744d32f9b 100644 --- a/2011/richards/richards.c +++ b/2011/richards/richards.c @@ -24,11 +24,11 @@ #define H 9<<16 #define I case #define J(i) calloc(i,1) -#define W(c) e=(k*)memcpy(e,x[(u)c],y[(u)c])+y[(u)c]; +#define W(c) e=(o*)memmove(e,x[(u)c],y[(u)c])+y[(u)c]; #define N break; I q char k; q void o; -q int u; +q unsigned long u; q o(*f) (vo o *); q struct { u *a, **R, *m, h, c; @@ -43,7 +43,7 @@ u sk[H]; k *w; o *x[H]; u y[H]; -k *j, *e; +f *j, *e; u l=256; o g(u v) { @@ -123,15 +123,15 @@ o T() o rd(u v) { - k *a = 0, **b = &a, **c = b + 32; + o *a = 0, **b = &a, **c = b + 24; x[v] = w; - for (; b < c && (*b < w || *b > (k *) T || *b == (k *) (long) v); b++); + for (; b < c && (*b < (o *)w || *b > (o *) T || *b == (long) v); b++); if (b == c) { jmp_buf *j = alloca(sizeof(*j)); setjmp(*j); rd(v); } else { - y[v] = *b - w; + y[v] = *b - (o*)w; w = *b; } } @@ -146,7 +146,7 @@ o re(vo k * rec) } F(d) M--; *M /= M[1]; -} F(p) printf("%d\n", *M); +} F(p) printf("%lu\n", *M); } F(x) u n = *M--; if (!S j[n]) @@ -165,7 +165,7 @@ lx(d); o *lib1[] = { T, T, T, T, T } ; o *lib2[] = { T, ld, lp, lx, l1 } ; -u main() +int main() { u i; k *b; @@ -192,7 +192,7 @@ u main() #if NM malloc(H); #else - mmap(NULL, H, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + mmap(NULL, H, -1, MAP_ANON | MAP_PRIVATE, -1, 0); #endif while (b = fgets(malloc(999), 999, stdin)) ((f) K(b, d)) (d); diff --git a/bugs.md b/bugs.md index 28fce88b5..fa27de435 100644 --- a/bugs.md +++ b/bugs.md @@ -1852,27 +1852,77 @@ have an archive or mirror? Please provide us it! Thank you. ## [2011/richards](2011/richards/richards.c) ([README.md](2011/richards/README.md)) ## STATUS: doesn't work with some platforms - please help us fix -This does not appear to work with macOS. We're not sure if this is to do with -the Apple silicon chip or not. At a glance it appears to be that it might be the -function pointers. In particular it seems to crash at: +This does not appear to work with macOS, resulting in a segfault. We're not +sure if this is to do with the Apple silicon chip or not but it seems unlikely. +At first glance it appeared to be that it might be the function pointers. These +were changed a bit and it might have helped a bit but this is not certain +either. What was noticed is that there is an overflow according to `asan`: -```c - W(1) while ((c = *p)) { +``` +==32361==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x00016d368d08 at pc 0x000102b1dcb0 bp 0x00016d368b90 sp 0x00016d368b88 +READ of size 8 at 0x00016d368d08 thread T0 + #0 0x102b1dcac in rd richards.c:128 + #1 0x102b1e1f4 in re richards.c:145 + #2 0x102a7e7e0 in t richards.c:104 + #3 0x102b1f7cc in main richards.c:185 + #4 0x19498ff24 () + +Address 0x00016d368d08 is located in stack of thread T0 at offset 40 in frame + #0 0x102b1dae8 in rd richards.c:125 + + This frame has 1 object(s): + [32, 40) 'a' (line 126) <== Memory access at offset 40 overflows this variable +HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork + (longjmp and C++ exceptions *are* supported) +SUMMARY: AddressSanitizer: stack-buffer-overflow richards.c:128 in rd +Shadow bytes around the buggy address: + 0x00702da8d150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d190: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 +=>0x00702da8d1a0: 00[f3]f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d1b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d1c0: f1 f1 f1 f1 00 f3 f3 f3 00 00 00 00 00 00 00 00 + 0x00702da8d1d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d1e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d1f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb +==32361==ABORTING + ``` -in the `K` function. It's called like this, from main(): +This was reported in both linux as 32-bit and 64-bit and macOS as 64-bit except +that the sizes were different in 32-bit (as expected). The code it is having a +problem with is: ```c - while (b = fgets(malloc(999), 999, stdin)) - ((f) K(b, d)) (d); + o *a = 0, **b = &a, **c = b + 24; + x[v] = w; + for (; b < c && (*b < (o *)w || *b > (o *) T || *b == (long) v); b++); + ``` -But what is curious is that it seems to have different problems depending on the -macros defined. In an attempt to get it to work the `mmap()` call was changed to -allow for exec and read and write (which might be a problem in such a -combination) but this only works in linux (it already did work in linux, -however, so this doesn't help much). +where `o` is a `void`. Do you have a fix? We welcome it!