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.
This commit is contained in:
Cody Boone Ferguson committed 2023-05-08 04:36:28 -07:00
1 parent 33a798c8cd
commit be793cc328
4 files changed
+152 -51

No files matched your search

+2 -2
View File
@@ -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
#
+5 -2
View File
@@ -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:
+16 -12
View File
@@ -3,7 +3,10 @@
#endif
#include<setjmp.h>
#include<stdio.h>
#if !NM
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#ifndef NM
#include<sys/mman.h>
#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);
+129 -35
View File
@@ -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 (<unknown module>)
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 (<unknown module>)
==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 (<unknown module>)
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
<https://github.com/GregorR/ioccc2011>.
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