Fixture 164

nested tlv walker

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

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

Nested type-length-value, the shape that BER/DER, USB descriptors, ISO 8583, Bluetooth advertising data and half of firmware-land all share:

node := type:u8 len:u8 value[len]

A type with bit 7 set is a CONTAINER: its value is itself a TLV sequence, walked recursively. Everything else is a leaf whose value bytes are data. A sequence is well formed only if the nodes tile it EXACTLY -- no trailing bytes, no node whose value runs past the end of its enclosing container.

Why this stresses a decompiler: the bound at every step is not the buffer, it is the *current container*, and that bound is re-derived on each recursion from the parent's own length field. Lowered, this is a family of nearly identical compares against different registers, and the recursion is a self-call whose arguments (p + body, vlen, depth + 1) carry the whole safety argument. A decompiler that reconstructs the bound from the outer buffer length instead of the container length, or that loses + 2 when advancing past a node header, emits C that walks every well-formed message identically and reads out of bounds on a nested length that lies. The "exactly tiles" check (-3) is what makes such a slip observable at all: with a merely permissive walker, an off-by-one just silently sees a different node count.

UB notes: len is clamped to [0, 16] before use, so every subtraction below is on small non-negative values. Recursion depth is capped at 4 and every node advances the cursor by at least 2 bytes, so the walk always terminates; a redundant iteration guard makes that bound explicit rather than implied.

tests/decompiler_fixtures/src/164_nested_tlv_walker.c source
/* 164_nested_tlv_walker.c
 *
 * Nested type-length-value, the shape that BER/DER, USB descriptors, ISO 8583,
 * Bluetooth advertising data and half of firmware-land all share:
 *
 *   node := type:u8  len:u8  value[len]
 *
 * A type with bit 7 set is a CONTAINER: its value is itself a TLV sequence,
 * walked recursively. Everything else is a leaf whose value bytes are data.
 * A sequence is well formed only if the nodes tile it EXACTLY -- no trailing
 * bytes, no node whose value runs past the end of its enclosing container.
 *
 * Why this stresses a decompiler: the bound at every step is not the buffer, it
 * is the *current container*, and that bound is re-derived on each recursion
 * from the parent's own length field. Lowered, this is a family of nearly
 * identical compares against different registers, and the recursion is a
 * self-call whose arguments (`p + body`, `vlen`, `depth + 1`) carry the whole
 * safety argument. A decompiler that reconstructs the bound from the outer
 * buffer length instead of the container length, or that loses `+ 2` when
 * advancing past a node header, emits C that walks every well-formed message
 * identically and reads out of bounds on a nested length that lies. The
 * "exactly tiles" check (-3) is what makes such a slip observable at all: with
 * a merely permissive walker, an off-by-one just silently sees a different
 * node count.
 *
 * UB notes: `len` is clamped to [0, 16] before use, so every subtraction below
 * is on small non-negative values. Recursion depth is capped at 4 and every
 * node advances the cursor by at least 2 bytes, so the walk always terminates;
 * a redundant iteration guard makes that bound explicit rather than implied.
 */
#include <stddef.h>
#include <stdint.h>

#define TLV164_MAX_BUF   16
#define TLV164_MAX_DEPTH 4
#define TLV164_CONTAINER 0x80u
#define TLV164_HDR_BYTES 2
#define TLV164_HIT_BASE  1000

/* Clamp a caller length into [0, TLV164_MAX_BUF] before any arithmetic. */
static int32_t tlv164_clamp(int32_t n) {
    if (n < 0) {
        return 0;
    }
    if (n > TLV164_MAX_BUF) {
        return TLV164_MAX_BUF;
    }
    return n;
}

/* Walk [p, p + limit) as a TLV sequence at nesting level `depth`.
 * Returns the number of nodes (>= 0) or a distinct negative code, accumulating
 * the deepest level reached in *deepest and every leaf byte into *leaf_sum. */
