Fixture 161

packed struct layout

C · 5 functions · 4 lanes · 18 of 20 function-lanes behave identically

2 of 4 lanes have a function that returns a different result after decompilation: clang-O2 (4/5), gcc-O2 (4/5).

__attribute__((packed)) wire records: the same four members declared twice, once with natural alignment and once packed. The natural struct is 12 bytes (kind @0, 3 bytes of padding, seq @4, port @8, ttl @10, 1 byte of tail padding); the packed struct is 8 bytes with seq @1 and port @5 -- both of them unaligned. Nothing in the C source says "1" and "5"; the attribute does, and every offset in the emitted code is a resolved constant.

Why this stresses a decompiler: after lowering, the two layouts are just different immediate displacements off a base register, and a packed 4-byte load at displacement 1 looks exactly like a natural one at displacement 4. A decompiler that re-types the buffer with a *plausible* aggregate rather than the actual one produces C that compiles, type-checks, reads well, and decodes a different byte range -- a shift of the whole record by three bytes, structurally invisible and behaviorally fatal. The size/offset probes here pin the layout as an observable, and encode/decode pin that the packed member accesses really do straddle the alignment boundaries.

UB notes: the wire bytes are moved through an unsigned char * view of a whole struct object (character-type access aliases everything, C11 6.5p7), never by casting a byte buffer to a struct pointer, and never by taking the address of a packed member (which is both a diagnostic and a misaligned pointer). Every packed byte is covered by a member, so no indeterminate padding is ever read.

tests/decompiler_fixtures/src/161_packed_struct_layout.c source
/* 161_packed_struct_layout.c
 *
 * `__attribute__((packed))` wire records: the same four members declared twice,
 * once with natural alignment and once packed. The natural struct is 12 bytes
 * (kind @0, 3 bytes of padding, seq @4, port @8, ttl @10, 1 byte of tail
 * padding); the packed struct is 8 bytes with seq @1 and port @5 -- both of them
 * unaligned. Nothing in the C source says "1" and "5"; the attribute does, and
 * every offset in the emitted code is a resolved constant.
 *
 * Why this stresses a decompiler: after lowering, the two layouts are just
 * different immediate displacements off a base register, and a packed 4-byte
 * load at displacement 1 looks exactly like a natural one at displacement 4.
 * A decompiler that re-types the buffer with a *plausible* aggregate rather
 * than the actual one produces C that compiles, type-checks, reads well, and
 * decodes a different byte range -- a shift of the whole record by three bytes,
 * structurally invisible and behaviorally fatal. The size/offset probes here
 * pin the layout as an observable, and encode/decode pin that the packed member
 * accesses really do straddle the alignment boundaries.
 *
 * UB notes: the wire bytes are moved through an `unsigned char *` view of a
 * whole struct object (character-type access aliases everything, C11 6.5p7),
 * never by casting a byte buffer to a struct pointer, and never by taking the
 * address of a packed member (which is both a diagnostic and a misaligned
 * pointer). Every packed byte is covered by a member, so no indeterminate
 * padding is ever read.
 */
#include <stddef.h>
#include <stdint.h>

#define PK161_WIRE_BYTES 8
#define PK161_MAX_BUF    16

/* Host-natural layout: the compiler is free to insert padding. */
struct pk161_natural {
    uint8_t  kind;
    uint32_t seq;
    uint16_t port;
    uint8_t  ttl;
};

/* The wire layout: no padding anywhere, so seq and port are unaligned. */
struct pk161_wire {
    uint8_t  kind; /* offset 0 */
    uint32_t seq;  /* offset 1 -- unaligned 4-byte member */
    uint16_t port; /* offset 5 -- unaligned 2-byte member */
    uint8_t  ttl;  /* offset 7 */
} __attribute__((packed));

_Static_assert(sizeof(struct pk161_wire) == PK161_WIRE_BYTES,
               "packed wire record must be exactly 8 bytes");
