Fixture 111
self referential struct
C · 1 functions · 4 lanes · 2 of 4 function-lanes behave identically
2 of 4 lanes have a function that returns a different result after decompilation: clang-O2 (0/1), gcc-O0 (0/1).
A struct containing a pointer to its own type. The nodes live in a caller-owned array and are linked by real addresses, so traversal is a chain of dependent loads that must terminate on the recovered null test.
#include <stdint.h>
/* A struct containing a pointer to its own type. The nodes live in a
* caller-owned array and are linked by real addresses, so traversal is a chain
* of dependent loads that must terminate on the recovered null test. */
struct Node {
int32_t value;
struct Node *next;
};
#define NODE_MAX 8
__attribute__((noinline)) int32_t
link_and_sum(int32_t *values, int32_t count) {
struct Node nodes[NODE_MAX];
struct Node *cursor;
int32_t index;
int32_t total = 0;
int32_t visited = 0;
if (values == 0 || count < 0 || count > NODE_MAX) {
return -1;
}
for (index = 0; index < count; ++index) {
nodes[index].value = values[index];
nodes[index].next = (index + 1 < count) ? &nodes[index + 1] : 0;
}
for (cursor = (count > 0) ? &nodes[0] : 0; cursor != 0;
cursor = cursor->next) {
total += cursor->value;
visited += 1;
if (visited > NODE_MAX) {
return -2;
}
}
return total * 10 + visited;
} Recovered C
Generated by glaurung decompile --style decbench at b47f6b43.
baseline.json records the result after recompiling the C and calling it beside the
original with seeded inputs.
clang -O2
0/1link_and_sum fail 153 lines
// glaurung: link_and_sum @ 0x1100
typedef struct Node Node;
int32_t link_and_sum(int32_t * arg0, int32_t arg1) {
Node * cursor;
int index;
int total;
int visited;
long local_10;
int local_18;
long local_20;
int local_28;
long local_30;
int local_38;
long local_40;
int local_48;
long local_50;
int local_58;
long local_60;
int local_68;
long local_70;
int local_78;
long local_8;
long local_80;
int local_88;
long ret;
long rsp;
long var4;
long var47;
long var5;
long var50;
long var53;
long var56;
long var59;
long var6;
long var62;
long var65;
long var9;
rsp = (rsp - 8);
local_8 = ret;
ret = 0xffffffff;
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return ret;
}
if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
// x86-64 epilogue: tear down frame
return ret;
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
var4 = 0;
var5 = 0;
L_12c4: ;
var6 = (unsigned long)((unsigned int)((var5 + (var5 * 4))));
return (unsigned int)((var4 + (var6 * 2)));
}
local_88 = *(int *)(((long)arg0));
var9 = 0;
local_80 = (((unsigned long)((unsigned long)((unsigned int)(arg1))) < (unsigned long)(2)) ? 0 : (rsp - 112));
if (((unsigned long)((unsigned int)(arg1)) != 1)) {
local_78 = *(int *)(((long)arg0 + 0x4));
local_70 = (((unsigned long)(3) <= (unsigned long)((unsigned long)((unsigned int)(arg1)))) ? (rsp - 96) : 0);
if (((unsigned long)((unsigned int)(arg1)) != 2)) {
local_68 = *(int *)(((long)arg0 + 0x8));
local_60 = (((unsigned long)(4) <= (unsigned long)((unsigned long)((unsigned int)(arg1)))) ? (rsp - 80) : 0);
if (((unsigned long)((unsigned int)(arg1)) != 3)) {
local_58 = *(int *)(((long)arg0 + 0xc));
local_50 = (((unsigned long)(5) <= (unsigned long)((unsigned long)((unsigned int)(arg1)))) ? (rsp - 64) : 0);
if (((unsigned long)((unsigned int)(arg1)) != 4)) {
local_48 = *(int *)(((long)arg0 + 0x10));
local_40 = (((unsigned long)(6) <= (unsigned long)((unsigned long)((unsigned int)(arg1)))) ? (rsp - 48) : 0);
if (((unsigned long)((unsigned int)(arg1)) != 5)) {
local_38 = *(int *)(((long)arg0 + 0x14));
local_30 = (((unsigned long)(7) <= (unsigned long)((unsigned long)((unsigned int)(arg1)))) ? (rsp - 32) : 0);
if (((unsigned long)((unsigned int)(arg1)) != 6)) {
local_28 = *(int *)(((long)arg0 + 0x18));
local_20 = (((unsigned long)(8) <= (unsigned long)((unsigned long)((unsigned int)(arg1)))) ? (rsp - 16) : 0);
if (((unsigned long)((unsigned int)(arg1)) != 7)) {
local_18 = *(int *)(((long)arg0 + 0x1c));
local_10 = (((unsigned long)(9) <= (unsigned long)((unsigned long)((unsigned int)(arg1)))) ? rsp : 0);
}
}
}
}
}
}
}
var4 = 0;
var5 = var9;
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
var6 = (unsigned long)((unsigned int)((var5 + (var5 * 4))));
// x86-64 epilogue: tear down frame
return (unsigned int)((var4 + (var6 * 2)));
}
var5 = (unsigned long)((unsigned int)(local_88));
var47 = local_80;
if ((local_80 == 0)) {
var4 = 1;
goto L_12c4;
} else {
var5 = (unsigned long)((unsigned int)((var5 + *(int *)((var47)))));
var50 = *(long *)((var47 + 0x8));
if ((var50 == 0)) {
var4 = 2;
goto L_12c4;
} else {
var5 = (unsigned long)((unsigned int)((var5 + *(int *)((var50)))));
var53 = *(long *)((var50 + 0x8));
if ((var53 == 0)) {
var4 = 3;
goto L_12c4;
} else {
var5 = (unsigned long)((unsigned int)((var5 + *(int *)((var53)))));
var56 = *(long *)((var53 + 0x8));
if ((var56 == 0)) {
var4 = 4;
goto L_12c4;
} else {
var5 = (unsigned long)((unsigned int)((var5 + *(int *)((var56)))));
var59 = *(long *)((var56 + 0x8));
if ((var59 == 0)) {
var4 = 5;
goto L_12c4;
} else {
var5 = (unsigned long)((unsigned int)((var5 + *(int *)((var59)))));
var62 = *(long *)((var59 + 0x8));
if ((var62 == 0)) {
var4 = 6;
goto L_12c4;
} else {
var5 = (unsigned long)((unsigned int)((var5 + *(int *)((var62)))));
var65 = *(long *)((var62 + 0x8));
if ((var65 == 0)) {
var4 = 7;
goto L_12c4;
} else {
ret = 0xfffffffe;
if ((*(long *)((var65 + 0x8)) != 0)) {
// x86-64 epilogue: tear down frame
return ret;
}
var5 = (unsigned long)((unsigned int)((var5 + *(int *)((var65)))));
var4 = 8;
goto L_12c4;
}
}
}
}
}
}
}
// x86-64 epilogue: tear down frame
return ret;
} gcc -O0
0/1link_and_sum fail 81 lines
// glaurung: link_and_sum @ 0x1119
typedef struct Node Node;
int32_t link_and_sum(int32_t * arg0, int32_t arg1) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
int total;
int visited;
int index;
Node * cursor;
long local_8;
unsigned char local_90[128];
long rbp;
long ret;
long rsp;
int var15;
long var23;
void * var30;
int var39;
rsp = (rsp - 8);
rbp = rsp;
rsp = (rsp - 192);
local_8 = (long)(0x28);
total = 0;
visited = 0;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8))) {
goto L_117e;
}
}
}
ret = 0xffffffff;
goto L_12a1;
L_117e: ;
index = 0;
goto L_1214;
L_118d: ;
*(int *)(((((long)(index) << 4) + rbp) - 144)) = arg0[(long)(index)];
var15 = ((unsigned int)(index) + 1);
if (((((unsigned int)(arg1) == (unsigned int)(var15)) | (arg1 < var15)) == 0)) {
var23 = (long)((((long)((int)(((unsigned long)((unsigned int)(index)) + 1))) << 4) + &local_90[0]));
goto L_11f3;
}
var23 = 0;
L_11f3: ;
*(long *)(((((long)(index) << 4) + rbp) - 136)) = var23;
index = (index + 1);
L_1214: ;
if ((index < arg1)) {
goto L_118d;
}
if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0)) {
var30 = &local_90[0];
goto L_123d;
}
var30 = (void *)(0);
L_123d: ;
cursor = var30;
goto L_127e;
L_1246: ;
total = (total + (unsigned int)(*(int *)((long)cursor)));
visited = (visited + 1);
if (((((unsigned long)((unsigned int)(visited)) == 8) | ((long)(visited) < 8)) == 0)) {
ret = 0xfffffffe;
goto L_12a1;
}
cursor = (Node *)(*(long *)(((long)cursor + 0x8)));
L_127e: ;
if ((cursor != 0)) {
goto L_1246;
}
var39 = ((unsigned int)(((unsigned long)((unsigned int)(total)) << 2)) + (unsigned int)(total));
ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(visited)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var39)) + (unsigned long)((unsigned int)(var39))))))));
L_12a1: ;
if ((local_8 == 0x28)) {
// x86-64 epilogue: restore rbp
return ret;
}
__stack_chk_fail();
// x86-64 epilogue: restore rbp
return ret;
} clang -O0
1/1link_and_sum pass 69 lines
// glaurung: link_and_sum @ 0x1100
typedef struct Node Node;
__attribute__((no_stack_protector)) int32_t link_and_sum(int32_t * arg0, int32_t arg1) {
int total;
int visited;
int index;
unsigned char cursor[16];
int local_4;
unsigned char local_a0[128];
long local_c0;
void * local_c8;
total = 0;
visited = 0;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8))) {
goto L_114e;
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_114e: ;
index = 0;
L_1158: ;
if ((arg1 <= index)) {
goto L_1206;
}
*(int *)((&local_a0[0] + ((long)(index) << 4))) = arg0[(long)(index)];
if (((long)((int)(((unsigned long)((unsigned int)(index)) + 1))) < (long)(arg1))) {
local_c0 = (long)((&local_a0[0] + ((long)((int)(((unsigned long)((unsigned int)(index)) + 1))) << 4)));
goto L_11d2;
}
local_c0 = 0;
goto L_11d2;
L_11d2: ;
*(long *)(((&local_a0[0] + ((long)(index) << 4)) + 8)) = local_c0;
index = ((unsigned int)(index) + 1);
goto L_1158;
L_1206: ;
if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0)) {
local_c8 = &local_a0[0];
goto L_1231;
}
local_c8 = (void *)(0);
goto L_1231;
L_1231: ;
*(long *)(&cursor[0]) = (long)((long)local_c8);
L_123f: ;
if ((*(long *)(&cursor[0]) == 0)) {
goto L_12a6;
}
total = ((unsigned int)(*(int *)(*(long *)(&cursor[0]))) + total);
visited = ((unsigned int)(visited) + 1);
if (((((unsigned long)((unsigned int)(visited)) == 8) | ((long)(visited) < 8)) == 0)) {
local_4 = -2;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
goto L_128f;
L_128f: ;
*(long *)(&cursor[0]) = *(long *)((*(long *)(&cursor[0]) + 8));
goto L_123f;
L_12a6: ;
local_4 = ((total * 10) + visited);
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} gcc -O2
1/1link_and_sum pass 73 lines
// glaurung: link_and_sum @ 0x1120
typedef struct Node Node;
int32_t link_and_sum(int32_t * arg0, int32_t arg1) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
Node * cursor;
int visited;
int index;
int total;
long local_10;
unsigned char local_98[128];
long ret;
long var12;
long var13;
long var14;
long var22;
int var23;
long var6;
long var8;
long var9;
local_10 = (long)(0x28);
if ((arg0 == 0)) {
L_1204: ;
ret = 0xffffffff;
} else {
if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
goto L_1204;
} else {
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
ret = 0;
} else {
var6 = (unsigned long)((unsigned int)((arg1 - 1)));
var8 = var6;
var9 = (long)(((long)arg0 + (var6 * 4)));
var12 = (long)((&local_98[0] + 16));
*(int *)((var12 - 0x10)) = *(int *)(((long)arg0));
if (((long)arg0 != var9)) {
var13 = (long)arg0;
while ((var13 != var9)) {
var14 = (unsigned long)((unsigned int)(*(int *)((var13 + 0x4))));
var13 = (var13 + 4);
*(long *)((var12 - 0x8)) = var12;
var12 = (var12 + 16);
*(int *)((var12 - 0x10)) = var14;
}
}
*(long *)((&local_98[0] + (((long)((int)(var8)) << 4) + 8))) = 0;
cursor = (Node *)&local_98[0];
visited = 1;
var22 = (unsigned long)((unsigned int)(*(int *)(&local_98[0])));
L_11b8: ;
while (1) {
cursor = (Node *)(*(long *)(((long)cursor + 0x8)));
if ((cursor == 0)) {
break;
}
var23 = (visited + 1);
visited = (unsigned long)((unsigned int)(var23));
var22 = (unsigned long)((unsigned int)((var22 + *(int *)(((long)cursor)))));
if (((unsigned long)((unsigned int)(var23)) != 9)) {
goto L_11b8;
} else {
ret = 0xfffffffe;
}
if ((local_10 != 0x28)) {
__stack_chk_fail();
}
return ret;
}
ret = (unsigned long)((unsigned int)((visited + ((unsigned long)((unsigned int)((var22 + (var22 * 4)))) * 2))));
}
}
}
}