Fixture 05

cleanup and state machine

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

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

Control-flow closure fixture: goto cleanup ladders, cold error blocks, retry loops (backward gotos), and a small protocol state machine. The target bug class is mis-structured cross-block flow — a decompiler that drops a cleanup edge, folds two error arms together, or mis-orders the state transitions produces a different return the moment an input exercises the affected path.

Targets review #3 / #5 (cleanup ladders + control-flow join structuring). Key property: every local goto resolves to an emitted label — no dangling gotos, every cold block is reachable via some input. Each failure path returns a DISTINCT negative code; success returns a positive value derived from the input. All functions are differential-testable: int / const uint8_t* arguments, int return, no libc.

tests/decompiler_fixtures/src/05_cleanup_and_state_machine.c source
/* 05_cleanup_and_state_machine.c
 *
 * Control-flow closure fixture: `goto cleanup` ladders, cold error blocks,
 * retry loops (backward gotos), and a small protocol state machine. The target
 * bug class is mis-structured cross-block flow — a decompiler that drops a
 * cleanup edge, folds two error arms together, or mis-orders the state
 * transitions produces a different return the moment an input exercises the
 * affected path.
 *
 * Targets review #3 / #5 (cleanup ladders + control-flow join structuring).
 * Key property: every local `goto` resolves to an emitted label — no dangling
 * gotos, every cold block is reachable via some input. Each failure path
 * returns a DISTINCT negative code; success returns a positive value derived
 * from the input. All functions are differential-testable: int / const uint8_t*
 * arguments, int return, no libc.
 */
#include <stdint.h>

/* Resource-acquisition-style validation ladder. Several conditions are checked
 * in sequence; each failure jumps into a cleanup ladder that unwinds the
 * "acquired" state (modeled by an accumulator that each stage adjusts) and
 * returns a distinct negative error code. Success returns a positive value
 * derived from the input bytes.
 *
 * A bounded retry loop sits in the middle: a transient condition on one byte
 * jumps backward to `retry` up to a fixed number of attempts before giving up
 * through the cleanup ladder. */
int process(const uint8_t *in, int n) {
    int acc = 0;
    int stage = 0;   /* how far we "acquired"; cleanup unwinds by stage */
    int attempts = 0;

    if (in == 0)
        goto fail_null;      /* nothing acquired yet */
    if (n < 4)
        goto fail_short;     /* nothing acquired yet */

    /* Stage 1: header byte must be even. */
    stage = 1;
    if ((in[0] & 1) != 0)
        goto fail_hdr;
    acc += in[0];

retry:
    /* Stage 2 with retry: in[1] must be non-zero. If it is zero we "retry"
     * by folding in the next attempt's contribution; after 3 attempts we fail
     * through the cleanup ladder. */
    if (in[1] == 0) {
        attempts++;
        if (attempts < 3) {
            acc += 1;        /* transient backoff contribution */
            goto retry;
        }
        goto fail_retry;     /* exhausted retries: stage 1 acquired */
    }

    /* Stage 2 acquired. */
    stage = 2;
    acc += in[1] * 2;

    /* Stage 3: in[2] bounds the payload nibble. */
    stage = 3;
    if (in[2] > 0x7F)
        goto fail_range;
    acc += in[2] * 3;

    /* Stage 4: checksum-style consistency across the first four bytes. */
    stage = 4;
    {
        int sum = in[0] + in[1] + in[2] + in[3];
        if ((sum & 0xFF) == 0xEE)
            goto fail_checksum;
        acc += in[3] * 4;
    }

    /* Success: a positive value that folds in the stage reached and the
     * accumulated contributions, kept in a modest positive range. */
    return 1000 + (acc & 0x3FF) + stage;

    /* --- cold cleanup ladder: unwinds by falling through, each entry point
     *     releases exactly the resources acquired up to its stage. --- */
fail_checksum:
    acc -= in[3] * 4;        /* release stage 4 */
    /* fall through */
fail_range:
    if (stage >= 3)
        acc -= in[2] * 3;    /* release stage 3 */
    /* fall through */
fail_retry:
fail_hdr:
    if (stage >= 1)
        acc -= in[0];        /* release stage 1 */
    /* distinct codes for the ladder entry points that share the tail */
    if (stage == 4) return -40;
    if (stage == 3) return -30;
    if (attempts >= 3) return -25;   /* fail_retry entry */
    return -10;                       /* fail_hdr entry */

fail_short:
    return -2;
fail_null:
    return -1;
}

