Fixture 42
rpn evaluator
C · 1 functions · 4 lanes · 3 of 4 function-lanes behave identically
One lane has a function that returns a different result after decompilation: clang-O2 (0/1).
Reverse-Polish evaluation over an explicit operand stack. Operators arrive as bytes and dispatch through a switch; division guards zero and the INT32_MIN / -1 overflow case, which is a real correctness trap.
#include <stdint.h>
/* Reverse-Polish evaluation over an explicit operand stack. Operators arrive
* as bytes and dispatch through a switch; division guards zero and the
* INT32_MIN / -1 overflow case, which is a real correctness trap. */
#define RPN_MAX 16
__attribute__((noinline)) int32_t
rpn_evaluate(const uint8_t *tokens, const int32_t *operands, int32_t length,
int32_t *result) {
int32_t stack[RPN_MAX];
int32_t depth = 0;
int32_t index;
if (tokens == 0 || operands == 0 || result == 0 || length < 0 ||
length > RPN_MAX) {
return -1;
}
for (index = 0; index < length; ++index) {
uint8_t token = tokens[index];
if (token == (uint8_t)'#') {
if (depth >= RPN_MAX) {
return -2;
}
stack[depth] = operands[index];
depth += 1;
continue;
}
if (depth < 2) {
return -3;
}
{
int32_t right = stack[depth - 1];
int32_t left = stack[depth - 2];
int32_t value;
depth -= 2;
switch (token) {
case '+':
value = (int32_t)((uint32_t)left + (uint32_t)right);
break;
case '-':
value = (int32_t)((uint32_t)left - (uint32_t)right);
break;
case '*':
value = (int32_t)((uint32_t)left * (uint32_t)right);
break;
case '/':
if (right == 0 || (left == (-2147483647 - 1) && right == -1)) {
return -4;
}
value = left / right;
break;
default:
return -5;
}
stack[depth] = value;
depth += 1;
}
}
if (depth != 1) {
return -6;
}
*result = stack[0];
return depth;
} 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/1rpn_evaluate fail 82 lines
// glaurung: rpn_evaluate @ 0x1100
__attribute__((no_stack_protector)) int32_t rpn_evaluate(const uint8_t * arg0, const int32_t * arg1, int32_t arg2, int32_t * arg3) {
int depth;
int index;
unsigned char token;
int left;
int right;
int value;
unsigned char local_58[88];
long ret;
long var0;
long var10;
long var17;
long var3;
long var7;
// x86-64 prologue: save callee registers, frame 24 bytes
ret = 0xffffffff;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
// x86-64 epilogue: restore callee registers
return ret;
}
if ((arg0 == 0)) {
// x86-64 epilogue: restore callee registers
return ret;
}
if ((arg1 == 0)) {
// x86-64 epilogue: restore callee registers
return ret;
}
if ((arg3 == 0)) {
// x86-64 epilogue: restore callee registers
return ret;
}
ret = 0xfffffffa;
if (((unsigned long)((unsigned int)(arg2)) == 0)) {
// x86-64 epilogue: restore callee registers
return ret;
}
var0 = (unsigned long)((unsigned int)(arg2));
var3 = 0x2000;
depth = 0;
var7 = 0;
goto L_1165;
L_1155: ;
index = (var7 + 1);
depth = (unsigned long)((unsigned int)(var10));
var7 = (unsigned long)((unsigned int)(index));
if ((var0 == index)) {
goto L_11f0;
}
L_1165: ;
token = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + var7))));
if (((unsigned long)((unsigned char)((token & 255))) == 35)) {
if (((((unsigned long)((unsigned int)(depth)) == 15) | ((long)(depth) < 15)) == 0)) {
// x86-64 epilogue: restore callee registers
return 0xfffffffe;
}
*(int *)((&local_58[0] + ((long)(depth) * 4))) = *(int *)(((long)arg1 + var7 * 4));
var10 = (unsigned long)((unsigned int)((depth + 1)));
goto L_1155;
}
if (((long)(depth) < 2)) {
// x86-64 epilogue: restore callee registers
return 0xfffffffd;
}
ret = 0xfffffffb;
var17 = ((((unsigned long)(token) & 255) - 42) & 255);
if (((unsigned long)(5) < (unsigned long)((unsigned long)((unsigned char)((var17 & 255)))))) {
// x86-64 epilogue: restore callee registers
return ret;
}
/* unrecovered indirect jump through ((long)((int)(*(int *)((var3 + ((unsigned int)((unsigned char)((var17 & 255))) * 4))))) + var3) */
L_11f0: ;
ret = 0xfffffffa;
if (((unsigned long)((unsigned int)(var10)) != 1)) {
// x86-64 epilogue: restore callee registers
return ret;
}
*(int *)(((long)arg3)) = *(int *)(&local_58[0]);
// x86-64 epilogue: restore callee registers
return 1;
} clang -O0
1/1rpn_evaluate pass 131 lines
// glaurung: rpn_evaluate @ 0x1100
__attribute__((no_stack_protector)) int32_t rpn_evaluate(const uint8_t * arg0, const int32_t * arg1, int32_t arg2, int32_t * arg3) {
int depth;
int index;
unsigned char token;
int right;
int left;
int value;
int local_4;
unsigned char local_70[64];
long local_90;
int var27;
// x86-64 prologue: save rbp, frame 16 bytes
depth = 0;
if ((arg0 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if ((arg1 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if ((arg3 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((long)(arg2) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
index = 0;
L_1166: ;
while (1) {
if ((arg2 <= index)) {
goto L_12e7;
}
token = arg0[index];
if (((unsigned long)((unsigned long)(token)) == 35)) {
if ((16 <= (long)(depth))) {
goto L_1197;
}
*(int *)((&local_70[0] + ((long)(depth) * 4))) = arg1[(long)(index)];
depth = ((unsigned int)(depth) + 1);
goto L_12d9;
}
if (((long)(depth) < 2)) {
goto L_11ce;
}
right = *(int *)((&local_70[0] + ((long)((int)(((unsigned long)((unsigned int)(depth)) - 1))) * 4)));
left = *(int *)((&local_70[0] + ((long)((int)(((unsigned long)((unsigned int)(depth)) - 2))) * 4)));
depth = ((unsigned int)(depth) - 2);
var27 = ((unsigned int)(token) - 42);
local_90 = (unsigned int)(var27);
if (((((unsigned long)((unsigned long)((unsigned int)(var27))) < (unsigned long)(5)) | ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var27)) - 5))) == 0)) == 0)) {
goto L_12b6;
}
switch (local_90) {
case 0:
goto L_125c;
case 1:
goto L_1234;
case 3:
goto L_1248;
case 5:
goto L_1271;
default:
goto L_12b6;
}
L_1234: ;
value = ((unsigned int)(left) + right);
goto L_12c2;
L_1248: ;
value = ((unsigned int)(left) - right);
goto L_12c2;
L_125c: ;
value = ((unsigned int)(left) * right);
goto L_12c2;
L_1271: ;
if (((unsigned long)((unsigned int)(right)) == 0)) {
goto L_1295;
}
if (((unsigned long)((unsigned int)(left)) == 0x80000000)) {
if (((unsigned long)((unsigned int)(right)) == 0xffffffff)) {
goto L_1295;
}
}
value = ((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(left))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(left)))) / (int)(right)));
goto L_12c2;
L_12c2: ;
*(int *)((&local_70[0] + ((long)(depth) * 4))) = value;
depth = ((unsigned int)(depth) + 1);
L_12d9: ;
index = ((unsigned int)(index) + 1);
goto L_1166;
}
L_1197: ;
local_4 = -2;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_11ce: ;
local_4 = -3;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_1295: ;
local_4 = -4;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_12b6: ;
local_4 = -5;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_12e7: ;
if (((unsigned long)((unsigned int)(depth)) != 1)) {
local_4 = -6;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
*(int *)((long)arg3) = *(int *)(&local_70[0]);
local_4 = depth;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} gcc -O0
1/1rpn_evaluate pass 115 lines
// glaurung: rpn_evaluate @ 0x1119
int32_t rpn_evaluate(const uint8_t * arg0, const int32_t * arg1, int32_t arg2, int32_t * arg3) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
int depth;
int index;
unsigned char token;
int right;
int left;
int value;
unsigned char local_50[64];
long local_8;
long ret;
int var26;
local_8 = (long)(0x28);
depth = 0;
if ((arg0 != 0)) {
if ((arg1 != 0)) {
if ((arg3 != 0)) {
if ((0 <= (long)(arg2))) {
if ((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16))) {
goto L_1187;
}
}
}
}
}
ret = 0xffffffff;
goto L_12ce;
L_1187: ;
index = 0;
goto L_12a3;
L_1193: ;
token = arg0[index];
if ((token == 35)) {
if (((((unsigned long)((unsigned int)(depth)) == 15) | ((long)(depth) < 15)) == 0)) {
ret = 0xfffffffe;
goto L_12ce;
}
*(int *)((&local_50[0] + ((long)(depth) * 4))) = arg1[(long)(index)];
depth = (depth + 1);
goto L_129f;
}
if (((((unsigned long)((unsigned int)(depth)) == 1) | ((long)(depth) < 1)) != 0)) {
ret = 0xfffffffd;
goto L_12ce;
}
right = *(int *)((&local_50[0] + ((long)((int)(((unsigned long)((unsigned int)(depth)) - 1))) * 4)));
left = *(int *)((&local_50[0] + ((long)((int)(((unsigned long)((unsigned int)(depth)) - 2))) * 4)));
depth = (depth - 2);
var26 = (unsigned int)(token);
if (((unsigned long)((unsigned long)(token)) == 47)) {
goto L_1260;
}
if (((((unsigned long)((unsigned int)(var26)) == 47) | ((long)((int)(var26)) < 47)) == 0)) {
goto L_1288;
}
if (((unsigned long)((unsigned int)(var26)) != 45)) {
if (((((unsigned long)((unsigned int)(var26)) == 45) | ((long)((int)(var26)) < 45)) == 0)) {
goto L_1288;
}
if (((unsigned long)((unsigned int)(var26)) == 42)) {
goto L_1252;
}
if (((unsigned long)((unsigned int)(var26)) != 43)) {
goto L_1288;
}
value = ((unsigned int)(right) + (unsigned int)(left));
goto L_128f;
}
value = ((unsigned int)(left) - (unsigned int)(right));
goto L_128f;
L_1252: ;
value = ((unsigned int)(right) * (unsigned int)(left));
goto L_128f;
L_1260: ;
if (((unsigned long)((unsigned int)(right)) != 0)) {
if (((unsigned long)((unsigned int)(left)) != 0x80000000)) {
goto L_127c;
}
if (((unsigned long)((unsigned int)(right)) != 0xffffffff)) {
goto L_127c;
}
}
ret = 0xfffffffc;
goto L_12ce;
L_127c: ;
value = ((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(left))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(left)))) / (int)(right)));
goto L_128f;
L_1288: ;
ret = 0xfffffffb;
goto L_12ce;
L_128f: ;
*(int *)((&local_50[0] + ((long)(depth) * 4))) = value;
depth = (depth + 1);
L_129f: ;
index = (index + 1);
L_12a3: ;
if ((index < arg2)) {
goto L_1193;
}
if (((unsigned long)((unsigned int)(depth)) != 1)) {
ret = 0xfffffffa;
goto L_12ce;
}
*(int *)((long)arg3) = *(int *)(&local_50[0]);
ret = (unsigned long)((unsigned int)(depth));
L_12ce: ;
if ((local_8 == 0x28)) {
// x86-64 epilogue: restore rbp
return ret;
}
__stack_chk_fail();
// x86-64 epilogue: restore rbp
return ret;
} gcc -O2
1/1rpn_evaluate pass 140 lines
// glaurung: rpn_evaluate @ 0x1120
int32_t rpn_evaluate(const uint8_t * arg0, const int32_t * arg1, int32_t arg2, int32_t * arg3) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
int depth;
int index;
int right;
int left;
unsigned char token;
int value;
long cf_14;
long local_10;
unsigned char local_58[64];
long ret;
long t152;
long var15;
long var20;
long var25;
long var27;
long var28;
long var3;
int * var4;
long var8;
long zf_14;
local_10 = (long)(0x28);
if ((arg0 != 0)) {
var3 = (long)arg1;
if ((arg1 != 0)) {
var4 = (int *)arg3;
if ((arg3 != 0)) {
if (((unsigned long)((unsigned long)((unsigned int)(arg2))) <= (unsigned long)(16))) {
goto L_1178;
}
}
}
}
ret = 0xffffffff;
L_1158: ;
if ((local_10 != 0x28)) {
goto L_126e;
}
// x86-64 epilogue: tear down frame
return ret;
L_1178: ;
if (((unsigned long)((unsigned int)(arg2)) == 0)) {
goto L_1264;
}
var8 = (unsigned long)((unsigned int)((arg2 - 1)));
depth = 0;
index = 0;
goto L_11d1;
L_1190: ;
if ((((unsigned long)((unsigned int)(depth)) == 1) | ((long)(depth) < 1))) {
goto L_1250;
}
var15 = (unsigned long)((unsigned int)((depth - 1)));
right = (unsigned long)((unsigned int)(*(int *)((&local_58[0] + ((long)((int)(var15)) * 4)))));
var20 = (long)((int)((depth - 2)));
left = (unsigned long)((unsigned int)(*(int *)((&local_58[0] + (var20 * 4)))));
t152 = ((unsigned long)(token) & 255);
zf_14 = ((unsigned long)((unsigned char)(t152)) == 45);
cf_14 = ((unsigned long)((unsigned long)((unsigned char)(t152))) < (unsigned long)(45));
if (((unsigned long)((unsigned char)(t152)) == 45)) {
goto L_1228;
}
if (((cf_14 | zf_14) == 0)) {
goto L_11f0;
}
if (((unsigned long)((unsigned char)((token & 255))) == 42)) {
goto L_1220;
}
if (((unsigned long)((unsigned char)((token & 255))) != 43)) {
goto L_1210;
}
var25 = (unsigned long)((unsigned int)((left + right)));
L_11bf: ;
*(int *)((&local_58[0] + (var20 * 4))) = var25;
var27 = (unsigned long)((unsigned int)(var15));
L_11c5: ;
var28 = ((unsigned long)((unsigned int)(index)) + 1);
if ((index == var8)) {
goto L_1240;
}
depth = var27;
index = var28;
L_11d1: ;
token = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + index))));
if (((unsigned long)((unsigned char)((token & 255))) != 35)) {
goto L_1190;
}
if (((((unsigned long)((unsigned int)(depth)) == 15) | ((long)(depth) < 15)) == 0)) {
goto L_125a;
}
*(int *)((&local_58[0] + ((long)(depth) * 4))) = *(int *)((var3 + index * 4));
var27 = (unsigned long)((unsigned int)((depth + 1)));
goto L_11c5;
L_11f0: ;
if (((unsigned long)((unsigned char)((token & 255))) != 47)) {
goto L_1210;
}
if (((unsigned long)((unsigned int)(right)) == 0)) {
goto L_122c;
}
if (((unsigned long)((unsigned int)(left)) == 0x80000000)) {
if (((unsigned long)((unsigned int)(right)) == 0xffffffff)) {
goto L_122c;
}
}
var25 = ((int)((((long long)(int)((((unsigned long)((long)(left)) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(left)) / (int)(right)));
goto L_11bf;
L_1210: ;
ret = 0xfffffffb;
goto L_1158;
L_1220: ;
var25 = (unsigned long)((unsigned int)((left * right)));
goto L_11bf;
L_1228: ;
var25 = (unsigned long)((unsigned int)((left - right)));
goto L_11bf;
L_122c: ;
ret = 0xfffffffc;
goto L_1158;
L_1240: ;
if (((unsigned long)((unsigned int)(var27)) != 1)) {
goto L_1264;
}
*(int *)((var4)) = *(int *)(&local_58[0]);
ret = var27;
goto L_1158;
L_1250: ;
ret = 0xfffffffd;
goto L_1158;
L_125a: ;
ret = 0xfffffffe;
goto L_1158;
L_1264: ;
ret = 0xfffffffa;
goto L_1158;
L_126e: ;
__stack_chk_fail();
}