Fixture 86

flexible array member

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

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

C99 flexible array members: the trailing int32_t items[] contributes nothing to sizeof, so the header size and the element stride must both be recovered to walk the payload correctly.

tests/decompiler_fixtures/src/86_flexible_array_member.c source
#include <stdint.h>

/* C99 flexible array members: the trailing `int32_t items[]` contributes
 * nothing to sizeof, so the header size and the element stride must both be
 * recovered to walk the payload correctly. */

struct Packet {
    int32_t length;
    int32_t tag;
    int32_t items[];
};

__attribute__((noinline)) int32_t
flexible_header_size(void) {
    return (int32_t)sizeof(struct Packet);
}

__attribute__((noinline)) int32_t
flexible_sum(const int32_t *storage, int32_t available) {
    const struct Packet *packet;
    int32_t total = 0;
    int32_t index;
    int32_t count;
    if (storage == 0 || available < 2 || available > 16) {
        return -1;
    }
    packet = (const struct Packet *)(const void *)storage;
    count = packet->length;
    if (count < 0 || count > available - 2) {
        return -2;
    }
    for (index = 0; index < count; ++index) {
        total += packet->items[index];
    }
    return total + packet->tag;
}

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
flexible_header_size pass 6 lines
// glaurung: flexible_header_size @ 0x1100
int32_t flexible_header_size(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 8;
}
flexible_sum pass 46 lines
// glaurung: flexible_sum @ 0x1110
typedef struct Packet Packet;
__attribute__((no_stack_protector)) int32_t flexible_sum(const int32_t * arg0, int32_t arg1) {
    int total;
    unsigned char packet[8];
    int count;
    int index;
    int local_4;
    long var6;
    // x86-64 prologue: save rbp
    total = 0;
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 2)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    *(long *)(&packet[0]) = (long)((long)arg0);
    count = *(int *)(*(long *)(&packet[0]));
    if (((long)(count) < 0)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - 2)));
    if (((((unsigned int)(count) == (unsigned int)(var6)) | ((long)(count) < (long)((int)(var6)))) == 0)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (index = 0; (index < count); index++) {
        total = ((unsigned int)(*(int *)(((*(long *)(&packet[0]) + ((long)(index) * 4)) + 8))) + total);
    }
    local_4 = ((unsigned int)(total) + *(int *)((*(long *)(&packet[0]) + 4)));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

2/2
flexible_header_size pass 4 lines
// glaurung: flexible_header_size @ 0x1100
int32_t flexible_header_size(void) {
    return 8;
}
flexible_sum pass 66 lines
// glaurung: flexible_sum @ 0x1110
int32_t flexible_sum(const int32_t * arg0, int32_t arg1) {
    int count;
    int index;
    int total;
    long ret;
    long var10;
    long var12;
    long var17;
    int var2;
    int var32;
    long var33;
    long var39;
    long var41;
    long var42;
    int var43;
    long var6;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)((unsigned long)((unsigned int)((arg1 - 17)))) < (unsigned long)(0xfffffff1))) {
        return ret;
    }
    count = (unsigned long)((unsigned int)(*(int *)(((long)arg0))));
    ret = 0xfffffffe;
    if (((long)(count) < 0)) {
        return ret;
    }
    var2 = (arg1 - 2);
    if (((((unsigned int)(count) == (unsigned int)(var2)) | (count < var2)) == 0)) {
        return ret;
    }
    if ((count == 0)) {
        var6 = 0;
    } else {
        var10 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(count)) & 7)));
        if (((unsigned long)(7) <= (unsigned long)((count - 1)))) {
            var12 = (unsigned long)((unsigned int)((count & -8)));
            index = 0;
            var17 = 0;
            do {
                var32 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var17 + *(int *)(((long)arg0 + index * 4 + 0x8))))) + *(int *)(((long)arg0 + index * 4 + 0xc))))) + *(int *)(((long)arg0 + index * 4 + 0x10))))) + *(int *)(((long)arg0 + index * 4 + 0x14))))) + *(int *)(((long)arg0 + index * 4 + 0x18))))) + *(int *)(((long)arg0 + index * 4 + 0x1c))))) + *(int *)(((long)arg0 + index * 4 + 0x20)))) + *(int *)(((long)arg0 + index * 4 + 0x24)));
                var17 = (unsigned long)((unsigned int)(var32));
                index = (index + 8);
                var6 = (unsigned long)((unsigned int)(var32));
                var33 = (unsigned long)((unsigned int)(index));
            } while ((var12 != index));
        } else {
            var6 = 0;
            var33 = 0;
        }
        if ((var10 != 0)) {
            var39 = (long)((((long)arg0 + (var33 * 4)) + 8));
            var41 = 0;
            var42 = var6;
            while ((var10 != var41)) {
                var43 = (var42 + *(int *)((var39 + var41 * 4)));
                var42 = (unsigned long)((unsigned int)(var43));
                var41 = (var41 + 1);
                var6 = (unsigned long)((unsigned int)(var43));
            }
        }
    }
    return (unsigned int)((var6 + *(int *)(((long)arg0 + 0x4))));
}

