Fixture 131

obfuscated composite

C · 2 functions · 4 lanes · 8 of 8 function-lanes behave identically

All 4 lanes recompile and return the same results as the original.

An IOCCC-flavoured composition of everything this batch covers: a function-pointer table indexed by a bit trick, a comma-operator loop header, a statement expression, reversed subscripts, and a nested conditional. Dense on purpose, and fully defined throughout.

tests/decompiler_fixtures/src/131_obfuscated_composite.c source
#include <stdint.h>

/* An IOCCC-flavoured composition of everything this batch covers: a
 * function-pointer table indexed by a bit trick, a comma-operator loop header,
 * a statement expression, reversed subscripts, and a nested conditional. Dense
 * on purpose, and fully defined throughout. */

static int32_t twist(int32_t v) { return (int32_t)(((uint32_t)v << 3) ^ 0x9E37u); }
static int32_t fold(int32_t v) { return (int32_t)(((uint32_t)v >> 2) + 0x1234u); }

typedef int32_t (*Stage)(int32_t);
static Stage const STAGES[2] = {twist, fold};

#define PICK(v) ({ int32_t _v = (v); STAGES[(_v & 1)](_v); })

__attribute__((noinline)) int32_t
obfuscated_pipeline(int32_t *state, int32_t count, int32_t seed) {
    int32_t i;
    int32_t acc = seed;
    int32_t last = 0;
    if (state == 0 || count < 0 || count > 16) {
        return -1;
    }
    for (i = 0; i < count; last = acc, acc = PICK(acc), i[state] = acc, ++i) {
        acc ^= (i & 3) ? (i << 1) : ~i;
    }
    return count ? ((count - 1)[state] ^ last) : acc;
}

__attribute__((noinline)) int32_t
nested_conditional_matrix(int32_t a, int32_t b, int32_t c, int32_t d) {
    return (a < b) ? ((c < d) ? ((a < c) ? a : c) : ((a < d) ? a : d))
                   : ((c < d) ? ((b < c) ? b : c) : ((b < d) ? b : d));
}

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 -O0

2/2
nested_conditional_matrix pass 25 lines
// glaurung: nested_conditional_matrix @ 0x1220
int32_t nested_conditional_matrix(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    int local_14;
    int local_1c;
    int local_24;
    int local_2c;
    // x86-64 prologue: save rbp
    if ((arg1 <= arg0)) {
        if ((arg3 <= arg2)) {
            local_2c = ((arg3 <= arg1) ? (unsigned long)((unsigned int)(arg3)) : (unsigned long)((unsigned int)(arg1)));
            return (unsigned int)(local_2c);
        } else {
            local_24 = ((arg2 <= arg1) ? (unsigned long)((unsigned int)(arg2)) : (unsigned long)((unsigned int)(arg1)));
            return (unsigned int)(local_24);
        }
    } else {
        if ((arg3 <= arg2)) {
            local_1c = ((arg3 <= arg0) ? (unsigned long)((unsigned int)(arg3)) : (unsigned long)((unsigned int)(arg0)));
            return (unsigned int)(local_1c);
        } else {
            local_14 = ((arg2 <= arg0) ? (unsigned long)((unsigned int)(arg2)) : (unsigned long)((unsigned int)(arg0)));
            return (unsigned int)(local_14);
        }
    }
}
obfuscated_pipeline pass 50 lines
// glaurung: obfuscated_pipeline @ 0x1100
int32_t obfuscated_pipeline(int32_t * arg0, int32_t arg1, int32_t arg2) {
    extern void fold(void);
    extern void twist(void);
    static void (*STAGES[2])(void) = {
        (void (*)(void))twist,
        (void (*)(void))fold,
    };
    int acc;
    int last;
    int i;
    int _v;
    int local_2c;
    int local_30;
    int local_34;
    int local_4;
    long var23;
    // x86-64 prologue: save rbp, frame 64 bytes
    acc = arg2;
    last = 0;
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (i = 0; (i < arg1); i++) {
        local_30 = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(i)) & 3))) == 0) ? ((unsigned long)((unsigned int)(i)) ^ -1) : ((unsigned long)((unsigned int)(i)) << 1));
        acc = ((unsigned int)(local_30) ^ acc);
        last = acc;
        _v = acc;
        var23 = ((long (*)(long))(STAGES[(long)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(_v)) & 1)))))]))((unsigned long)((unsigned int)(_v)));
        local_2c = var23;
        acc = local_2c;
        arg0[(long)(i)] = acc;
    }
    local_34 = (((unsigned long)((unsigned int)(arg1)) == 0) ? (unsigned long)((unsigned int)(acc)) : ((unsigned long)((unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(arg1)) - 1)))])) ^ (unsigned long)((unsigned int)(last))));
    local_4 = local_34;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

