skip to content
==> tests/leb128.c <==
1/* LEB128: values, the length limits and the padding rules of the WebAssembly spec. */
2#include "mesh/check.h"
3#include "wasm/leb128.h"
4
5#define BYTES(...) ((const uint8_t[]){__VA_ARGS__})
6#define LEN(...) sizeof((const uint8_t[]){__VA_ARGS__})
7
8static size_t u32(const uint8_t *p, size_t n, uint32_t *v) { return wasm_leb_u32(p, p + n, v); }
9static size_t s32(const uint8_t *p, size_t n, int32_t *v) { return wasm_leb_s32(p, p + n, v); }
10static size_t s33(const uint8_t *p, size_t n, int64_t *v) { return wasm_leb_s33(p, p + n, v); }
11static size_t s64(const uint8_t *p, size_t n, int64_t *v) { return wasm_leb_s64(p, p + n, v); }
12static size_t u64(const uint8_t *p, size_t n, uint64_t *v) { return wasm_leb_u64(p, p + n, v); }
13
14int main(void) {
15    uint32_t a;
16    int32_t b;
17    int64_t c;
18    uint64_t d;
19    CHECK_U(u32(BYTES(0x00), 1, &a), 1);
20    CHECK_U(a, 0);
21    CHECK_U(u32(BYTES(0xe5, 0x8e, 0x26), 3, &a), 3);
22    CHECK_U(a, 624485);
23    /* Non-minimal encodings are fine within the length limit. */
24    CHECK_U(u32(BYTES(0x80, 0x80, 0x80, 0x80, 0x00), 5, &a), 5);
25    CHECK_U(a, 0);
26    CHECK_U(u32(BYTES(0xff, 0xff, 0xff, 0xff, 0x0f), 5, &a), 5);
27    CHECK_U(a, 0xffffffffu);
28    /* Too long, unused bits set, truncated. */
29    CHECK_U(u32(BYTES(0x80, 0x80, 0x80, 0x80, 0x80, 0x00), 6, &a), 0);
30    CHECK_U(u32(BYTES(0xff, 0xff, 0xff, 0xff, 0x1f), 5, &a), 0);
31    CHECK_U(u32(BYTES(0x80, 0x80), 2, &a), 0);
32    CHECK_U(u32(BYTES(0x80), 0, &a), 0);
33
34    CHECK_U(s32(BYTES(0x7f), 1, &b), 1);
35    CHECK_I(b, -1);
36    CHECK_U(s32(BYTES(0xc0, 0xbb, 0x78), 3, &b), 3);
37    CHECK_I(b, -123456);
38    CHECK_U(s32(BYTES(0x80, 0x80, 0x80, 0x80, 0x78), 5, &b), 5);
39    CHECK_I(b, INT32_MIN);
40    CHECK_U(s32(BYTES(0xff, 0xff, 0xff, 0xff, 0x07), 5, &b), 5);
41    CHECK_I(b, INT32_MAX);
42    /* The last byte's unused bits must repeat the sign. */
43    CHECK_U(s32(BYTES(0xff, 0xff, 0xff, 0xff, 0x0f), 5, &b), 0);
44    CHECK_U(s32(BYTES(0x80, 0x80, 0x80, 0x80, 0x70), 5, &b), 0);
45    CHECK_U(s32(BYTES(0xff, 0xff, 0xff, 0xff, 0x7f), 5, &b), 5);
46    CHECK_I(b, -1);
47
48    CHECK_U(s33(BYTES(0x40), 1, &c), 1);
49    CHECK_I(c, -64);
50    CHECK_U(s33(BYTES(0xff, 0xff, 0xff, 0xff, 0x0f), 5, &c), 5);
51    CHECK_I(c, 0xffffffffll);
52    CHECK_U(s33(BYTES(0xff, 0xff, 0xff, 0xff, 0x7f), 5, &c), 5);
53    CHECK_I(c, -1);
54    CHECK_U(s33(BYTES(0xff, 0xff, 0xff, 0xff, 0x1f), 5, &c), 0);
55    CHECK_U(s33(BYTES(0xff, 0xff, 0xff, 0xff, 0x2f), 5, &c), 0);
56
57    CHECK_U(s64(BYTES(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f), 10, &c), 10);
58    CHECK_I(c, INT64_MIN);
59    CHECK_U(s64(BYTES(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00), 10, &c), 10);
60    CHECK_I(c, INT64_MAX);
61    CHECK_U(s64(BYTES(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01), 10, &c), 0);
62    CHECK_U(u64(BYTES(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01), 10, &d), 10);
63    CHECK_U(d, UINT64_MAX);
64    CHECK_U(u64(BYTES(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02), 10, &d), 0);
65
66    /* Round trips of every 32-bit edge. */
67    const uint32_t vals[] = {0, 1, 63, 64, 127, 128, 8191, 8192, 0x7fffffff, 0x80000000u, 0xffffffffu};
68    for (size_t i = 0; i < sizeof vals / sizeof vals[0]; i++) {
69        uint8_t buf[5];
70        size_t n = 0;
71        uint32_t v = vals[i];
72        do {
73            uint8_t byte = v & 0x7f;
74            v >>= 7;
75            buf[n++] = (uint8_t)(byte | (v ? 0x80 : 0));
76        } while (v);
77        CHECK_U(u32(buf, n, &a), n);
78        CHECK_U(a, vals[i]);
79        int64_t s = (int32_t)vals[i];
80        n = 0;
81        for (;;) {
82            uint8_t byte = (uint8_t)(s & 0x7f);
83            s >>= 7; /* arithmetic on every target we build for */
84            if ((s == 0 && !(byte & 0x40)) || (s == -1 && (byte & 0x40))) {
85                buf[n++] = byte;
86                break;
87            }
88            buf[n++] = (uint8_t)(byte | 0x80);
89        }
90        CHECK_U(s32(buf, n, &b), n);
91        CHECK_I(b, (int32_t)vals[i]);
92    }
93    return mesh_check_done();
94}