static int32_t tlv164_walk(const uint8_t *p, int32_t limit, int32_t depth,
                           int32_t *deepest, int32_t *leaf_sum) {
    int32_t cursor = 0;
    int32_t nodes = 0;
    int32_t guard = 0;

    if (depth > TLV164_MAX_DEPTH) {
        return -4; /* nesting deeper than this parser will follow */
    }
    if (depth > *deepest) {
        *deepest = depth;
    }

    while (cursor + TLV164_HDR_BYTES <= limit) {
        uint32_t type = (uint32_t)p[cursor];
        int32_t value_len = (int32_t)p[cursor + 1];
        int32_t body = cursor + TLV164_HDR_BYTES;

        guard++;
        if (guard > TLV164_MAX_BUF) {
            return -5; /* unreachable while every node advances >= 2 bytes */
        }
        /* The bound is the ENCLOSING CONTAINER, not the outermost buffer. */
        if (value_len > limit - body) {
            return -2;
        }
        nodes++;
        if ((type & TLV164_CONTAINER) != 0u) {
            int32_t inner =
                tlv164_walk(p + body, value_len, depth + 1, deepest, leaf_sum);
            if (inner < 0) {
                return inner;
            }
            nodes += inner;
        } else {
            int32_t i;
            for (i = 0; i < value_len; i++) {
                *leaf_sum += (int32_t)p[body + i];
            }
        }
        cursor = body + value_len;
    }
    if (cursor != limit) {
        return -3; /* trailing bytes that are not a complete node */
    }
    return nodes;
}

/* Depth-first search for the first node of type `want`, at any nesting level.
 * Returns TLV164_HIT_BASE + first value byte for a non-empty match,
 * TLV164_HIT_BASE for an empty one, 0 when absent, or a negative code. */
static int32_t tlv164_seek(const uint8_t *p, int32_t limit, int32_t depth,
                           uint32_t want) {
    int32_t cursor = 0;
    int32_t guard = 0;

    if (depth > TLV164_MAX_DEPTH) {
        return -4;
    }

    while (cursor + TLV164_HDR_BYTES <= limit) {
        uint32_t type = (uint32_t)p[cursor];
        int32_t value_len = (int32_t)p[cursor + 1];
        int32_t body = cursor + TLV164_HDR_BYTES;

        guard++;
        if (guard > TLV164_MAX_BUF) {
            return -5;
        }
        if (value_len > limit - body) {
            return -2;
        }
        if (type == want) {
            return (value_len > 0) ? TLV164_HIT_BASE + (int32_t)p[body]
                                   : TLV164_HIT_BASE;
        }
        if ((type & TLV164_CONTAINER) != 0u) {
            int32_t hit = tlv164_seek(p + body, value_len, depth + 1, want);
            if (hit != 0) {
                return hit;
            }
        }
        cursor = body + value_len;
    }
    return 0;
}

/* Total node count over the whole nesting tree, or a negative code. */
__attribute__((noinline)) int32_t
tlv164_node_count(const uint8_t *buf, int32_t len) {
    int32_t deepest = 0;
    int32_t leaf_sum = 0;

    if (buf == NULL) {
        return -1;
    }
    return tlv164_walk(buf, tlv164_clamp(len), 0, &deepest, &leaf_sum);
}

/* Deepest nesting level reached (0 for a flat sequence), or a negative code. */
__attribute__((noinline)) int32_t
tlv164_max_depth(const uint8_t *buf, int32_t len) {
    int32_t deepest = 0;
    int32_t leaf_sum = 0;
    int32_t rc;

    if (buf == NULL) {
        return -1;
    }
    rc = tlv164_walk(buf, tlv164_clamp(len), 0, &deepest, &leaf_sum);
    return (rc < 0) ? rc : deepest;
}

/* Sum of every LEAF value byte -- container headers and container payload
 * framing bytes must not contribute. Returns a positive summary or a code. */
__attribute__((noinline)) int32_t
tlv164_leaf_sum(const uint8_t *buf, int32_t len) {
    int32_t deepest = 0;
    int32_t leaf_sum = 0;
    int32_t rc;

    if (buf == NULL) {
        return -1;
    }
    rc = tlv164_walk(buf, tlv164_clamp(len), 0, &deepest, &leaf_sum);
    return (rc < 0) ? rc : (TLV164_HIT_BASE + leaf_sum * 10 + rc);
}

/* Depth-first lookup by node type. */
__attribute__((noinline)) int32_t
tlv164_find_type(const uint8_t *buf, int32_t len, int32_t want_type) {
    if (buf == NULL) {
        return -1;
    }
    return tlv164_seek(buf, tlv164_clamp(len), 0,
                       (uint32_t)want_type & 0xFFu);
}

