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.
/* 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/5tlv164_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/5tlv164_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/5tlv164_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/5tlv164_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;
}