/* Protocol state machine: walk `input` advancing IDLE -> HDR -> BODY -> DONE.
 * The byte sequence drives the transitions; the return code depends on which
 * state the walk ends in and how much body was consumed. If a decompiler
 * mis-structures the state dispatch (e.g. swaps two case arms or drops the
 * fallthrough from HDR to BODY) the return diverges for crafted inputs. */
int fsm(const uint8_t *input, int len) {
    enum { S_IDLE = 0, S_HDR = 1, S_BODY = 2, S_DONE = 3, S_ERR = 4 };
    int state = S_IDLE;
    int body_count = 0;
    int checksum = 0;
    int i = 0;

    if (input == 0 || len <= 0)
        return -100;

    while (i < len) {
        uint8_t b = input[i];
        switch (state) {
        case S_IDLE:
            /* Start-of-message marker. */
            if (b == 0xA5)
                state = S_HDR;
            else if (b == 0x00)
                state = S_IDLE;      /* idle padding, stay */
            else
                goto machine_error;
            break;
        case S_HDR:
            /* Header carries the declared body length in the low nibble. */
            if (b == 0xFF)
                goto machine_error;  /* reserved header */
            body_count = (b & 0x0F);
            if (body_count == 0)
                state = S_DONE;      /* empty body: jump straight to DONE */
            else
                state = S_BODY;
            checksum = b;
            break;
        case S_BODY:
            checksum += b;
            body_count--;
            if (body_count == 0)
                state = S_DONE;
            /* else remain in S_BODY consuming more bytes */
            break;
        case S_DONE:
            /* Trailer byte must match the low byte of the checksum. */
            if (b == (uint8_t)(checksum & 0xFF))
                return 200 + (checksum & 0x3F);   /* clean finish */
            else
                return -201;                       /* bad trailer */
        default:
            goto machine_error;
        }
        i++;
    }

    /* Ran out of input: distinct code per terminal state so a mis-structured
     * transition surfaces. */
    if (state == S_DONE) return 150;      /* reached DONE, no trailer seen */
    if (state == S_BODY) return -150;     /* truncated body */
    if (state == S_HDR)  return -140;     /* header without body */
    return -130;                          /* still idle */

machine_error:
    return -110 - state;                  /* distinct per originating state */
}

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
fsm pass 121 lines
// glaurung: fsm @ 0x1320
int fsm(const uint8_t * arg0, int arg1) {
    int state;
    int body_count;
    int checksum;
    int i;
    unsigned char b;
    long local_30;
    int local_4;
    // x86-64 prologue: save rbp
    state = 0;
    body_count = 0;
    checksum = 0;
    i = 0;
    if ((arg0 == 0)) {
        local_4 = -100;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) != 0)) {
        local_4 = -100;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    L_136d: ;
    while (1) {
        if ((arg1 <= i)) {
            goto L_14a9;
        }
        b = arg0[i];
        local_30 = (unsigned int)(state);
        if (((unsigned long)(3) < (unsigned long)((unsigned long)((unsigned int)(state))))) {
            goto L_1496;
        }
        switch (local_30) {
            case 0:
                goto L_13ac;
            case 1:
                goto L_13ef;
            case 2:
                goto L_1436;
            case 3:
                goto L_145f;
        }
        L_13ac: ;
        if (((unsigned long)((unsigned long)(b)) == 165)) {
            state = 1;
            goto L_13ea;
        }
        if (((unsigned long)((unsigned long)(b)) != 0)) {
            goto L_13e0;
        }
        state = 0;
        goto L_13e5;
        L_13e5: ;
        goto L_13ea;
        L_13ea: ;
        goto L_149b;
        L_13ef: ;
        if (((unsigned long)((unsigned long)(b)) == 255)) {
            goto L_13fe;
        }
        body_count = ((unsigned int)(b) & 15);
        if (((unsigned long)((unsigned int)(body_count)) == 0)) {
            state = 3;
            goto L_142a;
        }
        state = 2;
        L_142a: ;
        checksum = b;
        goto L_149b;
        L_1436: ;
        checksum = ((unsigned int)(b) + checksum);
        body_count = ((unsigned int)(body_count) - 1);
        if (((unsigned long)((unsigned int)(body_count)) == 0)) {
            state = 3;
        }
        goto L_149b;
        L_149b: ;
        i = ((unsigned int)(i) + 1);
        goto L_136d;
    }
    L_13e0: ;
    goto L_14f7;
    L_13fe: ;
    goto L_14f7;
    L_145f: ;
    if (((unsigned long)((unsigned long)(b)) == (unsigned long)((unsigned int)((unsigned char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(checksum)) & 255))) & 255)))))) {
        local_4 = ((unsigned int)(((unsigned long)((unsigned int)(checksum)) & 63)) + 200);
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = -201;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1496: ;
    goto L_14f7;
    L_14a9: ;
    if (((unsigned long)((unsigned int)(state)) == 3)) {
        local_4 = 150;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((unsigned long)((unsigned int)(state)) == 2)) {
        local_4 = -150;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((unsigned long)((unsigned int)(state)) == 1)) {
        local_4 = -140;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = -130;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_14f7: ;
    local_4 = (0xffffff92 - state);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
process pass 84 lines
// glaurung: process @ 0x1100
int process(const uint8_t * arg0, int arg1) {
    int acc;
    int stage;
    int attempts;
    int sum;
    int local_4;
    int var23;
    acc = 0;
    stage = 0;
    attempts = 0;
    if ((arg0 == 0)) {
        goto L_1305;
    }
    if (((long)(arg1) < 4)) {
        goto L_12f9;
    }
    stage = 1;
    if (((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)((long)arg0))) & 1))) != 0)) {
        goto L_1292;
    }
    acc = ((unsigned int)((unsigned char)(*(char *)((long)arg0))) + acc);
    L_116b: ;
    if (((unsigned long)((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x1))))) == 0)) {
        attempts = ((unsigned int)(attempts) + 1);
        if (((long)(attempts) < 3)) {
            acc = ((unsigned int)(acc) + 1);
            goto L_116b;
        }
        goto L_128d;
    }
    stage = 2;
    acc = ((unsigned int)(((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x1)))) << 1)) + acc);
    stage = 3;
    var23 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x2))));
    if (((((unsigned long)((unsigned int)(var23)) == 127) | ((long)((int)(var23)) < 127)) != 0)) {
        acc = (((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x2)))) * 3) + acc);
        stage = 4;
        sum = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)((long)arg0))) + (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x1))))))) + (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x2)))))) + (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x3)))));
        if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(sum)) & 255))) != 238)) {
            acc = ((unsigned int)(((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x3)))) << 2)) + acc);
            local_4 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(acc)) & 1023))) + 1000)) + stage);
            // x86-64 epilogue: restore rbp
            return (unsigned int)(local_4);
        }
        acc = ((unsigned int)(acc) - (unsigned int)(((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x3)))) << 2)));
    }
    if ((3 <= (long)(stage))) {
        acc = ((unsigned int)(acc) - ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x2)))) * 3));
    }
    goto L_128d;
    L_128d: ;
    goto L_1292;
    L_1292: ;
    if ((1 <= (long)(stage))) {
        acc = ((unsigned int)(acc) - (unsigned int)((unsigned char)(*(char *)((long)arg0))));
    }
    if (((unsigned long)((unsigned int)(stage)) == 4)) {
        local_4 = -40;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((unsigned long)((unsigned int)(stage)) == 3)) {
        local_4 = -30;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((3 <= (long)(attempts))) {
        local_4 = -25;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = -10;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_12f9: ;
    local_4 = -2;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1305: ;
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

2/2
fsm pass 103 lines
// glaurung: fsm @ 0x1170
int fsm(const uint8_t * arg0, int arg1) {
    int state;
    int i;
    int body_count;
    int checksum;
    long ret;
    long var0;
    long var10;
    long var11;
    long var12;
    int var14;
    int var19;
    long var20;
    int var34;
    int var40;
    long var41;
    ret = 0xffffff9c;
    if ((arg0 == 0)) {
        return ret;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return ret;
    }
    var0 = (unsigned long)((unsigned int)(arg1));
    var10 = 0;
    var11 = 0;
    var12 = 0;
    state = 0;
    L_11b8: ;
    while (1) {
        if (((unsigned long)(3) < (unsigned long)((unsigned long)((unsigned int)(state))))) {
            goto L_121c;
        }
        goto L_11bd;
        L_11a0: ;
        var19 = (var11 - 1);
        var20 = (unsigned long)((unsigned int)(var19));
        var10 = (unsigned long)((unsigned int)((var10 + var14)));
        state = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(var19)) == 0) | 2)));
        L_11af: ;
        i = (var12 + 1);
        var11 = var20;
        var12 = (unsigned long)((unsigned int)(i));
        if ((var0 == i)) {
            goto L_1201;
        }
        goto L_11b8;
        L_11bd: ;
        var14 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + var12))));
        switch ((unsigned long)((unsigned int)(state))) {
            case 0:
                goto L_11cc;
            case 1:
                goto L_11e0;
            case 2:
                goto L_11a0;
            case 3:
                goto L_1224;
        }
        L_11cc: ;
        if (((unsigned long)((unsigned char)((var14 & 255))) == 165)) {
            goto L_11fa;
        }
        if (((unsigned long)((unsigned char)((var14 & 255))) != 0)) {
            goto L_121c;
        }
        var20 = var11;
        state = 0;
        goto L_11af;
        L_11e0: ;
        if (((unsigned long)((unsigned char)((var14 & 255))) == 255)) {
            goto L_121c;
        }
        var34 = ((unsigned int)(var14) & 15);
        state = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(var34)) == 0) | 2)));
        var10 = (unsigned long)((unsigned int)(var14));
        var20 = (unsigned long)((unsigned int)(var34));
        goto L_11af;
        L_11fa: ;
        state = 1;
        var20 = var11;
        goto L_11af;
    }
    L_1201: ;
    var40 = (state - 1);
    var41 = (unsigned long)((unsigned int)(var40));
    ret = 0xffffff7e;
    if (((unsigned long)(3) <= (unsigned long)((unsigned long)((unsigned int)(var40))))) {
        goto L_121b;
    }
    ret = (unsigned long)((unsigned int)(*(int *)((0x2010 + ((long)((int)(var41)) * 4)))));
    L_121b: ;
    return ret;
    L_121c: ;
    return (unsigned int)((0xffffff92 - state));
    L_1224: ;
    ret = 0xffffff37;
    if (((unsigned char)((var14 & 255)) != (unsigned char)((var10 & 255)))) {
        goto L_121b;
    }
    return (unsigned int)(((unsigned long)((unsigned int)((var10 & 63))) + 200));
}
process pass 36 lines
// glaurung: process @ 0x1100
int process(const uint8_t * arg0, int arg1) {
    int acc;
    int stage;
    int sum;
    long ret;
    int var0;
    int var1;
    int var2;
    int var6;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    ret = 0xfffffffe;
    if ((4 <= (long)(arg1))) {
        var0 = (unsigned int)((unsigned char)(*(char *)(((long)arg0))));
        ret = 0xfffffff6;
        if (((unsigned long)((unsigned char)((var0 & 1))) != 0)) {
            return ret;
        }
        var1 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x1))));
        if (((unsigned long)((unsigned int)(var1)) == 0)) {
            return 0xffffffe7;
        }
        var2 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x2))));
        if (((long)((signed char)((var2 & 255))) < 0)) {
            return 0xffffffe2;
        }
        var6 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x3))));
        ret = 0xffffffd8;
        if (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var1 + var0))) + var2))) + var6))) & 255))) != 238)) {
            ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var2 + (var2 * 2)))) + (unsigned long)((unsigned int)((var0 + (var1 * 2))))))) + (var6 * 4)))) & 1023))) + 1004)));
        }
    }
    return ret;
}