/* Emit container{leaf} so the accepting path is reachable without a hand-built
 * vector. Returns the total encoded size, or a negative code. */
__attribute__((noinline)) int32_t
tlv164_encode_nested(uint8_t *out, int32_t out_len, int32_t inner_type,
                     int32_t inner_len) {
    int32_t room = tlv164_clamp(out_len);
    int32_t value_len = inner_len;
    int32_t total;
    int32_t i;

    if (out == NULL) {
        return -1;
    }
    if (value_len < 0) {
        value_len = 0;
    }
    if (value_len > 4) {
        value_len = 4;
    }
    total = TLV164_HDR_BYTES + TLV164_HDR_BYTES + value_len;
    if (room < total) {
        return -2;
    }
    out[0] = 0x81u;                                   /* container type */
    out[1] = (uint8_t)(TLV164_HDR_BYTES + value_len); /* container length */
    /* Clear bit 7 so the inner node is always a leaf, whatever was asked. */
    out[2] = (uint8_t)((uint32_t)inner_type & 0x7Fu);
    out[3] = (uint8_t)value_len;
    for (i = 0; i < value_len; i++) {
        out[TLV164_HDR_BYTES + TLV164_HDR_BYTES + i] =
            (uint8_t)(0x10u + (uint32_t)i);
    }
    return total;
}

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