_Static_assert(sizeof(struct pk161_natural) > sizeof(struct pk161_wire),
               "the natural layout must be the padded one");

/* Clamp any caller-supplied length into [0, PK161_MAX_BUF] before it is used in
 * arithmetic, so a hostile INT_MIN can never overflow a subtraction. */
static int32_t pk161_clamp(int32_t n) {
    if (n < 0) {
        return 0;
    }
    if (n > PK161_MAX_BUF) {
        return PK161_MAX_BUF;
    }
    return n;
}

/* sizeof(natural) - sizeof(packed): the padding the attribute removes. */
__attribute__((noinline)) int32_t pk161_layout_delta(void) {
    return (int32_t)(sizeof(struct pk161_natural) - sizeof(struct pk161_wire));
}

/* Every member offset in both layouts. Cases 0..3 are the natural struct,
 * 4..7 the packed one; the pairwise difference IS the specification. */
__attribute__((noinline)) int32_t pk161_member_offset(int32_t which) {
    switch (which & 7) {
    case 0:
        return (int32_t)offsetof(struct pk161_natural, kind);
    case 1:
        return (int32_t)offsetof(struct pk161_natural, seq);
    case 2:
        return (int32_t)offsetof(struct pk161_natural, port);
    case 3:
        return (int32_t)offsetof(struct pk161_natural, ttl);
    case 4:
        return (int32_t)offsetof(struct pk161_wire, kind);
    case 5:
        return (int32_t)offsetof(struct pk161_wire, seq);
    case 6:
        return (int32_t)offsetof(struct pk161_wire, port);
    default:
        return (int32_t)offsetof(struct pk161_wire, ttl);
    }
}

/* Fill a packed record member-by-member (the stores land at 0/1/5/7), then emit
 * its 8 bytes to the caller's buffer. Returns the byte sum, or a negative code.
 */
__attribute__((noinline)) int32_t
pk161_encode(uint8_t *out, int32_t out_len, uint32_t seq, int32_t kind) {
    struct pk161_wire record = {0, 0, 0, 0};
    const unsigned char *raw;
    int32_t limit = pk161_clamp(out_len);
    int32_t sum = 0;
    int32_t i;

    if (out == NULL) {
        return -1;
    }
    if (limit < PK161_WIRE_BYTES) {
        return -2;
    }

    record.kind = (uint8_t)((uint32_t)kind & 0xFFu);
    record.seq  = seq;
    record.port = (uint16_t)(((uint32_t)kind >> 8) & 0xFFFFu);
    record.ttl  = (uint8_t)((seq >> 24) & 0xFFu);

    raw = (const unsigned char *)&record;
    for (i = 0; i < PK161_WIRE_BYTES; i++) {
        out[i] = (uint8_t)raw[i];
        sum += (int32_t)raw[i];
    }
    return sum;
}

/* Refill a packed record from wire bytes, then read one member back. The read
 * of `seq` is a 4-byte access at offset 1. Returns 0xFFFFFFFF on rejection;
 * no member of this record can legitimately produce that value except `seq`,
 * which is documented as ambiguous. */
__attribute__((noinline)) uint32_t
pk161_read_field(const uint8_t *in, int32_t in_len, int32_t which) {
    struct pk161_wire record = {0, 0, 0, 0};
    unsigned char *raw;
    int32_t limit = pk161_clamp(in_len);
    int32_t i;

    if (in == NULL) {
        return 0xFFFFFFFFu;
    }
    if (limit < PK161_WIRE_BYTES) {
        return 0xFFFFFFFFu;
    }

    raw = (unsigned char *)&record;
    for (i = 0; i < PK161_WIRE_BYTES; i++) {
        raw[i] = (unsigned char)in[i];
    }

    switch (which & 3) {
    case 0:
        return (uint32_t)record.kind;
    case 1:
        return record.seq; /* unaligned load at wire offset 1 */
    case 2:
        return (uint32_t)record.port; /* unaligned load at wire offset 5 */
    default:
        return (uint32_t)record.ttl;
    }
}