2/2
nested_conditional_matrix pass 15 lines
// glaurung: nested_conditional_matrix @ 0x11a0
int32_t nested_conditional_matrix(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    long var0;
    var0 = (unsigned long)((unsigned int)(arg2));
    if ((arg0 < arg1)) {
        if (((long)(arg3) <= (long)((int)(var0)))) {
            return (unsigned int)((arg0 < arg3) ? arg0 : arg3);
        }
        return (((long)(arg0) < (long)((int)(var0))) ? arg0 : var0);
    }
    if (((long)(arg3) <= (long)((int)(var0)))) {
        return (unsigned int)((arg1 < arg3) ? arg1 : arg3);
    }
    return (((long)(arg1) < (long)((int)(var0))) ? arg1 : var0);
}
obfuscated_pipeline pass 73 lines
// glaurung: obfuscated_pipeline @ 0x1100
__attribute__((no_stack_protector)) int32_t obfuscated_pipeline(int32_t * arg0, int32_t arg1, int32_t arg2) {
    extern void fold(void);
    extern void twist(void);
    static void (*STAGES[2])(void) = {
        (void (*)(void))twist,
        (void (*)(void))fold,
    };
    int i;
    int _v;
    int acc;
    int last;
    unsigned char local_38[56];
    long rbp;
    long ret;
    long var0;
    long var1;
    long var12;
    long var13;
    long var14;
    long var16;
    long var17;
    long var2;
    long var21;
    long var25;
    long var3;
    long var30;
    long var4;
    long var5;
    *(long *)((&local_38[0] + 48)) = rbp;
    *(long *)((&local_38[0] + 40)) = var0;
    *(long *)((&local_38[0] + 32)) = var1;
    *(long *)((&local_38[0] + 24)) = var2;
    *(long *)((&local_38[0] + 16)) = var3;
    *(long *)((&local_38[0] + 8)) = var4;
    *(long *)(&local_38[0]) = ret;
    var5 = 0xffffffff;
    if ((arg0 == 0)) {
        ret = (unsigned long)((unsigned int)(var5));
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var5);
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        ret = (unsigned long)((unsigned int)(var5));
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var5);
    }
    var12 = (unsigned long)((unsigned int)(arg2));
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        var5 = (unsigned long)((unsigned int)(var12));
    } else {
        var13 = (long)arg0;
        *(long *)(&local_38[0]) = (unsigned long)((unsigned int)(arg1));
        var14 = (unsigned long)((unsigned int)(arg1));
        var16 = 0;
        var17 = 0xffffffff;
        i = 0;
        var21 = var12;
        do {
            var25 = (unsigned long)((unsigned int)(((((unsigned long)((unsigned char)((i & 3))) == 0) ? var17 : (unsigned long)((unsigned int)(var16))) ^ var21)));
            var30 = ((long (*)(long))(STAGES[(unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var25)) & 1)))]))((unsigned long)((unsigned int)(var25)));
            *(int *)((var13 + i * 4)) = var30;
            i = (i + 1);
            var16 = (unsigned long)((unsigned int)((var16 + 2)));
            var17 = (unsigned long)((unsigned int)((var17 - 1)));
            var21 = var30;
        } while ((var14 != i));
        var5 = (unsigned long)((unsigned int)((var25 ^ *(int *)((var13 + ((unsigned long)((unsigned int)((*(long *)(&local_38[0]) - 1))) * 4))))));
    }
    ret = (unsigned long)((unsigned int)(var5));
    // x86-64 epilogue: tear down frame
    return (unsigned int)(var5);
}

gcc -O0