2/5
tlv164_encode_nested pass 45 lines
// glaurung: tlv164_encode_nested @ 0x14f0
int32_t tlv164_encode_nested(uint8_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    int value_len;
    int total;
    int i;
    int room;
    long ret;
    long var1;
    int var13;
    int var5;
    var1 = (((long)(arg1) < 16) ? arg1 : 16);
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var5 = ((0 <= (long)(arg3)) ? arg3 : 0);
    value_len = (((unsigned long)((unsigned long)((unsigned int)(var5))) < (unsigned long)(4)) ? var5 : 4);
    total = (unsigned long)((unsigned int)((value_len + 4)));
    ret = 0xfffffffe;
    if (((unsigned long)((unsigned long)((unsigned int)((((long)((int)(var1)) < 0) ? 0 : var1)))) < (unsigned long)((unsigned long)((unsigned int)(total))))) {
        return ret;
    }
    *(signed char *)(((long)arg0)) = -127;
    *(signed char *)(((long)arg0 + 0x1)) = (value_len + 2);
    *(signed char *)(((long)arg0 + 0x2)) = (arg2 & 127);
    *(signed char *)(((long)arg0 + 0x3)) = value_len;
    if (((((unsigned long)((unsigned int)(arg3)) == 0) | ((long)(arg3) < 0)) != 0)) {
        if (((unsigned long)((unsigned long)((unsigned int)(var5))) < (unsigned long)(4))) {
            return (unsigned int)(total);
        }
    }
    *(signed char *)(((long)arg0 + 0x4)) = 16;
    var13 = ((2 <= (long)(value_len)) ? value_len : 1);
    if ((2 <= (long)(value_len))) {
        *(signed char *)(((long)arg0 + 0x5)) = 17;
        if (((unsigned long)((unsigned int)(var13)) == 2)) {
            return (unsigned int)(total);
        }
        *(signed char *)(((long)arg0 + 0x6)) = 18;
        if (((unsigned long)((unsigned int)(var13)) == 3)) {
            return (unsigned int)(total);
        }
        *(signed char *)(((long)arg0 + 0x7)) = 19;
    }
    return (unsigned int)(total);
}
tlv164_find_type fail 12 lines
// glaurung: tlv164_find_type @ 0x13d0
int32_t tlv164_find_type(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern int tlv164_seek(char *, long, int, unsigned int);
    int ret;
    long var1;
    if ((arg0 != 0)) {
        var1 = (((long)(arg1) < 16) ? arg1 : 16);
        ret = tlv164_seek((char *)(arg0), (unsigned long)((unsigned int)((((long)((int)(var1)) < 0) ? 0 : var1))), 0, (unsigned int)((unsigned char)((arg2 & 255))));
        return ret;
    }
    return 0xffffffff;
}
tlv164_leaf_sum pass 26 lines
// glaurung: tlv164_leaf_sum @ 0x1360
__attribute__((no_stack_protector)) int32_t tlv164_leaf_sum(const uint8_t * arg0, int32_t arg1) {
    extern int tlv164_walk(char *, int, int, int *, int *);
    int deepest;
    int leaf_sum;
    int rc;
    unsigned char local_10[4];
    unsigned char local_c[4];
    long var1;
    long var10;
    long var3;
    int var6;
    long var9;
    *(int *)(&local_c[0]) = 0;
    *(int *)(&local_10[0]) = 0;
    if ((arg0 == 0)) {
        return 0xffffffff;
    } else {
        var1 = (((long)(arg1) < 16) ? arg1 : 16);
        var3 = 0;
        var6 = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)((((long)((int)(var1)) < 0) ? 0 : var1))), 0, (int *)(&local_c[0]), (int *)(&local_10[0]));
        var9 = (unsigned long)((unsigned int)(*(int *)(&local_10[0])));
        var10 = (unsigned long)((unsigned int)((var9 + (var9 * 4))));
        return (unsigned int)(((((long)((int)(var6)) < 0) ? var3 : (unsigned long)((unsigned int)(((var10 + var10) + 1000)))) + (unsigned long)((unsigned int)(var6))));
    }
}
tlv164_max_depth fail 29 lines
// glaurung: tlv164_max_depth @ 0x1310
__attribute__((no_stack_protector)) int32_t tlv164_max_depth(const uint8_t * arg0, int32_t arg1) {
    extern int tlv164_walk(char *, int, int, int *, int *);
    int deepest;
    int leaf_sum;
    int rc;
    unsigned char local_4[8];
    long local_8;
    long ret;
    long rsp;
    long var2;
    int var7;
    rsp = (rsp - 8);
    local_8 = ret;
    local_8 = 0;
    *(int *)(&local_4[0]) = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    var2 = (((long)(arg1) < 16) ? arg1 : 16);
    var7 = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)((((long)((int)(var2)) < 0) ? 0 : var2))), 0, (int *)(rsp), (int *)(&local_4[0]));
    ret = (unsigned long)((unsigned int)(var7));
    if ((0 <= (long)((int)(var7)))) {
        ret = (unsigned long)((unsigned int)(local_8));
    }
    // x86-64 epilogue: tear down frame
    return ret;
}
tlv164_node_count fail 23 lines
// glaurung: tlv164_node_count @ 0x1100
__attribute__((no_stack_protector)) int32_t tlv164_node_count(const uint8_t * arg0, int32_t arg1) {
    extern int tlv164_walk(char *, int, int, int *, int *);
    int deepest;
    int leaf_sum;
    unsigned char local_4[8];
    int local_8;
    int ret;
    long rsp;
    long var2;
    rsp = (rsp - 8);
    local_8 = ret;
    *(int *)(&local_4[0]) = 0;
    local_8 = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    var2 = (((long)(arg1) < 16) ? arg1 : 16);
    ret = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)((((long)((int)(var2)) < 0) ? 0 : var2))), 0, (int *)(&local_4[0]), (int *)(rsp));
    // x86-64 epilogue: tear down frame
    return ret;
}

gcc -O2