/* Encode into a local frame and decode straight back: the roundtrip only holds
 * if both directions agree on offsets 1 and 5. */
__attribute__((noinline)) int32_t
pk161_roundtrip(uint32_t seq, int32_t kind) {
    uint8_t frame[PK161_MAX_BUF];
    int32_t rc;
    int32_t i;

    for (i = 0; i < PK161_MAX_BUF; i++) {
        frame[i] = 0;
    }
    rc = pk161_encode(frame, PK161_WIRE_BYTES, seq, kind);
    if (rc < 0) {
        return rc;
    }
    if (pk161_read_field(frame, PK161_WIRE_BYTES, 1) != seq) {
        return -3;
    }
    if (pk161_read_field(frame, PK161_WIRE_BYTES, 2) !=
        (((uint32_t)kind >> 8) & 0xFFFFu)) {
        return -4;
    }
    return rc;
}

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

4/5
pk161_encode pass 36 lines
// glaurung: pk161_encode @ 0x1150
int32_t pk161_encode(uint8_t * arg0, int32_t arg1, uint32_t arg2, int32_t arg3) {
    int i;
    int sum;
    long local_10;
    long local_8;
    long rbp;
    long ret;
    long var1;
    long var13;
    int var17;
    int var18;
    int var19;
    int var40;
    long var9;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    ret = 0xfffffffe;
    if ((8 <= (long)(arg1))) {
        local_8 = rbp;
        local_10 = var1;
        var9 = (unsigned long)((unsigned int)(((unsigned int)(arg2) >> 24)));
        var13 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg3)) >> 16)));
        *(signed char *)(((long)arg0)) = arg3;
        var17 = (unsigned int)((unsigned char)(((unsigned long)((unsigned int)(((unsigned int)(arg2) >> 16))) & 255)));
        var18 = (unsigned int)((unsigned char)((arg2 & 255)));
        var19 = (unsigned int)((unsigned char)((((unsigned int)(arg2) >> 8) & 255)));
        *(int *)(((long)arg0 + 0x1)) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var19 << 8))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var17 << 16))) | (unsigned long)((unsigned int)((arg2 & -0x1000000LL))))))))) | var18);
        var40 = (unsigned int)((unsigned char)((((unsigned int)(arg3) >> 8) & 255)));
        *(short *)(((long)arg0 + 0x5)) = ((unsigned long)((unsigned int)((var13 << 8))) | var40);
        *(signed char *)(((long)arg0 + 0x7)) = var9;
        ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)((var13 & 255))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)((arg3 & 255))) + var18))) + var19))) + var17))) + var9))) + var40)))))) + var9)));
    }
    return ret;
}
pk161_layout_delta pass 4 lines
// glaurung: pk161_layout_delta @ 0x1120
int32_t pk161_layout_delta(void) {
    return 4;
}
pk161_member_offset pass 11 lines
// glaurung: pk161_member_offset @ 0x1130
int32_t pk161_member_offset(int32_t arg0) {
    long ret;
    long var1;
    var1 = (unsigned long)((unsigned int)((arg0 & 7)));
    ret = 7;
    if (((unsigned long)((unsigned int)(var1)) != 7)) {
        ret = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(var1)) == 0) ? 0 : (((unsigned long)((unsigned int)(var1)) == 1) ? 4 : (((unsigned long)((unsigned int)(var1)) == 2) ? 8 : (((unsigned long)((unsigned int)(var1)) == 3) ? 10 : (((unsigned long)((unsigned int)(var1)) == 4) ? 0 : (((unsigned long)((unsigned int)(var1)) == 5) ? 1 : (((unsigned long)((unsigned int)(var1)) == 6) ? 5 : *(int *)((0x2000 + ((unsigned long)((unsigned int)(var1)) * 4))))))))))));
    }
    return ret;
}
pk161_read_field pass 23 lines
// glaurung: pk161_read_field @ 0x11d0
uint32_t pk161_read_field(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    long ret;
    long var1;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((long)(arg1) < 8)) {
        return ret;
    }
    var1 = (unsigned long)((unsigned int)((arg2 & 3)));
    if (((unsigned long)((unsigned int)(var1)) == 2)) {
        return (unsigned int)((unsigned short)(*(short *)(((long)arg0 + 0x5))));
    }
    if (((unsigned long)((unsigned int)(var1)) == 1)) {
        return (unsigned int)(*(int *)(((long)arg0 + 0x1)));
    }
    if (((unsigned long)((unsigned int)(var1)) == 0)) {
        return (unsigned int)((unsigned char)(*(char *)(((long)arg0))));
    }
    return (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x7))));
}
pk161_roundtrip fail 36 lines
// glaurung: pk161_roundtrip @ 0x1210
__attribute__((no_stack_protector)) int32_t pk161_roundtrip(uint32_t arg0, int32_t arg1) {
    extern int pk161_encode(char *, int, unsigned int, int);
    extern unsigned int pk161_read_field(char *, int, int);
    int rc;
    int i;
    unsigned char local_28[40];
    long ret;
    long rsp;
    long var0;
    long var1;
    unsigned int var11;
    unsigned int var15;
    int var7;
    // x86-64 prologue: save callee registers, frame 24 bytes
    rsp = (rsp - 16);
    var0 = (unsigned long)((unsigned int)(arg1));
    var1 = (unsigned long)(arg0);
    *(int *)(&local_28[0]) = 0;
    *(int *)((&local_28[0] + 4)) = 0;
    *(int *)((&local_28[0] + 8)) = 0;
    *(int *)((&local_28[0] + 12)) = 0;
    var7 = pk161_encode((char *)(rsp), 8, arg0, (unsigned long)((unsigned int)(arg1)));
    rc = (unsigned long)((unsigned int)(var7));
    if (((long)((int)(var7)) < 0)) {
        return (unsigned int)(rc);
    }
    var11 = pk161_read_field((char *)(rsp), 8, 1);
    ret = 0xfffffffd;
    if ((var11 == (unsigned long)((unsigned int)(var1)))) {
        var15 = pk161_read_field((char *)(rsp), 8, 2);
        ret = ((var15 == (unsigned long)((unsigned int)((unsigned short)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) >> 8))) & 0xffff))))) ? rc : 0xfffffffc);
    }
    // x86-64 epilogue: restore callee registers
    return ret;
}