gcc -O0

2/2
fsm pass 86 lines
// glaurung: fsm @ 0x12dc
int fsm(const uint8_t * arg0, int arg1) {
    int state;
    int body_count;
    int checksum;
    int i;
    unsigned char b;
    state = 0;
    body_count = 0;
    checksum = 0;
    i = 0;
    if ((arg0 != 0)) {
        if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0)) {
            goto L_13fa;
        }
    }
    // x86-64 epilogue: restore rbp
    return 0xffffff9c;
    L_1322: ;
    b = arg0[i];
    switch (state) {
        case 0:
            if ((b == 165)) {
                state = 1;
                goto L_13f6;
            }
            if ((b != 0)) {
                // x86-64 epilogue: restore rbp
                return (unsigned int)((0xffffff92 - state));
            }
            state = 0;
            goto L_13f6;
        case 1:
            if ((b == 255)) {
                // x86-64 epilogue: restore rbp
                return (unsigned int)((0xffffff92 - state));
            }
            body_count = ((unsigned int)(b) & 15);
            if (((unsigned long)((unsigned int)(body_count)) == 0)) {
                state = 3;
                goto L_13b6;
            }
            state = 2;
            L_13b6: ;
            checksum = b;
            goto L_13f6;
        case 2:
            checksum = (checksum + (unsigned int)(b));
            body_count = (body_count - 1);
            if (((unsigned long)((unsigned int)(body_count)) != 0)) {
                goto L_13f5;
            }
            state = 3;
            goto L_13f5;
        case 3:
            if ((b == (unsigned long)((unsigned char)(((unsigned long)((unsigned int)(checksum)) & 255))))) {
                // x86-64 epilogue: restore rbp
                return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(checksum)) & 63))) + 200));
            }
            // x86-64 epilogue: restore rbp
            return 0xffffff37;
            L_13f5: ;
            L_13f6: ;
            i = (i + 1);
            L_13fa: ;
            if ((i < arg1)) {
                goto L_1322;
            }
            if (((unsigned long)((unsigned int)(state)) == 3)) {
                // x86-64 epilogue: restore rbp
                return 150;
            }
            if (((unsigned long)((unsigned int)(state)) == 2)) {
                // x86-64 epilogue: restore rbp
                return 0xffffff6a;
            }
            if (((unsigned long)((unsigned int)(state)) != 1)) {
                // x86-64 epilogue: restore rbp
                return 0xffffff7e;
            }
            // x86-64 epilogue: restore rbp
            return 0xffffff74;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)((0xffffff92 - state));
}
process pass 82 lines
// glaurung: process @ 0x10f9
int process(const uint8_t * arg0, int arg1) {
    int acc;
    int stage;
    int attempts;
    int sum;
    int var14;
    int var23;
    int var73;
    acc = 0;
    stage = 0;
    attempts = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 3) | ((long)(arg1) < 3))) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    stage = 1;
    if (((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)((long)arg0))) & 255))) & 1))) != 0)) {
        goto L_1284;
    }
    acc = (acc + (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)((long)arg0))) & 255))));
    L_115b: ;
    if (((unsigned long)((unsigned char)(((unsigned int)((unsigned char)(arg0[1])) & 255))) == 0)) {
        attempts = (attempts + 1);
        if (((((unsigned long)((unsigned int)(attempts)) == 2) | ((long)(attempts) < 2)) == 0)) {
            goto L_1287;
        }
        acc = (acc + 1);
        goto L_115b;
    }
    stage = 2;
    var14 = (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[1])) & 255)));
    acc = (acc + (unsigned int)((var14 + var14)));
    stage = 3;
    if ((0 <= (long)((signed char)(((unsigned int)((unsigned char)(arg0[2])) & 255))))) {
        var23 = (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[2])) & 255)));
        acc = (acc + (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var23)) + (unsigned long)((unsigned int)(var23))))) + var23)));
        stage = 4;
        sum = ((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[3])) & 255))) + (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)((long)arg0))) & 255))) + (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[1])) & 255)))))) + (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[2])) & 255))))));
        if (((unsigned long)((unsigned int)((unsigned char)(((unsigned long)((unsigned int)(sum)) & 255)))) != 238)) {
            acc = (acc + (unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[3])) & 255))) << 2)));
            // x86-64 epilogue: restore rbp
            return (unsigned int)(((unsigned long)((unsigned int)(stage)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(acc)) & 1023))) + 1000)))));
        }
        acc = (acc - (unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[3])) & 255))) << 2)));
        goto L_125e;
    }
    L_125e: ;
    if ((((unsigned long)((unsigned int)(stage)) == 2) | ((long)(stage) < 2))) {
        goto L_128a;
    }
    var73 = (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[2])) & 255)));
    acc = (acc + (unsigned int)(((unsigned long)((unsigned int)(var73)) - (unsigned long)((unsigned int)((var73 * 4))))));
    goto L_128b;
    L_1284: ;
    goto L_128b;
    L_1287: ;
    goto L_128b;
    L_128a: ;
    L_128b: ;
    if (((((unsigned long)((unsigned int)(stage)) == 0) | ((long)(stage) < 0)) == 0)) {
        acc = (acc - (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)((long)arg0))) & 255))));
    }
    if (((unsigned long)((unsigned int)(stage)) == 4)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffd8;
    }
    if (((unsigned long)((unsigned int)(stage)) == 3)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffe2;
    }
    if ((((unsigned long)((unsigned int)(attempts)) == 2) | ((long)(attempts) < 2))) {
        // x86-64 epilogue: restore rbp
        return 0xfffffff6;
    }
    // x86-64 epilogue: restore rbp
    return 0xffffffe7;
}