4/5
tlv164_encode_nested pass 35 lines
// glaurung: tlv164_encode_nested @ 0x1550
int32_t tlv164_encode_nested(uint8_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    int value_len;
    int total;
    int i;
    int room;
    long var1;
    long var17;
    long var2;
    long var9;
    var1 = (long)arg0;
    var2 = (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1);
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var9 = ((((unsigned long)((unsigned int)(arg3)) == 4) | ((long)(arg3) < 4)) ? arg3 : 4);
    value_len = (((long)((int)(var9)) < 0) ? 0 : var9);
    total = (unsigned long)((unsigned int)((value_len + 4)));
    if (((((long)((int)(var2)) < 0) ? 0 : var2) < total)) {
        return 0xfffffffe;
    }
    *(signed char *)((long)arg0) = -127;
    *(signed char *)((var1 + 0x1)) = (value_len + 2);
    *(signed char *)((var1 + 0x2)) = (arg2 & 127);
    *(signed char *)((var1 + 0x3)) = value_len;
    if ((((unsigned long)((unsigned int)(arg3)) != 0) && (0 <= (long)(arg3)))) {
        i = 0;
        do {
            *(signed char *)((var1 + i + 0x4)) = (i + 16);
            var17 = ((unsigned long)((unsigned int)(i)) + 1);
            i = var17;
        } while (((((unsigned int)(value_len) == (unsigned int)(var17)) | ((long)(value_len) < (long)((int)(var17)))) == 0));
    }
    return (unsigned int)(total);
}
tlv164_find_type pass 10 lines
// glaurung: tlv164_find_type @ 0x1520
int32_t tlv164_find_type(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern int tlv164_seek(char *, int, int, unsigned int);
    int ret;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    ret = tlv164_seek((char *)(arg0), (((long)((int)((((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1))) < 0) ? 0 : (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1)), 0, (unsigned int)((unsigned char)((arg2 & 255))));
    return ret;
}
tlv164_leaf_sum pass 28 lines
// glaurung: tlv164_leaf_sum @ 0x14a0
int32_t tlv164_leaf_sum(const uint8_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char deepest[4];
    unsigned char leaf_sum[4];
    int rc;
    long local_10;
    long var10;
    int var9;
    local_10 = (long)(0x28);
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 == 0)) {
        rc = 0xffffffff;
    } else {
        var9 = tlv164_walk((char *)(arg0), (((long)((int)((((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1))) < 0) ? 0 : (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        rc = (unsigned long)((unsigned int)(var9));
        if ((0 <= (long)((int)(var9)))) {
            var10 = (unsigned long)((unsigned int)(*(int *)(&leaf_sum[0])));
            rc = (unsigned long)((unsigned int)(((var9 + ((unsigned long)((unsigned int)((var10 + (var10 * 4)))) * 2)) + 1000)));
        }
    }
    if ((local_10 != 0x28)) {
        __stack_chk_fail();
    }
    return rc;
}
tlv164_max_depth fail 24 lines
// glaurung: tlv164_max_depth @ 0x1420
int32_t tlv164_max_depth(const uint8_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char deepest[4];
    unsigned char leaf_sum[4];
    int rc;
    long local_10;
    long ret;
    int var9;
    local_10 = (long)(0x28);
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 == 0)) {
        ret = 0xffffffff;
    } else {
        var9 = tlv164_walk((char *)(arg0), (((long)((int)((((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1))) < 0) ? 0 : (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        ret = ((0 <= (long)((int)(var9))) ? *(int *)(&deepest[0]) : var9);
    }
    if ((local_10 != 0x28)) {
        __stack_chk_fail();
    }
    return ret;
}
tlv164_node_count pass 23 lines
// glaurung: tlv164_node_count @ 0x13b0
int32_t tlv164_node_count(const uint8_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char deepest[4];
    unsigned char leaf_sum[4];
    long local_10;
    long ret;
    int var8;
    local_10 = (long)(0x28);
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 == 0)) {
        ret = 0xffffffff;
    } else {
        var8 = tlv164_walk((char *)(arg0), (((long)((int)((((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1))) < 0) ? 0 : (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0) ? 16 : arg1)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        ret = (unsigned long)((unsigned int)(var8));
    }
    if ((local_10 != 0x28)) {
        __stack_chk_fail();
    }
    return ret;
}

clang -O0

5/5
tlv164_encode_nested pass 36 lines
// glaurung: tlv164_encode_nested @ 0x1650
int32_t tlv164_encode_nested(uint8_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int tlv164_clamp(int);
    int room;
    int value_len;
    int total;
    int i;
    int var0;
    // x86-64 prologue: save rbp, frame 48 bytes
    var0 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
    room = var0;
    value_len = arg3;
    if ((arg0 != 0)) {
        if (((long)(value_len) < 0)) {
            value_len = 0;
        }
        if (((((unsigned long)((unsigned int)(value_len)) == 4) | ((long)(value_len) < 4)) == 0)) {
            value_len = 4;
        }
        total = ((unsigned int)(value_len) + 4);
        if ((total <= room)) {
            *(signed char *)((long)arg0) = -127;
            *(signed char *)(((long)arg0 + 0x1)) = ((unsigned long)((unsigned int)(value_len)) + 2);
            *(signed char *)(((long)arg0 + 0x2)) = ((unsigned long)((unsigned int)(arg2)) & 127);
            *(signed char *)(((long)arg0 + 0x3)) = value_len;
            for (i = 0; (i < value_len); i++) {
                arg0[(long)((int)(((unsigned long)((unsigned int)(i)) + 4)))] = ((unsigned long)((unsigned int)(i)) + 16);
            }
            return (unsigned int)(total);
        } else {
            return (unsigned int)(-2);
        }
    } else {
        return (unsigned int)(-1);
    }
}
tlv164_find_type pass 15 lines
// glaurung: tlv164_find_type @ 0x1480
int32_t tlv164_find_type(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern int tlv164_clamp(int);
    extern int tlv164_seek(char *, int, int, unsigned int);
    int var1;
    int var6;
    // x86-64 prologue: save rbp, frame 32 bytes
    if ((arg0 != 0)) {
        var1 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
        var6 = tlv164_seek((char *)(arg0), (unsigned long)((unsigned int)(var1)), 0, (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) & 255))));
        return (unsigned int)(var6);
    } else {
        return (unsigned int)(-1);
    }
}
tlv164_leaf_sum pass 23 lines
// glaurung: tlv164_leaf_sum @ 0x13f0
__attribute__((no_stack_protector)) int32_t tlv164_leaf_sum(const uint8_t * arg0, int32_t arg1) {
    extern int tlv164_clamp(int);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char deepest[4];
    unsigned char leaf_sum[4];
    int rc;
    int local_2c;
    int var1;
    int var4;
    // x86-64 prologue: save rbp, frame 48 bytes
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 != 0)) {
        var1 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
        var4 = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)(var1)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        rc = var4;
        local_2c = ((0 <= (long)(rc)) ? ((unsigned long)((unsigned int)(((*(int *)(&leaf_sum[0]) * 10) + 1000))) + (unsigned long)((unsigned int)(rc))) : (unsigned long)((unsigned int)(rc)));
        return (unsigned int)(local_2c);
    } else {
        return (unsigned int)(-1);
    }
}
tlv164_max_depth pass 23 lines
// glaurung: tlv164_max_depth @ 0x1360
__attribute__((no_stack_protector)) int32_t tlv164_max_depth(const uint8_t * arg0, int32_t arg1) {
    extern int tlv164_clamp(int);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char deepest[4];
    unsigned char leaf_sum[4];
    int rc;
    int local_2c;
    int var1;
    int var4;
    // x86-64 prologue: save rbp, frame 48 bytes
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 != 0)) {
        var1 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
        var4 = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)(var1)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        rc = var4;
        local_2c = ((0 <= (long)(rc)) ? *(int *)(&deepest[0]) : rc);
        return (unsigned int)(local_2c);
    } else {
        return (unsigned int)(-1);
    }
}
tlv164_node_count pass 19 lines
// glaurung: tlv164_node_count @ 0x1100
__attribute__((no_stack_protector)) int32_t tlv164_node_count(const uint8_t * arg0, int32_t arg1) {
    extern int tlv164_clamp(int);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char deepest[4];
    unsigned char leaf_sum[4];
    int var1;
    int var4;
    // x86-64 prologue: save rbp, frame 48 bytes
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 != 0)) {
        var1 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
        var4 = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)(var1)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        return (unsigned int)(var4);
    } else {
        return (unsigned int)(-1);
    }
}