gcc -O2

4/5
pk161_encode pass 49 lines
// glaurung: pk161_encode @ 0x1190
int32_t pk161_encode(uint8_t * arg0, int32_t arg1, uint32_t arg2, int32_t arg3) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int i;
    int sum;
    long local_10;
    unsigned char local_18[8];
    long var17;
    long var20;
    long var4;
    long var6;
    int var8;
    local_10 = (long)(0x28);
    var4 = 0;
    *(int *)((&local_18[0] + 1)) = 0;
    *(short *)((&local_18[0] + 5)) = 0;
    *(signed char *)((&local_18[0] + 7)) = 0;
    if ((arg0 == 0)) {
        var6 = 0xffffffff;
    } else {
        if ((((unsigned long)((unsigned int)(arg1)) == 7) | ((long)(arg1) < 7))) {
            var6 = 0xfffffffe;
        } else {
            *(signed char *)(&local_18[0]) = arg3;
            var8 = (unsigned int)((unsigned char)((arg3 & 255)));
            *(int *)((&local_18[0] + 1)) = arg2;
            *(short *)((&local_18[0] + 5)) = ((unsigned long)((unsigned int)(arg3)) >> 8);
            *(signed char *)((&local_18[0] + 7)) = ((unsigned int)(arg2) >> 24);
            var17 = 0;
            i = var4;
            while (1) {
                *(signed char *)(((long)arg0 + i)) = var8;
                i = (i + 1);
                sum = (var17 + var8);
                var20 = (unsigned long)((unsigned int)(sum));
                var6 = (unsigned long)((unsigned int)(sum));
                if ((i == 8)) {
                    break;
                }
                var8 = (unsigned int)((unsigned char)(*(char *)((&local_18[0] + i))));
                var17 = var20;
            }
        }
    }
    if ((local_10 != 0x28)) {
        __stack_chk_fail();
    }
    return (unsigned int)(var6);
}
pk161_layout_delta pass 4 lines
// glaurung: pk161_layout_delta @ 0x1160
int32_t pk161_layout_delta(void) {
    return 4;
}
pk161_member_offset pass 9 lines
// glaurung: pk161_member_offset @ 0x1170
int32_t pk161_member_offset(int32_t arg0) {
    long ret;
    ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 7)));
    if (((unsigned long)((unsigned int)(ret)) != 7)) {
        ret = (unsigned long)((unsigned int)(((ret == 0) ? 0 : ((ret == 1) ? 4 : ((ret == 2) ? 8 : ((ret == 3) ? 10 : ((ret == 4) ? 0 : ((ret == 5) ? 1 : ((ret == 6) ? 5 : *(int *)((0x2000 + (ret * 4))))))))))));
    }
    return ret;
}
pk161_read_field pass 20 lines
// glaurung: pk161_read_field @ 0x1240
uint32_t pk161_read_field(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    long var1;
    long var2;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 7) | ((long)(arg1) < 7))) {
        return 0xffffffff;
    }
    var1 = (unsigned long)((unsigned int)((arg2 & 3)));
    var2 = *(long *)(((long)arg0));
    if (((unsigned long)((unsigned int)(var1)) == 1)) {
        return ((unsigned long)(var2) >> 8);
    }
    if (((unsigned long)((unsigned int)(var1)) == 2)) {
        return (unsigned int)((unsigned short)((((unsigned long)(var2) >> 40) & 0xffff)));
    }
    return (((unsigned long)((unsigned int)(var1)) == 0) ? (unsigned int)((unsigned char)((var2 & 255))) : ((unsigned long)(var2) >> 56));
}
pk161_roundtrip fail 52 lines
// glaurung: pk161_roundtrip @ 0x12a0
__attribute__((no_stack_protector)) int32_t pk161_roundtrip(uint32_t arg0, int32_t arg1) {
    extern int pk161_encode(char *, int, unsigned int, int);
    extern unsigned int pk161_read_field(char *, int, int);
    int i;
    int rc;
    long rbp;
    long rsp;
    long stack_2;
    unsigned char stack_5[16];
    int var13;
    long var15;
    long var16;
    unsigned int var17;
    long var22;
    unsigned int var23;
    long var7;
    long var8;
    rsp = (rsp - 8);
    rsp = (rsp - 8);
    var7 = (unsigned long)(arg0);
    rsp = (rsp - 8);
    stack_2 = rbp;
    rsp = (rsp - 8);
    var8 = (unsigned long)((unsigned int)(arg1));
    rsp = (rsp - 40);
    // stack canary: save guard to %stack_4
    rbp = rsp;
    *(int *)(&stack_5[0]) = 0;
    *(int *)((&stack_5[0] + 4)) = 0;
    *(int *)((&stack_5[0] + 8)) = 0;
    *(int *)((&stack_5[0] + 12)) = 0;
    var13 = ((int (*)(char *))pk161_encode)((char *)(rsp));
    var15 = (unsigned long)((unsigned int)(var13));
    var16 = (unsigned long)((unsigned int)(var13));
    if ((0 <= (long)((int)(var13)))) {
        var17 = pk161_read_field((char *)(rbp), 8, 1);
        if ((var17 != (unsigned long)((unsigned int)(var7)))) {
            var16 = 0xfffffffd;
        } else {
            var22 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) >> 8)));
            var23 = pk161_read_field((char *)(rbp), 8, 2);
            var16 = ((var23 != (unsigned long)((unsigned int)((unsigned short)((var22 & 0xffff))))) ? 0xfffffffc : var15);
        }
    }
    // stack-canary check
    rsp = (rsp + 40);
    rsp = (rsp + 8);
    rbp = stack_2;
    // x86-64 epilogue: tear down frame
    return (unsigned int)(var16);
}