gcc -O2

2/2
fsm pass 118 lines
// glaurung: fsm @ 0x1180
int fsm(const uint8_t * arg0, int arg1) {
    unsigned char b;
    int body_count;
    int checksum;
    int i;
    int state;
    int var0;
    long var1;
    long var10;
    int var14;
    long var15;
    int var16;
    long var17;
    long var20;
    long var21;
    long var22;
    long var3;
    long var31;
    long var32;
    long var33;
    long var37;
    long var38;
    int var4;
    long var41;
    int var42;
    long var5;
    long var6;
    if ((arg0 == 0)) {
        return 0xffffff9c;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return 0xffffff9c;
    }
    var0 = (unsigned int)((unsigned char)(*(char *)(((long)arg0))));
    if (((unsigned long)((unsigned char)((var0 & 255))) != 165)) {
        if (((unsigned long)((unsigned char)((var0 & 255))) != 0)) {
            return 0xffffff92;
        }
        if (((unsigned long)((unsigned int)(arg1)) != 1)) {
            var1 = (long)(arg1);
            var3 = 1;
            do {
                var4 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + var3))));
                var5 = (long)((int)(var3));
                if (((unsigned long)((unsigned char)((var4 & 255))) == 165)) {
                    goto L_1298;
                }
                if (((unsigned long)((unsigned char)((var4 & 255))) != 0)) {
                    return 0xffffff92;
                }
                var6 = (var3 + 1);
                var3 = var6;
            } while ((var1 != var6));
        }
        return 0xffffff7e;
    }
    var5 = 0;
    var10 = 1;
    L_11e8: ;
    if ((((unsigned int)(arg1) == (unsigned int)(var10)) | ((long)(arg1) < (long)((int)(var10))))) {
        return 0xffffff74;
    }
    b = (unsigned int)((unsigned char)(arg0[(long)((int)(var10))]));
    if (((unsigned long)((unsigned char)((b & 255))) == 255)) {
        return 0xffffff91;
    }
    var14 = (unsigned int)((unsigned char)((b & 255)));
    var15 = (unsigned long)((unsigned int)((var5 + 2)));
    var16 = ((unsigned int)((unsigned int)(b)) & 15);
    var17 = (unsigned long)((unsigned int)(var16));
    if (((unsigned long)((unsigned int)(var16)) != 0)) {
        goto L_1238;
    }
    if ((((unsigned int)(arg1) == (unsigned int)(var15)) | ((long)(arg1) < (long)((int)(var15))))) {
        return 150;
    }
    var20 = (unsigned long)((unsigned int)(var14));
    var21 = (unsigned long)(b);
    var22 = (unsigned int)((unsigned char)(arg0[(long)((int)(var15))]));
    L_121e: ;
    return (((unsigned char)((var21 & 255)) != (unsigned char)((var22 & 255))) ? 0xffffff37 : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var20 & 63))) + 200))));
    L_1238: ;
    if (((((unsigned int)(arg1) == (unsigned int)(var15)) | ((long)(arg1) < (long)((int)(var15)))) == 0)) {
        var31 = (unsigned long)((unsigned int)((var14 + (unsigned int)((unsigned char)(arg0[(long)((int)(var15))])))));
        var32 = var15;
        if (((unsigned long)((unsigned char)((var17 & 255))) == 1)) {
            goto L_1280;
        }
        var33 = (unsigned long)((unsigned int)((var5 + 3)));
        if (((((unsigned int)(arg1) == (unsigned int)(var33)) | ((long)(arg1) < (long)((int)(var33)))) == 0)) {
            var37 = ((var5 + (unsigned long)((unsigned int)(((unsigned int)((unsigned char)((var17 & 255))) - 2)))) + 3);
            var38 = (long)((int)(var33));
            do {
                var32 = (unsigned long)((unsigned int)(var38));
                var31 = (unsigned long)((unsigned int)((var31 + (unsigned int)((unsigned char)(*(char *)(((long)arg0 + var38)))))));
                if ((var37 == var38)) {
                    goto L_1280;
                }
                var41 = (var38 + 1);
                var38 = var41;
            } while (((((unsigned int)(arg1) == (unsigned int)(var41)) | ((long)(arg1) < (long)((int)(var41)))) == 0));
        }
    }
    return 0xffffff6a;
    L_1280: ;
    var42 = (var32 + 1);
    if ((((unsigned int)(arg1) == (unsigned int)(var42)) | (arg1 < var42))) {
        return 150;
    }
    var20 = var31;
    var21 = (unsigned long)((unsigned int)(var31));
    var22 = (unsigned int)((unsigned char)(arg0[(long)((int)(var42))]));
    goto L_121e;
    L_1298: ;
    var10 = (unsigned long)((unsigned int)((var5 + 1)));
    goto L_11e8;
}
process pass 41 lines
// glaurung: process @ 0x1100
int process(const uint8_t * arg0, int arg1) {
    int acc;
    int stage;
    long ret;
    int var0;
    int var1;
    int var2;
    long var3;
    int var5;
    long var6;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 3) | ((long)(arg1) < 3))) {
        return 0xfffffffe;
    }
    var0 = (unsigned int)((unsigned char)(*(char *)(((long)arg0))));
    ret = 0xfffffff6;
    if (((unsigned long)((unsigned char)((var0 & 1))) != 0)) {
        return ret;
    }
    var1 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x1))));
    ret = 0xffffffe7;
    if (((unsigned long)((unsigned char)((var1 & 255))) == 0)) {
        return ret;
    }
    var2 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x2))));
    ret = 0xffffffe2;
    if (((long)((signed char)((var2 & 255))) < 0)) {
        return ret;
    }
    var3 = (unsigned long)((unsigned int)((var0 + (var1 * 2))));
    var5 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x3))));
    var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var2 + (var2 * 2)))) + var3)));
    ret = 0xffffffd8;
    if (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var3 - var1))) + var2))) + var5))) & 255))) != 238)) {
        return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var6 + (var5 * 4)))) & 1023))) + 1004));
    }
    return 0xffffffd8;
}

← 213 fixtures