gcc -O0

5/5
tlv164_encode_nested pass 36 lines
// glaurung: tlv164_encode_nested @ 0x15ef
int32_t tlv164_encode_nested(uint8_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int tlv164_clamp(int);
    int room;
    int value_len;
    int total;
    int i;
    int var1;
    // x86-64 prologue: save rbp, frame 40 bytes
    var1 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
    room = var1;
    value_len = arg3;
    if ((arg0 != 0)) {
        if (((long)(value_len) < 0)) {
            value_len = 0;
        }
        if (((((unsigned long)((unsigned int)(value_len)) == 4) | ((long)(value_len) < 4)) == 0)) {
            value_len = 4;
        }
        total = ((unsigned int)(value_len) + 4);
        if ((total <= room)) {
            *(signed char *)((long)arg0) = -127;
            arg0[1] = ((unsigned long)((unsigned int)(value_len)) + 2);
            arg0[2] = ((unsigned long)((unsigned int)(arg2)) & 127);
            arg0[3] = value_len;
            for (i = 0; (i < value_len); i++) {
                arg0[(long)((int)(((unsigned long)((unsigned int)(i)) + 4)))] = ((unsigned long)((unsigned int)(i)) + 16);
            }
            return (unsigned int)(total);
        } else {
            return 0xfffffffe;
        }
    } else {
        return 0xffffffff;
    }
}
tlv164_find_type pass 17 lines
// glaurung: tlv164_find_type @ 0x159f
int32_t tlv164_find_type(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern int tlv164_clamp(int);
    extern int tlv164_seek(char *, int, int, unsigned int);
    int var1;
    int var3;
    int var6;
    // x86-64 prologue: save rbp, frame 8 bytes
    if ((arg0 != 0)) {
        var1 = (unsigned int)((unsigned char)(((unsigned long)((unsigned int)(arg2)) & 255)));
        var3 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
        var6 = tlv164_seek((char *)(arg0), (unsigned long)((unsigned int)(var3)), 0, (unsigned long)((unsigned int)(var1)));
        return var6;
    } else {
        return 0xffffffff;
    }
}
tlv164_leaf_sum pass 37 lines
// glaurung: tlv164_leaf_sum @ 0x14fb
int32_t tlv164_leaf_sum(const uint8_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int tlv164_clamp(int);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char leaf_sum[16];
    unsigned char deepest[4];
    int rc;
    long ret;
    long var11;
    int var15;
    int var4;
    int var9;
    // x86-64 prologue: save rbp, frame 48 bytes
    *(long *)((&leaf_sum[0] + 8)) = (long)((long)(0x28));
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 != 0)) {
        var4 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
        var9 = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)(var4)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        rc = var9;
        if (((long)(rc) < 0)) {
            ret = (unsigned long)((unsigned int)(rc));
        } else {
            var11 = (unsigned long)((unsigned int)(*(int *)(&leaf_sum[0])));
            var15 = ((unsigned int)(((unsigned long)((unsigned int)(var11)) << 2)) + var11);
            ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(rc)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var15)) + (unsigned long)((unsigned int)(var15))))) + 1000))))));
        }
    } else {
        ret = 0xffffffff;
    }
    if ((*(long *)((&leaf_sum[0] + 8)) != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
tlv164_max_depth pass 29 lines
// glaurung: tlv164_max_depth @ 0x146b
int32_t tlv164_max_depth(const uint8_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int tlv164_clamp(int);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char leaf_sum[16];
    unsigned char deepest[4];
    int rc;
    long ret;
    int var4;
    int var9;
    // x86-64 prologue: save rbp, frame 48 bytes
    *(long *)((&leaf_sum[0] + 8)) = (long)((long)(0x28));
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 != 0)) {
        var4 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
        var9 = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)(var4)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        rc = var9;
        ret = ((0 <= (long)(rc)) ? (unsigned long)((unsigned int)(*(int *)(&deepest[0]))) : (unsigned long)((unsigned int)(rc)));
    } else {
        ret = 0xffffffff;
    }
    if ((*(long *)((&leaf_sum[0] + 8)) != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
tlv164_node_count pass 27 lines
// glaurung: tlv164_node_count @ 0x13ec
int32_t tlv164_node_count(const uint8_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    extern int tlv164_clamp(int);
    extern int tlv164_walk(char *, int, int, int *, int *);
    unsigned char leaf_sum[12];
    unsigned char deepest[4];
    long ret;
    int var4;
    int var9;
    // x86-64 prologue: save rbp, frame 32 bytes
    *(long *)((&leaf_sum[0] + 4)) = (long)((long)(0x28));
    *(int *)(&deepest[0]) = 0;
    *(int *)(&leaf_sum[0]) = 0;
    if ((arg0 != 0)) {
        var4 = tlv164_clamp((unsigned long)((unsigned int)(arg1)));
        var9 = tlv164_walk((char *)(arg0), (unsigned long)((unsigned int)(var4)), 0, (int *)(&deepest[0]), (int *)(&leaf_sum[0]));
        ret = (unsigned long)((unsigned int)(var9));
    } else {
        ret = 0xffffffff;
    }
    if ((*(long *)((&leaf_sum[0] + 4)) != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}

← 213 fixtures