clang -O0

5/5
pk161_encode pass 35 lines
// glaurung: pk161_encode @ 0x11d0
__attribute__((no_stack_protector)) int32_t pk161_encode(uint8_t * arg0, int32_t arg1, uint32_t arg2, int32_t arg3) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    extern int pk161_clamp(int);
    int limit;
    int sum;
    char * raw;
    int i;
    unsigned char local_28[8];
    void * var1;
    int var3;
    // x86-64 prologue: save rbp, frame 64 bytes
    var1 = memset((void *)(&local_28[0]), 0, (__SIZE_TYPE__)(8));
    var3 = pk161_clamp((unsigned long)((unsigned int)(arg1)));
    limit = var3;
    sum = 0;
    if ((arg0 != 0)) {
        if ((8 <= (long)(limit))) {
            *(signed char *)(&local_28[0]) = arg3;
            *(int *)((&local_28[0] + 1)) = arg2;
            *(short *)((&local_28[0] + 5)) = ((unsigned long)((unsigned int)(arg3)) >> 8);
            *(signed char *)((&local_28[0] + 7)) = ((unsigned int)(arg2) >> 24);
            raw = (char *)&local_28[0];
            for (i = 0; ((long)(i) < 8); i++) {
                arg0[i] = raw[i];
                sum = ((unsigned int)((unsigned char)(raw[i])) + sum);
            }
            return (unsigned int)(sum);
        } else {
            return (unsigned int)(-2);
        }
    } else {
        return (unsigned int)(-1);
    }
}
pk161_layout_delta pass 6 lines
// glaurung: pk161_layout_delta @ 0x1130
int32_t pk161_layout_delta(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 4;
}
pk161_member_offset pass 37 lines
// glaurung: pk161_member_offset @ 0x1140
int32_t pk161_member_offset(int32_t arg0) {
    long local_10;
    int local_4;
    long var2;
    // x86-64 prologue: save rbp
    var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 7)));
    local_10 = var2;
    if (((((unsigned long)((unsigned long)((unsigned int)(var2))) < (unsigned long)(6)) | ((unsigned long)((unsigned int)((var2 - 6))) == 0)) == 0)) {
        return 7;
    }
    switch (local_10) {
        case 0:
            local_4 = 0;
            break;
        case 1:
            local_4 = 4;
            break;
        case 2:
            local_4 = 8;
            break;
        case 3:
            local_4 = 10;
            break;
        case 4:
            local_4 = 0;
            break;
        case 5:
            local_4 = 1;
            break;
        case 6:
            local_4 = 5;
            break;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
pk161_read_field pass 44 lines
// glaurung: pk161_read_field @ 0x1300
__attribute__((no_stack_protector)) uint32_t pk161_read_field(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    extern int pk161_clamp(int);
    int limit;
    char * raw;
    int i;
    unsigned char local_20[8];
    int local_34;
    void * var1;
    int var16;
    int var3;
    // x86-64 prologue: save rbp, frame 64 bytes
    var1 = memset((void *)(&local_20[0]), 0, (__SIZE_TYPE__)(8));
    var3 = pk161_clamp((unsigned long)((unsigned int)(arg1)));
    limit = var3;
    if ((arg0 != 0)) {
        if ((8 <= (long)(limit))) {
            raw = (char *)&local_20[0];
            for (i = 0; ((long)(i) < 8); i++) {
                raw[i] = arg0[i];
            }
            var16 = ((unsigned int)(arg2) & 3);
            local_34 = var16;
            if (((unsigned long)((unsigned int)(var16)) == 0)) {
                return (unsigned int)((unsigned char)(*(char *)(&local_20[0])));
            } else {
                if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_34)) - 1))) == 0)) {
                    return (unsigned int)(*(int *)((&local_20[0] + 1)));
                } else {
                    if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_34)) - 2))) == 0)) {
                        return (unsigned int)((unsigned short)(*(short *)((&local_20[0] + 5))));
                    } else {
                        return (unsigned int)((unsigned char)(*(char *)((&local_20[0] + 7))));
                    }
                }
            }
        } else {
            return (unsigned int)(-1);
        }
    } else {
        return (unsigned int)(-1);
    }
}
pk161_roundtrip pass 32 lines
// glaurung: pk161_roundtrip @ 0x1400
__attribute__((no_stack_protector)) int32_t pk161_roundtrip(uint32_t arg0, int32_t arg1) {
    extern int pk161_encode(char *, int, unsigned int, int);
    extern unsigned int pk161_read_field(char *, int, int);
    int i;
    int rc;
    unsigned char local_20[16];
    int var4;
    unsigned int var6;
    unsigned int var8;
    // x86-64 prologue: save rbp, frame 48 bytes
    for (i = 0; ((long)(i) < 16); i++) {
        *(signed char *)((&local_20[0] + (long)(i))) = 0;
    }
    var4 = pk161_encode((char *)(&local_20[0]), 8, arg0, (unsigned long)((unsigned int)(arg1)));
    rc = var4;
    if ((0 <= (long)(rc))) {
        var6 = pk161_read_field((char *)(&local_20[0]), 8, 1);
        if ((var6 == arg0)) {
            var8 = pk161_read_field((char *)(&local_20[0]), 8, 2);
            if ((var8 == (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 8))) & 0xffff))))) {
                return (unsigned int)(rc);
            } else {
                return (unsigned int)(-4);
            }
        } else {
            return (unsigned int)(-3);
        }
    } else {
        return (unsigned int)(rc);
    }
}