gcc -O0

2/2
flexible_header_size pass 6 lines
// glaurung: flexible_header_size @ 0x10f9
int32_t flexible_header_size(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 8;
}
flexible_sum pass 37 lines
// glaurung: flexible_sum @ 0x1108
typedef struct Packet Packet;
int32_t flexible_sum(const int32_t * arg0, int32_t arg1) {
    int total;
    const Packet * packet;
    int count;
    int index;
    // x86-64 prologue: save rbp
    total = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 1) | ((long)(arg1) < 1))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    packet = (const Packet *)arg0;
    count = *(int *)((long)packet);
    if (((long)(count) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    if (((long)((int)(((unsigned long)((unsigned int)(arg1)) - 1))) <= (long)(count))) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    for (index = 0; (index < count); index++) {
        total = (total + (unsigned int)(*(int *)((((long)packet + ((long)(index) * 4)) + 8))));
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(total)) + (unsigned long)((unsigned int)(*(int *)(((long)packet + 0x4))))));
}

gcc -O2

2/2
flexible_header_size pass 4 lines
// glaurung: flexible_header_size @ 0x1100
int32_t flexible_header_size(void) {
    return 8;
}
flexible_sum pass 45 lines
// glaurung: flexible_sum @ 0x1110
int32_t flexible_sum(const int32_t * arg0, int32_t arg1) {
    int count;
    int total;
    int index;
    long t148;
    long var12;
    long var3;
    long var4;
    int var5;
    long var8;
    long var9;
    if (((unsigned long)(14) < (unsigned long)((unsigned long)((unsigned int)((arg1 - 2)))))) {
        return 0xffffffff;
    }
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    count = (unsigned long)((unsigned int)(*(int *)(((long)arg0))));
    if (((long)(count) < 0)) {
        return 0xfffffffe;
    }
    var3 = (unsigned long)((unsigned int)((arg1 - 1)));
    if ((((unsigned int)(var3) == (unsigned int)(count)) | ((long)((int)(var3)) < (long)(count)))) {
        return 0xfffffffe;
    }
    var4 = (unsigned long)((unsigned int)(count));
    if (((unsigned long)((unsigned int)(count)) == 0)) {
        t148 = *(int *)(((long)arg0 + 0x4));
        var5 = (var4 + t148);
        return (unsigned int)(var5);
    }
    var8 = (long)((arg0 + 2));
    var9 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((count - 1))) * 4)) + 12));
    var12 = 0;
    do {
        total = (var12 + *(int *)((var8)));
        var8 = (var8 + 4);
        var12 = (unsigned long)((unsigned int)(total));
        var4 = (unsigned long)((unsigned int)(total));
    } while ((var8 != var9));
    t148 = *(int *)(((long)arg0 + 0x4));
    var5 = (var4 + t148);
    return (unsigned int)(var5);
}

← 213 fixtures