2/2
nested_conditional_matrix pass 17 lines
// glaurung: nested_conditional_matrix @ 0x1207
int32_t nested_conditional_matrix(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    // x86-64 prologue: save rbp
    if ((arg1 <= arg0)) {
        if ((arg3 <= arg2)) {
            return ((((unsigned int)(arg3) == (unsigned int)(arg1)) | (arg3 < arg1)) ? (unsigned long)((unsigned int)(arg3)) : (unsigned long)((unsigned int)(arg1)));
        } else {
            return ((((unsigned int)(arg2) == (unsigned int)(arg1)) | (arg2 < arg1)) ? (unsigned long)((unsigned int)(arg2)) : (unsigned long)((unsigned int)(arg1)));
        }
    } else {
        if ((arg3 <= arg2)) {
            return ((((unsigned int)(arg3) == (unsigned int)(arg0)) | (arg3 < arg0)) ? (unsigned long)((unsigned int)(arg3)) : (unsigned long)((unsigned int)(arg0)));
        } else {
            return ((((unsigned int)(arg2) == (unsigned int)(arg0)) | (arg2 < arg0)) ? (unsigned long)((unsigned int)(arg2)) : (unsigned long)((unsigned int)(arg0)));
        }
    }
}
obfuscated_pipeline pass 42 lines
// glaurung: obfuscated_pipeline @ 0x1129
int32_t obfuscated_pipeline(int32_t * arg0, int32_t arg1, int32_t arg2) {
    extern void fold(void);
    extern void twist(void);
    static void (*STAGES[2])(void) = {
        (void (*)(void))twist,
        (void (*)(void))fold,
    };
    int acc;
    int last;
    int i;
    int _v;
    long var21;
    // x86-64 prologue: save rbp, frame 32 bytes
    acc = arg2;
    last = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    for (i = 0; (i < arg1); i++) {
        acc = (acc ^ (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(i)) & 3))) == 0) ? (~(unsigned long)((unsigned int)(i))) : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(i)) + (unsigned long)((unsigned int)(i)))))));
        last = acc;
        _v = acc;
        var21 = ((long (*)(long))(STAGES[(long)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(_v)) & 1)))))]))((unsigned long)((unsigned int)(_v)));
        acc = var21;
        arg0[(long)(i)] = acc;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return (unsigned int)(acc);
    } else {
        return (unsigned int)(((unsigned long)((unsigned int)(*(int *)(((long)arg0 + (((long)(arg1) << 2) - 4))))) ^ last));
    }
}

gcc -O2

2/2
nested_conditional_matrix pass 7 lines
// glaurung: nested_conditional_matrix @ 0x11c0
int32_t nested_conditional_matrix(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    if ((arg1 <= arg0)) {
        return ((arg3 <= arg2) ? (((((unsigned int)(arg1) == (unsigned int)(arg3)) | (arg1 < arg3)) == 0) ? arg3 : arg1) : ((((unsigned int)(arg1) == (unsigned int)(arg2)) | (arg1 < arg2)) ? arg1 : (unsigned long)((unsigned int)(arg2))));
    }
    return ((arg3 <= arg2) ? (((((unsigned int)(arg0) == (unsigned int)(arg3)) | (arg0 < arg3)) == 0) ? arg3 : arg0) : ((((unsigned int)(arg0) == (unsigned int)(arg2)) | (arg0 < arg2)) ? arg0 : (unsigned long)((unsigned int)(arg2))));
}
obfuscated_pipeline pass 53 lines
// glaurung: obfuscated_pipeline @ 0x1130
int32_t obfuscated_pipeline(int32_t * arg0, int32_t arg1, int32_t arg2) {
    extern void fold(void);
    extern void twist(void);
    static void (*STAGES[2])(void) = {
        (void (*)(void))twist,
        (void (*)(void))fold,
    };
    int i;
    int _v;
    int acc;
    long ret;
    long var0;
    long var1;
    long var19;
    long var2;
    long var7;
    long var9;
    if ((arg0 == 0)) {
        return (unsigned int)(-1);
    }
    var0 = (long)(arg1);
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_11b4;
    }
    ret = (unsigned long)((unsigned int)(arg2));
    if (((unsigned long)((unsigned int)(var0)) == 0)) {
        goto L_11a5;
    }
    var1 = (long)arg0;
    var2 = (unsigned long)((unsigned int)((var0 - 1)));
    i = 0;
    var7 = ret;
    goto L_1173;
    L_1170: ;
    i = var9;
    L_1173: ;
    _v = (unsigned long)((unsigned int)(((((unsigned long)((unsigned char)((i & 3))) != 0) ? (unsigned long)((unsigned int)((i + i))) : (~(unsigned long)((unsigned int)(i)))) ^ var7)));
    var19 = ((long (*)(long))(STAGES[(unsigned long)((unsigned int)(((unsigned long)((unsigned int)(_v)) & 1)))]))((unsigned long)((unsigned int)(_v)));
    var7 = var19;
    var9 = ((unsigned long)((unsigned int)(i)) + 1);
    *(int *)((var1 + i * 4)) = var19;
    if ((i != var2)) {
        goto L_1170;
    }
    ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((var1 + var0 * 4 - 0x4)))) ^ _v)));
    L_11a5: ;
    // x86-64 epilogue: tear down frame
    return ret;
    L_11b4: ;
    ret = 0xffffffff;
    goto L_11a5;
}

← 213 fixtures