gcc -O0

5/5
pk161_encode pass 45 lines
// glaurung: pk161_encode @ 0x1203
int32_t pk161_encode(uint8_t * arg0, int32_t arg1, uint32_t arg2, int32_t arg3) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int pk161_clamp(int);
    int limit;
    int sum;
    char * raw;
    int i;
    unsigned char local_10[8];
    long local_8;
    long ret;
    int var4;
    // x86-64 prologue: save rbp, frame 80 bytes
    local_8 = (long)(0x28);
    *(signed char *)(&local_10[0]) = 0;
    *(int *)((&local_10[0] + 1)) = 0;
    *(short *)((&local_10[0] + 5)) = 0;
    *(signed char *)((&local_10[0] + 7)) = 0;
    var4 = pk161_clamp((unsigned long)((unsigned int)(arg1)));
    limit = var4;
    sum = 0;
    if ((arg0 != 0)) {
        if (((((unsigned long)((unsigned int)(limit)) == 7) | ((long)(limit) < 7)) == 0)) {
            *(signed char *)(&local_10[0]) = arg3;
            *(int *)((&local_10[0] + 1)) = arg2;
            *(short *)((&local_10[0] + 5)) = ((unsigned long)((unsigned int)(arg3)) >> 8);
            *(signed char *)((&local_10[0] + 7)) = ((unsigned int)(arg2) >> 24);
            raw = (char *)&local_10[0];
            for (i = 0; ((((unsigned long)((unsigned int)(i)) == 7) | ((long)(i) < 7)) != 0); i++) {
                arg0[i] = raw[i];
                sum = (sum + (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(raw[i])) & 255))));
            }
            ret = (unsigned long)((unsigned int)(sum));
        } else {
            ret = 0xfffffffe;
        }
    } else {
        ret = 0xffffffff;
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
pk161_layout_delta pass 6 lines
// glaurung: pk161_layout_delta @ 0x1183
int32_t pk161_layout_delta(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 4;
}
pk161_member_offset pass 23 lines
// glaurung: pk161_member_offset @ 0x1192
int32_t pk161_member_offset(int32_t arg0) {
    // x86-64 prologue: save rbp
    switch ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 7)))) {
        case 0:
            return 0;
        case 1:
            return 4;
        case 2:
            return 8;
        case 3:
            return 10;
        case 4:
            return 0;
        case 5:
            return 1;
        case 6:
            return 5;
        default:
            return 7;
    }
    // x86-64 epilogue: restore rbp
}
pk161_read_field pass 57 lines
// glaurung: pk161_read_field @ 0x12f7
uint32_t pk161_read_field(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int pk161_clamp(int);
    int limit;
    char * raw;
    int i;
    unsigned char local_10[8];
    long local_8;
    long ret;
    long var18;
    int var4;
    // x86-64 prologue: save rbp, frame 48 bytes
    local_8 = (long)(0x28);
    *(signed char *)(&local_10[0]) = 0;
    *(int *)((&local_10[0] + 1)) = 0;
    *(short *)((&local_10[0] + 5)) = 0;
    *(signed char *)((&local_10[0] + 7)) = 0;
    var4 = pk161_clamp((unsigned long)((unsigned int)(arg1)));
    limit = var4;
    if ((arg0 != 0)) {
        if (((((unsigned long)((unsigned int)(limit)) == 7) | ((long)(limit) < 7)) == 0)) {
            raw = (char *)&local_10[0];
            for (i = 0; ((((unsigned long)((unsigned int)(i)) == 7) | ((long)(i) < 7)) != 0); i++) {
                raw[i] = arg0[i];
            }
            var18 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) & 3)));
            if (((unsigned long)((unsigned int)(var18)) == 2)) {
                ret = (unsigned int)((unsigned short)(((unsigned int)((unsigned short)(*(short *)((&local_10[0] + 5)))) & 0xffff)));
            } else {
                if (((((unsigned long)((unsigned int)(var18)) == 2) | ((long)((int)(var18)) < 2)) == 0)) {
                    L_13c8: ;
                    ret = (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)((&local_10[0] + 7)))) & 255)));
                } else {
                    if (((unsigned long)((unsigned int)(var18)) == 0)) {
                        ret = (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)(&local_10[0]))) & 255)));
                    } else {
                        if (((unsigned long)((unsigned int)(var18)) == 1)) {
                            ret = (unsigned long)((unsigned int)(*(int *)((&local_10[0] + 1))));
                        } else {
                            goto L_13c8;
                        }
                    }
                }
            }
        } else {
            ret = 0xffffffff;
        }
    } else {
        ret = 0xffffffff;
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
pk161_roundtrip pass 37 lines
// glaurung: pk161_roundtrip @ 0x13e5
int32_t pk161_roundtrip(uint32_t arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int pk161_encode(char *, int, unsigned int, int);
    extern unsigned int pk161_read_field(char *, int, int);
    int i;
    int rc;
    unsigned char local_20[16];
    long local_8;
    long ret;
    unsigned int var12;
    int var6;
    unsigned int var9;
    // x86-64 prologue: save rbp, frame 64 bytes
    local_8 = (long)(0x28);
    for (i = 0; ((((unsigned long)((unsigned int)(i)) == 15) | ((long)(i) < 15)) != 0); i++) {
        *(signed char *)((&local_20[0] + (long)(i))) = 0;
    }
    var6 = pk161_encode((char *)(&local_20[0]), 8, arg0, (unsigned long)((unsigned int)(arg1)));
    rc = var6;
    if ((0 <= (long)(rc))) {
        var9 = pk161_read_field((char *)(&local_20[0]), 8, 1);
        if ((arg0 == var9)) {
            var12 = pk161_read_field((char *)(&local_20[0]), 8, 2);
            ret = ((var12 == (unsigned long)((unsigned int)((unsigned short)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 8))) & 0xffff))))) ? (unsigned long)((unsigned int)(rc)) : 0xfffffffc);
        } else {
            ret = 0xfffffffd;
        }
    } else {
        ret = (unsigned long)((unsigned int)(rc));
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}

← 213 fixtures