==> 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}