From be793cc3280b6a822d2e4e1228d598eb2e989ebb Mon Sep 17 00:00:00 2001 From: Cody Boone Ferguson <53008573+xexyl@users.noreply.github.com> Date: Mon, 8 May 2023 04:36:28 -0700 Subject: [PATCH] More about 2011/richards and macOS This includes a minor code change. I believe at this point that it's an inherent issue of macOS but I might be wrong. I'll certainly look at this more in the future but I'm going to try and work on the remaining README.md files first. Time will tell how much I succeed. --- 2011/richards/Makefile | 4 +- 2011/richards/README.md | 7 +- 2011/richards/richards.c | 28 ++++--- bugs.md | 164 ++++++++++++++++++++++++++++++--------- 4 files changed, 152 insertions(+), 51 deletions(-) diff --git a/2011/richards/Makefile b/2011/richards/Makefile index 1ead51cb3..3b5f81a82 100644 --- a/2011/richards/Makefile +++ b/2011/richards/Makefile @@ -46,7 +46,7 @@ CWARN= -Wall -Wextra ${CSILENCE} # Compiler standard # -CSTD= -std=gnu11 +CSTD= -std=gnu99 # Compiler bit architecture # @@ -65,7 +65,7 @@ CINCLUDE= -include stdlib.h -include string.h -include stdio.h -include ctype.h # Optimization # -OPT= +OPT= # Default flags for ANSI C compilation # diff --git a/2011/richards/README.md b/2011/richards/README.md index 28fbef457..4fe27cbc5 100644 --- a/2011/richards/README.md +++ b/2011/richards/README.md @@ -15,14 +15,17 @@ make ./richards ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a minor problem +that showed up in both linux and macOS. He notes however that as of this time +this entry does not work with macOS. See [bugs.md](/bugs.md) for more details. +Thank you Cody! + ## Try: ```sh echo '10 9 8 7 6 5 4 3 2 1*p*p*p*p*p*p*p*p*p' | ./richards ``` -NOTE: this entry does not work in macOS. See [bugs.md](/bugs.md) for more -details. ## Judges' remarks: diff --git a/2011/richards/richards.c b/2011/richards/richards.c index 744d32f9b..76013a390 100644 --- a/2011/richards/richards.c +++ b/2011/richards/richards.c @@ -3,7 +3,10 @@ #endif #include #include -#if !NM +#include +#include +#include +#ifndef NM #include #endif #define vo volatile @@ -24,11 +27,11 @@ #define H 9<<16 #define I case #define J(i) calloc(i,1) -#define W(c) e=(o*)memmove(e,x[(u)c],y[(u)c])+y[(u)c]; +#define W(c) e=memmove(e,x[(u)c],y[(u)c])+y[(u)c]; #define N break; I q char k; q void o; -q unsigned long u; +q int u; q o(*f) (vo o *); q struct { u *a, **R, *m, h, c; @@ -43,7 +46,7 @@ u sk[H]; k *w; o *x[H]; u y[H]; -f *j, *e; +f j, e; u l=256; o g(u v) { @@ -59,7 +62,8 @@ f K(k * p, dt d) { k c, n = 0; f r = (f) e; - W(1) while ((c = *p)) { + W(1) + while ((c = *p)) { switch (c) { I '#': while (*++p != 10); @@ -123,9 +127,9 @@ o T() o rd(u v) { - o *a = 0, **b = &a, **c = b + 24; + o *a = 0, **b = &a, **c = b + 32; x[v] = w; - for (; b < c && (*b < (o *)w || *b > (o *) T || *b == (long) v); b++); + for (; b < c && (*b < (o *)w || *b > (o *) T || *b == &v); b++); if (b == c) { jmp_buf *j = alloca(sizeof(*j)); setjmp(*j); @@ -146,7 +150,7 @@ o re(vo k * rec) } F(d) M--; *M /= M[1]; -} F(p) printf("%lu\n", *M); +} F(p) printf("%d\n", *M); } F(x) u n = *M--; if (!S j[n]) @@ -162,8 +166,8 @@ M++; lx(d); } } -o *lib1[] = { T, T, T, T, T } ; -o *lib2[] = { T, ld, lp, lx, l1 } ; +f *lib1[] = { T, T, T, T, T } ; +f *lib2[] = { T, ld, lp, lx, l1 } ; int main() { @@ -189,10 +193,10 @@ int main() S l = (f *) lib2; S r = (f) T; j = e = -#if NM +#ifdef NM malloc(H); #else - mmap(NULL, H, -1, MAP_ANON | MAP_PRIVATE, -1, 0); + (f)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 243b8deb5..0c74f7b21 100644 --- a/bugs.md +++ b/bugs.md @@ -1906,43 +1906,107 @@ tends to result in empty output. 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`: +At first glance it appeared to be that it might be the function pointers or the +fact it is trying to execute code in memory. The function pointers were changed +a bit but this has not helped solve the problem with macOS. A few things that +were noticed depending on `asan` sanitisers specified. With `address` in linux: + ``` -==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 () +richards.c:101:9: runtime error: null pointer passed as argument 2, which is declared to never be null +``` -Address 0x00016d368d08 is located in stack of thread T0 at offset 40 in frame - #0 0x102b1dae8 in rd richards.c:125 +but it actually works. This code is: - This frame has 1 object(s): - [32, 40) 'a' (line 126) <== Memory access at offset 40 overflows this variable +```c + } else + p++; + W(c)} /* LINE 101 */ + } +``` + +Okay but what about argument 2? Well `W` is defined as: + +```c +#define W(c) e=memmove(e,x[(u)c], y[(u)c])+y[(u)c]; +``` + +so it would appear that + +```c +y[(u)c])+y[(u)c] +``` + +(at least in my tired head?) `y[1]` is NULL. But why does it work then? + + +Under macOS (with the arm64 chip) we get: + +``` +UndefinedBehaviorSanitizer:DEADLYSIGNAL +==10834==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0xffffffffffffffff (pc 0x00019f446748 bp 0x00016f353100 sp 0x00016f352b90 T139066) +==10834==The signal is caused by a WRITE memory access. + #0 0x19f446748 in _platform_memmove+0xa8 (libsystem_platform.dylib:arm64e+0x3748) (BuildId: 756cd10d62a032839e57cbaa810c95ac32000000200000000100000000030d00) + #1 0x100c33c2c in main richards.c:202 + #2 0x19f0bff24 () + +==10834==Register values: + x[0] = 0xffffffffffffffff x[1] = 0x0000000100ab18c1 x[2] = 0x00000000000000cf x[3] = 0x0000000000000000 + x[4] = 0x0000000100ab18a1 x[5] = 0x0000000000000001 x[6] = 0x000000000000000a x[7] = 0x0000000000000000 + x[8] = 0x00000001015972b8 x[9] = 0xffffffffffffffff x[10] = 0x0000000000000001 x[11] = 0x00000000000001f0 +x[12] = 0x0000000000000001 x[13] = 0x00000000000003e0 x[14] = 0x0000000000000001 x[15] = 0x0000000000000084 +x[16] = 0x000000019f4466a0 x[17] = 0x00000001ff3ad908 x[18] = 0x0000000000000000 x[19] = 0x0000000100c32a80 +x[20] = 0x00000001017e0000 x[21] = 0x00000001017e1910 x[22] = 0x000000016f353530 x[23] = 0x000000019f13a366 +x[24] = 0x000000016f3534b0 x[25] = 0x0000000000000001 x[26] = 0x0000000000000000 x[27] = 0x0000000000000000 +x[28] = 0x0000000000000000 fp = 0x000000016f353100 lr = 0x0000000100aaf880 sp = 0x000000016f352b90 +UndefinedBehaviorSanitizer can not provide additional info. +SUMMARY: UndefinedBehaviorSanitizer: SEGV (libsystem_platform.dylib:arm64e+0x3748) (BuildId: 756cd10d62a032839e57cbaa810c95ac32000000200000000100000000030d00) in _platform_memmove+0xa8 +==10834==ABORTING +``` + +and naturally it does not work. + +Adding the proper `PROT_WRITE` constant to the `mmap()` call does not seem to +help. Of course with the address this is not surprising so why is a different +address allocated in macOS? Or is it? + +Now with `address` sanitiser both linux and macOS crash at: + +``` +================================================================= +==10983==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x00016f8d5e78 at pc 0x0001005dd910 bp 0x00016f8d5cd0 sp 0x00016f8d5cc8 +READ of size 8 at 0x00016f8d5e78 thread T0 + #0 0x1005dd90c in rd richards.c:132 + #1 0x1005ddf8c in re richards.c:149 + #2 0x1005110a0 in t richards.c:108 + #3 0x1005df72c in main richards.c:189 + #4 0x19f0bff24 () + +Address 0x00016f8d5e78 is located in stack of thread T0 at offset 56 in frame + #0 0x1005dd678 in rd richards.c:129 + + This frame has 2 object(s): + [32, 36) 'v.addr' + [48, 56) 'a' (line 130) <== Memory access at offset 56 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 +SUMMARY: AddressSanitizer: stack-buffer-overflow richards.c:132 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 + 0x00702df3ab70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3ab80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3ab90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3aba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3abb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +=>0x00702df3abc0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 04 f2 00[f3] + 0x00702df3abd0: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3abe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3abf0: 00 00 00 00 f1 f1 f1 f1 00 f3 f3 f3 00 00 00 00 + 0x00702df3ac00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3ac10: 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 + Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 @@ -1959,25 +2023,55 @@ Shadow byte legend (one shadow byte represents 8 application bytes): ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb -==32361==ABORTING - +==10983==ABORTING +/bin/bash: line 1: 10983 Abort trap: 6 ./richards ``` -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: +which corresponds to the code: ```c - o *a = 0, **b = &a, **c = b + 24; +o rd(u v) +{ + o *a = 0, **b = &a, **c = b + 32; x[v] = w; - for (; b < c && (*b < (o *)w || *b > (o *) T || *b == (long) v); b++); + for (; b < c && (*b < (o *)w || *b > (o *) T || *b == &v); b++); /* LINE 132 */ ``` -where `o` is a `void`. +A warning of interest when compiling is: + +``` + +richards.c:169:15: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'o ()' (aka 'void ()') [-Wincompatible-pointer-types] +f *lib1[] = { T, T, T, T, T } ; + +... + +richards.c:170:15: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'o ()' (aka 'void ()') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^ +richards.c:170:18: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'void (volatile dt)' (aka 'void (struct (unnamed at richards.c:36:3) *volatile)') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^~ +richards.c:170:22: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'void (volatile dt)' (aka 'void (struct (unnamed at richards.c:36:3) *volatile)') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^~ +richards.c:170:26: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'void (volatile dt)' (aka 'void (struct (unnamed at richards.c:36:3) *volatile)') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^~ +richards.c:170:30: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'void (volatile dt)' (aka 'void (struct (unnamed at richards.c:36:3) *volatile)') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^~ +``` + +but I'm not sure if this is relevant or not: it might be. + +Finally the author has more about the entry at +. Do you have a fix? We welcome it! + ## [2011/vik](2011/vik/vik.c) ([README.md](2011/vik/README.md)) ## STATUS: INABIAF - please **DO NOT** fix