Coverage Report

Created: 2026-10-05 12:20

/home/runner/work/panackelty/panackelty/src/vm/decode.c
Line
Count
Source (jump to first uncovered line)
1
#include "decode.h"
2
3
#include "program.h"
4
#include "utf8.h"
5
6
#include <stdlib.h>
7
#include <string.h>
8
9
/* Bounded version-8 decoding. No runtime values or host operations are created here. */
10
11
17.6k
#define MAX_FUNCTIONS 4096u
12
79.1k
#define MAX_INSTRUCTIONS 4000000u
13
4.25M
#define MAX_NAME 1024u
14
347k
#define MAX_TEXT (1024u * 1024u)
15
339k
#define MAX_DIGITS 4096u
16
17
typedef struct {
18
    const uint8_t *data;
19
    size_t len, at;
20
    const char *error;
21
} Reader;
22
23
static void fail(Reader *r, const char *message)
24
6.23k
{
25
6.23k
    if (!r->error) {
  Branch (25:9): [True: 5.86k, False: 370]
26
5.86k
        r->error = message;
27
5.86k
    }
28
6.23k
}
29
30
static bool take(Reader *r, size_t n, const uint8_t **out)
31
9.65M
{
32
9.65M
    if (n > r->len - r->at) {
  Branch (32:9): [True: 2.24k, False: 9.65M]
33
2.24k
        fail(r, "truncated data");
34
2.24k
        return false;
35
2.24k
    }
36
9.65M
    *out = r->data + r->at;
37
9.65M
    r->at += n;
38
9.65M
    return true;
39
9.65M
}
40
41
static bool u8(Reader *r, uint8_t *out)
42
4.15M
{
43
4.15M
    const uint8_t *p;
44
4.15M
    if (!take(r, 1, &p)) {
  Branch (44:9): [True: 633, False: 4.15M]
45
633
        return false;
46
633
    }
47
4.15M
    *out = p[0];
48
4.15M
    return true;
49
4.15M
}
50
51
static bool u16(Reader *r, uint16_t *out)
52
2.36M
{
53
2.36M
    const uint8_t *p;
54
2.36M
    if (!take(r, 2, &p)) {
  Branch (54:9): [True: 635, False: 2.36M]
55
635
        return false;
56
635
    }
57
2.36M
    *out = (uint16_t)((p[0] << 8) | p[1]);
58
2.36M
    return true;
59
2.36M
}
60
61
static bool u32(Reader *r, uint32_t *out)
62
733k
{
63
733k
    const uint8_t *p;
64
733k
    if (!take(r, 4, &p)) {
  Branch (64:9): [True: 313, False: 732k]
65
313
        return false;
66
313
    }
67
732k
    *out = ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3];
68
732k
    return true;
69
733k
}
70
71
static char *text(Reader *r, bool name)
72
4.59M
{
73
4.59M
    uint32_t n32 = 0;
74
4.59M
    uint16_t n16 = 0;
75
4.59M
    size_t n;
76
4.59M
    if (name) {
  Branch (76:9): [True: 2.12M, False: 173k]
  Branch (76:9): [True: 2.12M, False: 173k]
77
4.25M
        if (!u16(r, &n16)) {
  Branch (77:13): [True: 603, False: 2.12M]
  Branch (77:13): [True: 603, False: 2.12M]
78
1.20k
            return NULL;
79
1.20k
        }
80
4.25M
        n = n16;
81
4.25M
        if (n > MAX_NAME) {
  Branch (81:13): [True: 581, False: 2.12M]
  Branch (81:13): [True: 581, False: 2.12M]
82
1.16k
            fail(r, "name exceeds limit");
83
1.16k
            return NULL;
84
1.16k
        }
85
4.25M
    } else {
86
347k
        if (!u32(r, &n32)) {
  Branch (86:13): [True: 14, False: 173k]
  Branch (86:13): [True: 14, False: 173k]
87
28
            return NULL;
88
28
        }
89
347k
        n = n32;
90
347k
        if (n > MAX_TEXT) {
  Branch (90:13): [True: 104, False: 173k]
  Branch (90:13): [True: 104, False: 173k]
91
208
            fail(r, "text exceeds limit");
92
208
            return NULL;
93
208
        }
94
347k
    }
95
4.59M
    const uint8_t *p;
96
4.59M
    if (!take(r, n, &p)) {
  Branch (96:9): [True: 568, False: 2.29M]
  Branch (96:9): [True: 568, False: 2.29M]
97
1.13k
        return NULL;
98
1.13k
    }
99
4.59M
    if (!utf8(p, n)) {
  Branch (99:9): [True: 981, False: 2.29M]
  Branch (99:9): [True: 981, False: 2.29M]
100
1.96k
        fail(r, "invalid UTF-8");
101
1.96k
        return NULL;
102
1.96k
    }
103
4.59M
    char *v = malloc(n + 1);
104
4.59M
    if (!v) {
  Branch (104:9): [True: 28, False: 2.29M]
  Branch (104:9): [True: 28, False: 2.29M]
105
56
        fail(r, "out of memory");
106
56
        return NULL;
107
56
    }
108
4.59M
    memcpy(v, p, n);
109
4.59M
    v[n] = 0;
110
4.59M
    return v;
111
4.59M
}
decode.c:text
Line
Count
Source
72
2.29M
{
73
2.29M
    uint32_t n32 = 0;
74
2.29M
    uint16_t n16 = 0;
75
2.29M
    size_t n;
76
2.29M
    if (name) {
  Branch (76:9): [True: 2.12M, False: 173k]
77
2.12M
        if (!u16(r, &n16)) {
  Branch (77:13): [True: 603, False: 2.12M]
78
603
            return NULL;
79
603
        }
80
2.12M
        n = n16;
81
2.12M
        if (n > MAX_NAME) {
  Branch (81:13): [True: 581, False: 2.12M]
82
581
            fail(r, "name exceeds limit");
83
581
            return NULL;
84
581
        }
85
2.12M
    } else {
86
173k
        if (!u32(r, &n32)) {
  Branch (86:13): [True: 14, False: 173k]
87
14
            return NULL;
88
14
        }
89
173k
        n = n32;
90
173k
        if (n > MAX_TEXT) {
  Branch (90:13): [True: 104, False: 173k]
91
104
            fail(r, "text exceeds limit");
92
104
            return NULL;
93
104
        }
94
173k
    }
95
2.29M
    const uint8_t *p;
96
2.29M
    if (!take(r, n, &p)) {
  Branch (96:9): [True: 568, False: 2.29M]
97
568
        return NULL;
98
568
    }
99
2.29M
    if (!utf8(p, n)) {
  Branch (99:9): [True: 981, False: 2.29M]
100
981
        fail(r, "invalid UTF-8");
101
981
        return NULL;
102
981
    }
103
2.29M
    char *v = malloc(n + 1);
104
2.29M
    if (!v) {
  Branch (104:9): [True: 28, False: 2.29M]
105
28
        fail(r, "out of memory");
106
28
        return NULL;
107
28
    }
108
2.29M
    memcpy(v, p, n);
109
2.29M
    v[n] = 0;
110
2.29M
    return v;
111
2.29M
}
decode.c:text
Line
Count
Source
72
2.29M
{
73
2.29M
    uint32_t n32 = 0;
74
2.29M
    uint16_t n16 = 0;
75
2.29M
    size_t n;
76
2.29M
    if (name) {
  Branch (76:9): [True: 2.12M, False: 173k]
77
2.12M
        if (!u16(r, &n16)) {
  Branch (77:13): [True: 603, False: 2.12M]
78
603
            return NULL;
79
603
        }
80
2.12M
        n = n16;
81
2.12M
        if (n > MAX_NAME) {
  Branch (81:13): [True: 581, False: 2.12M]
82
581
            fail(r, "name exceeds limit");
83
581
            return NULL;
84
581
        }
85
2.12M
    } else {
86
173k
        if (!u32(r, &n32)) {
  Branch (86:13): [True: 14, False: 173k]
87
14
            return NULL;
88
14
        }
89
173k
        n = n32;
90
173k
        if (n > MAX_TEXT) {
  Branch (90:13): [True: 104, False: 173k]
91
104
            fail(r, "text exceeds limit");
92
104
            return NULL;
93
104
        }
94
173k
    }
95
2.29M
    const uint8_t *p;
96
2.29M
    if (!take(r, n, &p)) {
  Branch (96:9): [True: 568, False: 2.29M]
97
568
        return NULL;
98
568
    }
99
2.29M
    if (!utf8(p, n)) {
  Branch (99:9): [True: 981, False: 2.29M]
100
981
        fail(r, "invalid UTF-8");
101
981
        return NULL;
102
981
    }
103
2.29M
    char *v = malloc(n + 1);
104
2.29M
    if (!v) {
  Branch (104:9): [True: 28, False: 2.29M]
105
28
        fail(r, "out of memory");
106
28
        return NULL;
107
28
    }
108
2.29M
    memcpy(v, p, n);
109
2.29M
    v[n] = 0;
110
2.29M
    return v;
111
2.29M
}
112
113
static bool read_nat(Reader *r, PnBigInt *out)
114
166k
{
115
166k
    uint16_t n;
116
166k
    const uint8_t *p;
117
166k
    pn_big_init(out);
118
166k
    if (!u16(r, &n)) {
  Branch (118:9): [True: 5, False: 83.1k]
  Branch (118:9): [True: 5, False: 83.1k]
119
10
        return false;
120
10
    }
121
166k
    size_t max_bytes = (MAX_DIGITS * 3322u + 7999u) / 8000u;
122
166k
    if (n > max_bytes) {
  Branch (122:9): [True: 34, False: 83.0k]
  Branch (122:9): [True: 34, False: 83.0k]
123
68
        fail(r, "integer exceeds digit limit");
124
68
        return false;
125
68
    }
126
166k
    if (!take(r, n, &p)) {
  Branch (126:9): [True: 70, False: 83.0k]
  Branch (126:9): [True: 70, False: 83.0k]
127
140
        return false;
128
140
    }
129
166k
    if (n && p[0] == 0) {
  Branch (129:9): [True: 56.1k, False: 26.8k]
  Branch (129:14): [True: 3, False: 56.1k]
  Branch (129:9): [True: 56.1k, False: 26.8k]
  Branch (129:14): [True: 3, False: 56.1k]
130
6
        fail(r, "non-minimal integer");
131
6
        return false;
132
6
    }
133
166k
    if (!pn_big_from_bytes(out, p, n)) {
  Branch (133:9): [True: 10, False: 83.0k]
  Branch (133:9): [True: 10, False: 83.0k]
134
20
        fail(r, "out of memory");
135
20
        return false;
136
20
    }
137
166k
    char *digits = pn_big_string(out);
138
166k
    if (!digits) {
  Branch (138:9): [True: 2, False: 83.0k]
  Branch (138:9): [True: 2, False: 83.0k]
139
4
        fail(r, "out of memory");
140
4
        return false;
141
4
    }
142
166k
    if (strlen(digits) > MAX_DIGITS) {
  Branch (142:9): [True: 0, False: 83.0k]
  Branch (142:9): [True: 0, False: 83.0k]
143
0
        fail(r, "integer exceeds digit limit");
144
0
    }
145
166k
    free(digits);
146
166k
    return !r->error;
147
166k
}
decode.c:read_nat
Line
Count
Source
114
83.1k
{
115
83.1k
    uint16_t n;
116
83.1k
    const uint8_t *p;
117
83.1k
    pn_big_init(out);
118
83.1k
    if (!u16(r, &n)) {
  Branch (118:9): [True: 5, False: 83.1k]
119
5
        return false;
120
5
    }
121
83.1k
    size_t max_bytes = (MAX_DIGITS * 3322u + 7999u) / 8000u;
122
83.1k
    if (n > max_bytes) {
  Branch (122:9): [True: 34, False: 83.0k]
123
34
        fail(r, "integer exceeds digit limit");
124
34
        return false;
125
34
    }
126
83.0k
    if (!take(r, n, &p)) {
  Branch (126:9): [True: 70, False: 83.0k]
127
70
        return false;
128
70
    }
129
83.0k
    if (n && p[0] == 0) {
  Branch (129:9): [True: 56.1k, False: 26.8k]
  Branch (129:14): [True: 3, False: 56.1k]
130
3
        fail(r, "non-minimal integer");
131
3
        return false;
132
3
    }
133
83.0k
    if (!pn_big_from_bytes(out, p, n)) {
  Branch (133:9): [True: 10, False: 83.0k]
134
10
        fail(r, "out of memory");
135
10
        return false;
136
10
    }
137
83.0k
    char *digits = pn_big_string(out);
138
83.0k
    if (!digits) {
  Branch (138:9): [True: 2, False: 83.0k]
139
2
        fail(r, "out of memory");
140
2
        return false;
141
2
    }
142
83.0k
    if (strlen(digits) > MAX_DIGITS) {
  Branch (142:9): [True: 0, False: 83.0k]
143
0
        fail(r, "integer exceeds digit limit");
144
0
    }
145
83.0k
    free(digits);
146
83.0k
    return !r->error;
147
83.0k
}
decode.c:read_nat
Line
Count
Source
114
83.1k
{
115
83.1k
    uint16_t n;
116
83.1k
    const uint8_t *p;
117
83.1k
    pn_big_init(out);
118
83.1k
    if (!u16(r, &n)) {
  Branch (118:9): [True: 5, False: 83.1k]
119
5
        return false;
120
5
    }
121
83.1k
    size_t max_bytes = (MAX_DIGITS * 3322u + 7999u) / 8000u;
122
83.1k
    if (n > max_bytes) {
  Branch (122:9): [True: 34, False: 83.0k]
123
34
        fail(r, "integer exceeds digit limit");
124
34
        return false;
125
34
    }
126
83.0k
    if (!take(r, n, &p)) {
  Branch (126:9): [True: 70, False: 83.0k]
127
70
        return false;
128
70
    }
129
83.0k
    if (n && p[0] == 0) {
  Branch (129:9): [True: 56.1k, False: 26.8k]
  Branch (129:14): [True: 3, False: 56.1k]
130
3
        fail(r, "non-minimal integer");
131
3
        return false;
132
3
    }
133
83.0k
    if (!pn_big_from_bytes(out, p, n)) {
  Branch (133:9): [True: 10, False: 83.0k]
134
10
        fail(r, "out of memory");
135
10
        return false;
136
10
    }
137
83.0k
    char *digits = pn_big_string(out);
138
83.0k
    if (!digits) {
  Branch (138:9): [True: 2, False: 83.0k]
139
2
        fail(r, "out of memory");
140
2
        return false;
141
2
    }
142
83.0k
    if (strlen(digits) > MAX_DIGITS) {
  Branch (142:9): [True: 0, False: 83.0k]
143
0
        fail(r, "integer exceeds digit limit");
144
0
    }
145
83.0k
    free(digits);
146
83.0k
    return !r->error;
147
83.0k
}
148
149
static bool read_decimal(Reader *r, Constant *out)
150
7.05k
{
151
7.05k
    uint8_t sign;
152
7.05k
    uint16_t ex, digits;
153
7.05k
    const uint8_t *p;
154
7.05k
    if (!u8(r, &sign) || !u16(r, &ex) || !u16(r, &digits)) {
  Branch (154:9): [True: 1, False: 3.52k]
  Branch (154:26): [True: 3, False: 3.52k]
  Branch (154:42): [True: 2, False: 3.52k]
  Branch (154:9): [True: 1, False: 3.52k]
  Branch (154:26): [True: 3, False: 3.52k]
  Branch (154:42): [True: 2, False: 3.52k]
155
12
        return false;
156
12
    }
157
7.04k
    out->boolean = sign != 0;
158
7.04k
    out->exponent = (int16_t)ex;
159
7.04k
    if (sign > 1 || !digits || out->exponent > 4096 || out->exponent < -4096 ||
  Branch (159:9): [True: 11, False: 3.51k]
  Branch (159:21): [True: 1, False: 3.51k]
  Branch (159:32): [True: 2, False: 3.50k]
  Branch (159:56): [True: 4, False: 3.50k]
  Branch (159:9): [True: 11, False: 3.51k]
  Branch (159:21): [True: 1, False: 3.51k]
  Branch (159:32): [True: 2, False: 3.50k]
  Branch (159:56): [True: 4, False: 3.50k]
160
7.04k
        digits > MAX_DIGITS) {
  Branch (160:9): [True: 9, False: 3.49k]
  Branch (160:9): [True: 9, False: 3.49k]
161
54
        fail(r, "invalid decimal");
162
54
        return false;
163
54
    }
164
6.99k
    size_t bytes = (digits + 1) / 2;
165
6.99k
    if (!take(r, bytes, &p)) {
  Branch (165:9): [True: 10, False: 3.48k]
  Branch (165:9): [True: 10, False: 3.48k]
166
20
        return false;
167
20
    }
168
6.97k
    char *value = malloc(digits);
169
6.97k
    if (!value) {
  Branch (169:9): [True: 2, False: 3.48k]
  Branch (169:9): [True: 2, False: 3.48k]
170
4
        fail(r, "out of memory");
171
4
        return false;
172
4
    }
173
56.0k
    for (size_t i = 0; i < digits; i++) {
  Branch (173:24): [True: 24.5k, False: 3.45k]
  Branch (173:24): [True: 24.5k, False: 3.45k]
174
49.1k
        uint8_t d = (i & 1) ? p[i / 2] & 15 : p[i / 2] >> 4;
  Branch (174:21): [True: 10.5k, False: 14.0k]
  Branch (174:21): [True: 10.5k, False: 14.0k]
175
49.1k
        if (d > 9) {
  Branch (175:13): [True: 26, False: 24.5k]
  Branch (175:13): [True: 26, False: 24.5k]
176
52
            free(value);
177
52
            fail(r, "invalid decimal digit");
178
52
            return false;
179
52
        }
180
49.1k
        value[i] = (char)('0' + d);
181
49.1k
    }
182
6.91k
    if ((digits & 1) && (p[bytes - 1] & 15) != 15) {
  Branch (182:9): [True: 3.43k, False: 26]
  Branch (182:25): [True: 12, False: 3.41k]
  Branch (182:9): [True: 3.43k, False: 26]
  Branch (182:25): [True: 12, False: 3.41k]
183
24
        free(value);
184
24
        fail(r, "invalid decimal padding");
185
24
        return false;
186
24
    }
187
6.89k
    if (digits > 1 && value[0] == '0') {
  Branch (187:9): [True: 3.42k, False: 16]
  Branch (187:23): [True: 4, False: 3.42k]
  Branch (187:9): [True: 3.42k, False: 16]
  Branch (187:23): [True: 4, False: 3.42k]
188
8
        free(value);
189
8
        fail(r, "non-minimal decimal coefficient");
190
8
        return false;
191
8
    }
192
6.88k
    bool ok = pn_big_from_digits(&out->number, value, digits, sign ? -1 : 1);
  Branch (192:63): [True: 3.38k, False: 61]
  Branch (192:63): [True: 3.38k, False: 61]
193
6.88k
    free(value);
194
6.88k
    if (!ok) {
  Branch (194:9): [True: 2, False: 3.43k]
  Branch (194:9): [True: 2, False: 3.43k]
195
4
        fail(r, "out of memory");
196
4
    }
197
6.88k
    return ok;
198
6.89k
}
decode.c:read_decimal
Line
Count
Source
150
3.52k
{
151
3.52k
    uint8_t sign;
152
3.52k
    uint16_t ex, digits;
153
3.52k
    const uint8_t *p;
154
3.52k
    if (!u8(r, &sign) || !u16(r, &ex) || !u16(r, &digits)) {
  Branch (154:9): [True: 1, False: 3.52k]
  Branch (154:26): [True: 3, False: 3.52k]
  Branch (154:42): [True: 2, False: 3.52k]
155
6
        return false;
156
6
    }
157
3.52k
    out->boolean = sign != 0;
158
3.52k
    out->exponent = (int16_t)ex;
159
3.52k
    if (sign > 1 || !digits || out->exponent > 4096 || out->exponent < -4096 ||
  Branch (159:9): [True: 11, False: 3.51k]
  Branch (159:21): [True: 1, False: 3.51k]
  Branch (159:32): [True: 2, False: 3.50k]
  Branch (159:56): [True: 4, False: 3.50k]
160
3.52k
        digits > MAX_DIGITS) {
  Branch (160:9): [True: 9, False: 3.49k]
161
27
        fail(r, "invalid decimal");
162
27
        return false;
163
27
    }
164
3.49k
    size_t bytes = (digits + 1) / 2;
165
3.49k
    if (!take(r, bytes, &p)) {
  Branch (165:9): [True: 10, False: 3.48k]
166
10
        return false;
167
10
    }
168
3.48k
    char *value = malloc(digits);
169
3.48k
    if (!value) {
  Branch (169:9): [True: 2, False: 3.48k]
170
2
        fail(r, "out of memory");
171
2
        return false;
172
2
    }
173
28.0k
    for (size_t i = 0; i < digits; i++) {
  Branch (173:24): [True: 24.5k, False: 3.45k]
174
24.5k
        uint8_t d = (i & 1) ? p[i / 2] & 15 : p[i / 2] >> 4;
  Branch (174:21): [True: 10.5k, False: 14.0k]
175
24.5k
        if (d > 9) {
  Branch (175:13): [True: 26, False: 24.5k]
176
26
            free(value);
177
26
            fail(r, "invalid decimal digit");
178
26
            return false;
179
26
        }
180
24.5k
        value[i] = (char)('0' + d);
181
24.5k
    }
182
3.45k
    if ((digits & 1) && (p[bytes - 1] & 15) != 15) {
  Branch (182:9): [True: 3.43k, False: 26]
  Branch (182:25): [True: 12, False: 3.41k]
183
12
        free(value);
184
12
        fail(r, "invalid decimal padding");
185
12
        return false;
186
12
    }
187
3.44k
    if (digits > 1 && value[0] == '0') {
  Branch (187:9): [True: 3.42k, False: 16]
  Branch (187:23): [True: 4, False: 3.42k]
188
4
        free(value);
189
4
        fail(r, "non-minimal decimal coefficient");
190
4
        return false;
191
4
    }
192
3.44k
    bool ok = pn_big_from_digits(&out->number, value, digits, sign ? -1 : 1);
  Branch (192:63): [True: 3.38k, False: 61]
193
3.44k
    free(value);
194
3.44k
    if (!ok) {
  Branch (194:9): [True: 2, False: 3.43k]
195
2
        fail(r, "out of memory");
196
2
    }
197
3.44k
    return ok;
198
3.44k
}
decode.c:read_decimal
Line
Count
Source
150
3.52k
{
151
3.52k
    uint8_t sign;
152
3.52k
    uint16_t ex, digits;
153
3.52k
    const uint8_t *p;
154
3.52k
    if (!u8(r, &sign) || !u16(r, &ex) || !u16(r, &digits)) {
  Branch (154:9): [True: 1, False: 3.52k]
  Branch (154:26): [True: 3, False: 3.52k]
  Branch (154:42): [True: 2, False: 3.52k]
155
6
        return false;
156
6
    }
157
3.52k
    out->boolean = sign != 0;
158
3.52k
    out->exponent = (int16_t)ex;
159
3.52k
    if (sign > 1 || !digits || out->exponent > 4096 || out->exponent < -4096 ||
  Branch (159:9): [True: 11, False: 3.51k]
  Branch (159:21): [True: 1, False: 3.51k]
  Branch (159:32): [True: 2, False: 3.50k]
  Branch (159:56): [True: 4, False: 3.50k]
160
3.52k
        digits > MAX_DIGITS) {
  Branch (160:9): [True: 9, False: 3.49k]
161
27
        fail(r, "invalid decimal");
162
27
        return false;
163
27
    }
164
3.49k
    size_t bytes = (digits + 1) / 2;
165
3.49k
    if (!take(r, bytes, &p)) {
  Branch (165:9): [True: 10, False: 3.48k]
166
10
        return false;
167
10
    }
168
3.48k
    char *value = malloc(digits);
169
3.48k
    if (!value) {
  Branch (169:9): [True: 2, False: 3.48k]
170
2
        fail(r, "out of memory");
171
2
        return false;
172
2
    }
173
28.0k
    for (size_t i = 0; i < digits; i++) {
  Branch (173:24): [True: 24.5k, False: 3.45k]
174
24.5k
        uint8_t d = (i & 1) ? p[i / 2] & 15 : p[i / 2] >> 4;
  Branch (174:21): [True: 10.5k, False: 14.0k]
175
24.5k
        if (d > 9) {
  Branch (175:13): [True: 26, False: 24.5k]
176
26
            free(value);
177
26
            fail(r, "invalid decimal digit");
178
26
            return false;
179
26
        }
180
24.5k
        value[i] = (char)('0' + d);
181
24.5k
    }
182
3.45k
    if ((digits & 1) && (p[bytes - 1] & 15) != 15) {
  Branch (182:9): [True: 3.43k, False: 26]
  Branch (182:25): [True: 12, False: 3.41k]
183
12
        free(value);
184
12
        fail(r, "invalid decimal padding");
185
12
        return false;
186
12
    }
187
3.44k
    if (digits > 1 && value[0] == '0') {
  Branch (187:9): [True: 3.42k, False: 16]
  Branch (187:23): [True: 4, False: 3.42k]
188
4
        free(value);
189
4
        fail(r, "non-minimal decimal coefficient");
190
4
        return false;
191
4
    }
192
3.44k
    bool ok = pn_big_from_digits(&out->number, value, digits, sign ? -1 : 1);
  Branch (192:63): [True: 3.38k, False: 61]
193
3.44k
    free(value);
194
3.44k
    if (!ok) {
  Branch (194:9): [True: 2, False: 3.43k]
195
2
        fail(r, "out of memory");
196
2
    }
197
3.44k
    return ok;
198
3.44k
}
199
200
static bool read_constant(Reader *r, Constant *out)
201
454k
{
202
454k
    uint8_t sign;
203
454k
    memset(out, 0, sizeof(*out));
204
454k
    pn_big_init(&out->number);
205
454k
    if (!u8(r, &out->tag)) {
  Branch (205:9): [True: 9, False: 454k]
206
9
        return false;
207
9
    }
208
454k
    switch (out->tag) {
209
79.5k
    case 0:
  Branch (209:5): [True: 79.5k, False: 374k]
210
79.5k
        return read_nat(r, &out->number);
211
3.56k
    case 1:
  Branch (211:5): [True: 3.56k, False: 450k]
212
3.56k
        if (!u8(r, &sign) || sign > 1) {
  Branch (212:13): [True: 2, False: 3.56k]
  Branch (212:30): [True: 19, False: 3.54k]
213
21
            fail(r, "invalid integer sign");
214
21
            return false;
215
21
        }
216
3.54k
        if (!read_nat(r, &out->number)) {
  Branch (216:13): [True: 42, False: 3.50k]
217
42
            return false;
218
42
        }
219
3.50k
        if (sign && pn_big_is_zero(&out->number)) {
  Branch (219:13): [True: 3.50k, False: 4]
  Branch (219:21): [True: 2, False: 3.49k]
220
2
            fail(r, "negative zero integer");
221
2
            return false;
222
2
        }
223
3.50k
        if (sign) {
  Branch (223:13): [True: 3.49k, False: 4]
224
3.49k
            out->number.sign = -1;
225
3.49k
        }
226
3.50k
        return true;
227
3.52k
    case 2:
  Branch (227:5): [True: 3.52k, False: 450k]
228
3.52k
        return read_decimal(r, out);
229
134k
    case 3: {
  Branch (229:5): [True: 134k, False: 319k]
230
134k
        size_t start = r->at;
231
134k
        out->text = text(r, false);
232
134k
        if (out->text) {
  Branch (232:13): [True: 134k, False: 116]
233
134k
            out->text_length = r->at - start - 4;
234
134k
        }
235
134k
        return out->text != NULL;
236
3.50k
    }
237
93.5k
    case 4:
  Branch (237:5): [True: 93.5k, False: 360k]
238
93.5k
        if (!u8(r, &sign) || sign > 1) {
  Branch (238:13): [True: 1, False: 93.5k]
  Branch (238:30): [True: 47, False: 93.4k]
239
48
            fail(r, "invalid Bool constant");
240
48
            return false;
241
48
        }
242
93.4k
        out->boolean = sign != 0;
243
93.4k
        return true;
244
138k
    case 5:
  Branch (244:5): [True: 138k, False: 315k]
245
138k
        return true;
246
350
    default:
  Branch (246:5): [True: 350, False: 453k]
247
350
        fail(r, "unknown constant tag");
248
350
        return false;
249
454k
    }
250
454k
}
251
252
static char **strings(Reader *r, uint16_t count, bool names)
253
99.5k
{
254
99.5k
    char **items = calloc(count, sizeof(char *));
255
99.5k
    if (count && !items) {
  Branch (255:9): [True: 49.7k, False: 5]
  Branch (255:18): [True: 2, False: 49.7k]
  Branch (255:9): [True: 49.7k, False: 5]
  Branch (255:18): [True: 2, False: 49.7k]
256
4
        fail(r, "out of memory");
257
4
        return NULL;
258
4
    }
259
364k
    for (uint16_t i = 0; i < count && !r->error; i++) {
  Branch (259:26): [True: 132k, False: 49.6k]
  Branch (259:39): [True: 132k, False: 168]
  Branch (259:26): [True: 132k, False: 49.6k]
  Branch (259:39): [True: 132k, False: 168]
260
265k
        items[i] = text(r, names);
261
265k
    }
262
99.5k
    if (r->error) {
  Branch (262:9): [True: 285, False: 49.5k]
  Branch (262:9): [True: 285, False: 49.5k]
263
1.31M
        for (uint16_t i = 0; i < count; i++) {
  Branch (263:30): [True: 659k, False: 285]
  Branch (263:30): [True: 659k, False: 285]
264
1.31M
            free(items[i]);
265
1.31M
        }
266
570
        free(items);
267
570
        return NULL;
268
570
    }
269
99.0k
    return items;
270
99.5k
}
decode.c:strings
Line
Count
Source
253
49.7k
{
254
49.7k
    char **items = calloc(count, sizeof(char *));
255
49.7k
    if (count && !items) {
  Branch (255:9): [True: 49.7k, False: 5]
  Branch (255:18): [True: 2, False: 49.7k]
256
2
        fail(r, "out of memory");
257
2
        return NULL;
258
2
    }
259
182k
    for (uint16_t i = 0; i < count && !r->error; i++) {
  Branch (259:26): [True: 132k, False: 49.6k]
  Branch (259:39): [True: 132k, False: 168]
260
132k
        items[i] = text(r, names);
261
132k
    }
262
49.7k
    if (r->error) {
  Branch (262:9): [True: 285, False: 49.5k]
263
659k
        for (uint16_t i = 0; i < count; i++) {
  Branch (263:30): [True: 659k, False: 285]
264
659k
            free(items[i]);
265
659k
        }
266
285
        free(items);
267
285
        return NULL;
268
285
    }
269
49.5k
    return items;
270
49.7k
}
decode.c:strings
Line
Count
Source
253
49.7k
{
254
49.7k
    char **items = calloc(count, sizeof(char *));
255
49.7k
    if (count && !items) {
  Branch (255:9): [True: 49.7k, False: 5]
  Branch (255:18): [True: 2, False: 49.7k]
256
2
        fail(r, "out of memory");
257
2
        return NULL;
258
2
    }
259
182k
    for (uint16_t i = 0; i < count && !r->error; i++) {
  Branch (259:26): [True: 132k, False: 49.6k]
  Branch (259:39): [True: 132k, False: 168]
260
132k
        items[i] = text(r, names);
261
132k
    }
262
49.7k
    if (r->error) {
  Branch (262:9): [True: 285, False: 49.5k]
263
659k
        for (uint16_t i = 0; i < count; i++) {
  Branch (263:30): [True: 659k, False: 285]
264
659k
            free(items[i]);
265
659k
        }
266
285
        free(items);
267
285
        return NULL;
268
285
    }
269
49.5k
    return items;
270
49.7k
}
271
272
static bool instruction(Reader *r, Instruction *in)
273
3.09M
{
274
3.09M
    uint16_t count;
275
3.09M
    uint32_t ignored;
276
3.09M
    memset(in, 0, sizeof(*in));
277
3.09M
    if (!u8(r, &in->op)) {
  Branch (277:9): [True: 603, False: 3.09M]
278
603
        return false;
279
603
    }
280
3.09M
    switch (in->op) {
281
454k
    case OP_CONST:
  Branch (281:5): [True: 454k, False: 2.64M]
282
454k
        return read_constant(r, &in->constant);
283
824k
    case OP_LOAD:
  Branch (283:5): [True: 824k, False: 2.27M]
284
1.18M
    case OP_STORE:
  Branch (284:5): [True: 363k, False: 2.73M]
285
1.20M
    case OP_ITER_INIT:
  Branch (285:5): [True: 19.9k, False: 3.07M]
286
1.39M
    case OP_FIELD_GET:
  Branch (286:5): [True: 182k, False: 2.91M]
287
1.39M
        in->name = text(r, true);
288
1.39M
        return !r->error;
289
74.6k
    case OP_POP:
  Branch (289:5): [True: 74.6k, False: 3.02M]
290
78.0k
    case OP_MAKE_RANGE:
  Branch (290:5): [True: 3.47k, False: 3.09M]
291
107k
    case OP_INDEX_GET:
  Branch (291:5): [True: 29.2k, False: 3.06M]
292
132k
    case OP_MATCH_FAIL:
  Branch (292:5): [True: 25.4k, False: 3.06M]
293
169k
    case OP_RETURN:
  Branch (293:5): [True: 36.9k, False: 3.05M]
294
169k
        return true;
295
7
    case OP_AWAIT_VALUE:
  Branch (295:5): [True: 7, False: 3.09M]
296
2.15k
    case OP_CALL_VALUE:
  Branch (296:5): [True: 2.14k, False: 3.09M]
297
2.15k
        return u8(r, &in->arity);
298
13.8k
    case OP_UNARY:
  Branch (298:5): [True: 13.8k, False: 3.08M]
299
13.8k
        if (!u8(r, &in->code) || in->code > 1) {
  Branch (299:13): [True: 2, False: 13.8k]
  Branch (299:34): [True: 23, False: 13.8k]
300
25
            fail(r, "unknown unary operator");
301
25
            return false;
302
25
        }
303
13.8k
        return true;
304
169k
    case OP_BINARY:
  Branch (304:5): [True: 169k, False: 2.92M]
305
169k
        if (!u8(r, &in->code) || in->code > 12) {
  Branch (305:13): [True: 2, False: 169k]
  Branch (305:34): [True: 18, False: 169k]
306
20
            fail(r, "unknown binary operator");
307
20
            return false;
308
20
        }
309
169k
        return true;
310
25.1k
    case OP_MAKE_ARRAY:
  Branch (310:5): [True: 25.1k, False: 3.06M]
311
25.1k
        if (!u16(r, &count)) {
  Branch (311:13): [True: 3, False: 25.1k]
312
3
            return false;
313
3
        }
314
25.1k
        in->count = count;
315
25.1k
        return true;
316
15.8k
    case OP_INTERPOLATE:
  Branch (316:5): [True: 15.8k, False: 3.07M]
317
15.8k
        if (!u16(r, &count)) {
  Branch (317:13): [True: 3, False: 15.8k]
318
3
            return false;
319
3
        }
320
15.8k
        in->count = count;
321
15.8k
        in->items = strings(r, count, false);
322
15.8k
        return !r->error;
323
19.8k
    case OP_ITER_NEXT:
  Branch (323:5): [True: 19.8k, False: 3.07M]
324
19.8k
        in->name = text(r, true);
325
19.8k
        in->name2 = text(r, true);
326
19.8k
        return in->name && in->name2 && u32(r, &in->target);
  Branch (326:16): [True: 19.7k, False: 64]
  Branch (326:28): [True: 19.6k, False: 56]
  Branch (326:41): [True: 19.6k, False: 4]
327
33.9k
    case OP_MAKE_RECORD:
  Branch (327:5): [True: 33.9k, False: 3.06M]
328
33.9k
        in->name = text(r, true);
329
33.9k
        if (!in->name || !u16(r, &count)) {
  Branch (329:13): [True: 44, False: 33.9k]
  Branch (329:26): [True: 2, False: 33.9k]
330
46
            return false;
331
46
        }
332
33.9k
        in->count = count;
333
33.9k
        in->items = strings(r, count, true);
334
33.9k
        return !r->error;
335
58.7k
    case OP_MAKE_VARIANT:
  Branch (335:5): [True: 58.7k, False: 3.03M]
336
58.7k
        in->name = text(r, true);
337
58.7k
        in->name2 = text(r, true);
338
58.7k
        if (!in->name || !in->name2 || !u16(r, &count)) {
  Branch (338:13): [True: 55, False: 58.6k]
  Branch (338:26): [True: 50, False: 58.6k]
  Branch (338:40): [True: 2, False: 58.6k]
339
107
            return false;
340
107
        }
341
58.6k
        in->count = count;
342
58.6k
        return true;
343
97.4k
    case OP_MATCH_VARIANT:
  Branch (343:5): [True: 97.4k, False: 2.99M]
344
97.4k
        in->name = text(r, true);
345
97.4k
        return in->name && u32(r, &in->target);
  Branch (345:16): [True: 97.3k, False: 50]
  Branch (345:28): [True: 97.3k, False: 4]
346
16
    case OP_AWAIT_CALL:
  Branch (346:5): [True: 16, False: 3.09M]
347
242k
    case OP_CALL:
  Branch (347:5): [True: 242k, False: 2.85M]
348
242k
        in->name = text(r, true);
349
242k
        return in->name && u8(r, &in->arity);
  Branch (349:16): [True: 242k, False: 74]
  Branch (349:28): [True: 242k, False: 1]
350
154k
    case OP_JUMP_FALSE:
  Branch (350:5): [True: 154k, False: 2.94M]
351
401k
    case OP_JUMP:
  Branch (351:5): [True: 246k, False: 2.84M]
352
401k
        return u32(r, &in->target);
353
778
    default:
  Branch (353:5): [True: 778, False: 3.09M]
354
778
        (void)ignored;
355
778
        fail(r, "unknown bytecode opcode");
356
778
        return false;
357
3.09M
    }
358
3.09M
}
359
360
bool decode(const uint8_t *data, size_t length, Program *p, const char **error)
361
23.6k
{
362
23.6k
    memset(p, 0, sizeof(*p));
363
23.6k
    Reader r = {data, length, 0, NULL};
364
23.6k
    const uint8_t *magic;
365
23.6k
    uint16_t version, count;
366
23.6k
    if (length > MAX_ARTIFACT) {
  Branch (366:9): [True: 1, False: 11.8k]
  Branch (366:9): [True: 1, False: 11.8k]
367
2
        *error = "artifact exceeds size limit";
368
2
        return false;
369
2
    }
370
23.6k
    if (!take(&r, 9, &magic) || memcmp(magic, "PANACKBC\0", 9)) {
  Branch (370:9): [True: 18, False: 11.7k]
  Branch (370:33): [True: 2.42k, False: 9.37k]
  Branch (370:9): [True: 18, False: 11.7k]
  Branch (370:33): [True: 2.42k, False: 9.37k]
371
4.87k
        *error = "not a Panackelty bytecode file";
372
4.87k
        return false;
373
4.87k
    }
374
18.7k
    if (!u16(&r, &version)) {
  Branch (374:9): [True: 6, False: 9.36k]
  Branch (374:9): [True: 6, False: 9.36k]
375
12
        *error = r.error;
376
12
        return false;
377
12
    }
378
18.7k
    if (version != 9) {
  Branch (378:9): [True: 537, False: 8.82k]
  Branch (378:9): [True: 537, False: 8.82k]
379
1.07k
        *error = "unsupported bytecode version";
380
1.07k
        return false;
381
1.07k
    }
382
17.6k
    if (!u16(&r, &count)) {
  Branch (382:9): [True: 6, False: 8.82k]
  Branch (382:9): [True: 6, False: 8.82k]
383
12
        *error = r.error;
384
12
        return false;
385
12
    }
386
17.6k
    if (count > MAX_FUNCTIONS) {
  Branch (386:9): [True: 248, False: 8.57k]
  Branch (386:9): [True: 248, False: 8.57k]
387
496
        *error = "function count exceeds limit";
388
496
        return false;
389
496
    }
390
17.1k
    p->count = count;
391
17.1k
    p->functions = calloc(count, sizeof(Function));
392
17.1k
    if (count && !p->functions) {
  Branch (392:9): [True: 8.57k, False: 3]
  Branch (392:18): [True: 4, False: 8.56k]
  Branch (392:9): [True: 8.57k, False: 3]
  Branch (392:18): [True: 4, False: 8.56k]
393
8
        *error = "out of memory";
394
8
        return false;
395
8
    }
396
17.1k
    size_t total = 0;
397
96.2k
    for (size_t i = 0; i < count && !r.error; i++) {
  Branch (397:24): [True: 42.2k, False: 5.83k]
  Branch (397:37): [True: 42.1k, False: 136]
  Branch (397:24): [True: 42.2k, False: 5.83k]
  Branch (397:37): [True: 42.1k, False: 136]
398
84.2k
        Function *f = &p->functions[i];
399
84.2k
        uint8_t flags, params;
400
84.2k
        uint32_t ins;
401
84.2k
        f->name = text(&r, true);
402
84.2k
        if (!f->name || !u8(&r, &flags) || flags > 2 || !u8(&r, &params)) {
  Branch (402:13): [True: 1.42k, False: 40.7k]
  Branch (402:25): [True: 5, False: 40.7k]
  Branch (402:44): [True: 288, False: 40.4k]
  Branch (402:57): [True: 4, False: 40.4k]
  Branch (402:13): [True: 1.42k, False: 40.7k]
  Branch (402:25): [True: 5, False: 40.7k]
  Branch (402:44): [True: 288, False: 40.4k]
  Branch (402:57): [True: 4, False: 40.4k]
403
3.44k
            if (!r.error) {
  Branch (403:17): [True: 288, False: 1.43k]
  Branch (403:17): [True: 288, False: 1.43k]
404
576
                fail(&r, "invalid function flags");
405
576
            }
406
3.44k
            break;
407
3.44k
        }
408
80.8k
        f->pure = flags == 1;
409
80.8k
        f->is_async = flags == 2;
410
80.8k
        f->param_count = params;
411
80.8k
        f->params = calloc(params, sizeof(char *));
412
80.8k
        if (params && !f->params) {
  Branch (412:13): [True: 33.5k, False: 6.88k]
  Branch (412:23): [True: 2, False: 33.5k]
  Branch (412:13): [True: 33.5k, False: 6.88k]
  Branch (412:23): [True: 2, False: 33.5k]
413
4
            fail(&r, "out of memory");
414
4
            break;
415
4
        }
416
219k
        for (size_t j = 0; j < params && !r.error; j++) {
  Branch (416:28): [True: 69.8k, False: 40.1k]
  Branch (416:42): [True: 69.5k, False: 277]
  Branch (416:28): [True: 69.8k, False: 40.1k]
  Branch (416:42): [True: 69.5k, False: 277]
417
139k
            f->params[j] = text(&r, true);
418
139k
        }
419
80.8k
        if (!u32(&r, &ins)) {
  Branch (419:13): [True: 279, False: 40.1k]
  Branch (419:13): [True: 279, False: 40.1k]
420
558
            break;
421
558
        }
422
80.2k
        if (ins > 1000000u || total + ins > MAX_INSTRUCTIONS) {
  Branch (422:13): [True: 592, False: 39.5k]
  Branch (422:31): [True: 0, False: 39.5k]
  Branch (422:13): [True: 592, False: 39.5k]
  Branch (422:31): [True: 0, False: 39.5k]
423
1.18k
            fail(&r, "instruction count exceeds limit");
424
1.18k
            break;
425
1.18k
        }
426
79.1k
        total += ins;
427
79.1k
        f->ins_count = ins;
428
79.1k
        f->ins = calloc(ins, sizeof(Instruction));
429
79.1k
        if (ins && !f->ins) {
  Branch (429:13): [True: 39.5k, False: 5]
  Branch (429:20): [True: 6, False: 39.5k]
  Branch (429:13): [True: 39.5k, False: 5]
  Branch (429:20): [True: 6, False: 39.5k]
430
12
            fail(&r, "out of memory");
431
12
            break;
432
12
        }
433
6.27M
        for (size_t j = 0; j < ins && !r.error; j++) {
  Branch (433:28): [True: 3.09M, False: 36.6k]
  Branch (433:39): [True: 3.09M, False: 2.89k]
  Branch (433:28): [True: 3.09M, False: 36.6k]
  Branch (433:39): [True: 3.09M, False: 2.89k]
434
6.19M
            instruction(&r, &f->ins[j]);
435
6.19M
        }
436
79.0k
    }
437
17.1k
    if (!r.error && r.at != r.len) {
  Branch (437:9): [True: 2.77k, False: 5.79k]
  Branch (437:21): [True: 33, False: 2.74k]
  Branch (437:9): [True: 2.77k, False: 5.79k]
  Branch (437:21): [True: 33, False: 2.74k]
438
66
        fail(&r, "trailing data");
439
66
    }
440
17.1k
    if (r.error) {
  Branch (440:9): [True: 5.83k, False: 2.74k]
  Branch (440:9): [True: 5.83k, False: 2.74k]
441
11.6k
        *error = r.error;
442
11.6k
        free_program(p);
443
11.6k
        return false;
444
11.6k
    }
445
5.48k
    return true;
446
17.1k
}
decode
Line
Count
Source
361
11.8k
{
362
11.8k
    memset(p, 0, sizeof(*p));
363
11.8k
    Reader r = {data, length, 0, NULL};
364
11.8k
    const uint8_t *magic;
365
11.8k
    uint16_t version, count;
366
11.8k
    if (length > MAX_ARTIFACT) {
  Branch (366:9): [True: 1, False: 11.8k]
367
1
        *error = "artifact exceeds size limit";
368
1
        return false;
369
1
    }
370
11.8k
    if (!take(&r, 9, &magic) || memcmp(magic, "PANACKBC\0", 9)) {
  Branch (370:9): [True: 18, False: 11.7k]
  Branch (370:33): [True: 2.42k, False: 9.37k]
371
2.43k
        *error = "not a Panackelty bytecode file";
372
2.43k
        return false;
373
2.43k
    }
374
9.37k
    if (!u16(&r, &version)) {
  Branch (374:9): [True: 6, False: 9.36k]
375
6
        *error = r.error;
376
6
        return false;
377
6
    }
378
9.36k
    if (version != 9) {
  Branch (378:9): [True: 537, False: 8.82k]
379
537
        *error = "unsupported bytecode version";
380
537
        return false;
381
537
    }
382
8.82k
    if (!u16(&r, &count)) {
  Branch (382:9): [True: 6, False: 8.82k]
383
6
        *error = r.error;
384
6
        return false;
385
6
    }
386
8.82k
    if (count > MAX_FUNCTIONS) {
  Branch (386:9): [True: 248, False: 8.57k]
387
248
        *error = "function count exceeds limit";
388
248
        return false;
389
248
    }
390
8.57k
    p->count = count;
391
8.57k
    p->functions = calloc(count, sizeof(Function));
392
8.57k
    if (count && !p->functions) {
  Branch (392:9): [True: 8.57k, False: 3]
  Branch (392:18): [True: 4, False: 8.56k]
393
4
        *error = "out of memory";
394
4
        return false;
395
4
    }
396
8.57k
    size_t total = 0;
397
48.1k
    for (size_t i = 0; i < count && !r.error; i++) {
  Branch (397:24): [True: 42.2k, False: 5.83k]
  Branch (397:37): [True: 42.1k, False: 136]
398
42.1k
        Function *f = &p->functions[i];
399
42.1k
        uint8_t flags, params;
400
42.1k
        uint32_t ins;
401
42.1k
        f->name = text(&r, true);
402
42.1k
        if (!f->name || !u8(&r, &flags) || flags > 2 || !u8(&r, &params)) {
  Branch (402:13): [True: 1.42k, False: 40.7k]
  Branch (402:25): [True: 5, False: 40.7k]
  Branch (402:44): [True: 288, False: 40.4k]
  Branch (402:57): [True: 4, False: 40.4k]
403
1.72k
            if (!r.error) {
  Branch (403:17): [True: 288, False: 1.43k]
404
288
                fail(&r, "invalid function flags");
405
288
            }
406
1.72k
            break;
407
1.72k
        }
408
40.4k
        f->pure = flags == 1;
409
40.4k
        f->is_async = flags == 2;
410
40.4k
        f->param_count = params;
411
40.4k
        f->params = calloc(params, sizeof(char *));
412
40.4k
        if (params && !f->params) {
  Branch (412:13): [True: 33.5k, False: 6.88k]
  Branch (412:23): [True: 2, False: 33.5k]
413
2
            fail(&r, "out of memory");
414
2
            break;
415
2
        }
416
109k
        for (size_t j = 0; j < params && !r.error; j++) {
  Branch (416:28): [True: 69.8k, False: 40.1k]
  Branch (416:42): [True: 69.5k, False: 277]
417
69.5k
            f->params[j] = text(&r, true);
418
69.5k
        }
419
40.4k
        if (!u32(&r, &ins)) {
  Branch (419:13): [True: 279, False: 40.1k]
420
279
            break;
421
279
        }
422
40.1k
        if (ins > 1000000u || total + ins > MAX_INSTRUCTIONS) {
  Branch (422:13): [True: 592, False: 39.5k]
  Branch (422:31): [True: 0, False: 39.5k]
423
592
            fail(&r, "instruction count exceeds limit");
424
592
            break;
425
592
        }
426
39.5k
        total += ins;
427
39.5k
        f->ins_count = ins;
428
39.5k
        f->ins = calloc(ins, sizeof(Instruction));
429
39.5k
        if (ins && !f->ins) {
  Branch (429:13): [True: 39.5k, False: 5]
  Branch (429:20): [True: 6, False: 39.5k]
430
6
            fail(&r, "out of memory");
431
6
            break;
432
6
        }
433
3.13M
        for (size_t j = 0; j < ins && !r.error; j++) {
  Branch (433:28): [True: 3.09M, False: 36.6k]
  Branch (433:39): [True: 3.09M, False: 2.89k]
434
3.09M
            instruction(&r, &f->ins[j]);
435
3.09M
        }
436
39.5k
    }
437
8.57k
    if (!r.error && r.at != r.len) {
  Branch (437:9): [True: 2.77k, False: 5.79k]
  Branch (437:21): [True: 33, False: 2.74k]
438
33
        fail(&r, "trailing data");
439
33
    }
440
8.57k
    if (r.error) {
  Branch (440:9): [True: 5.83k, False: 2.74k]
441
5.83k
        *error = r.error;
442
5.83k
        free_program(p);
443
5.83k
        return false;
444
5.83k
    }
445
2.74k
    return true;
446
8.57k
}
decode
Line
Count
Source
361
11.8k
{
362
11.8k
    memset(p, 0, sizeof(*p));
363
11.8k
    Reader r = {data, length, 0, NULL};
364
11.8k
    const uint8_t *magic;
365
11.8k
    uint16_t version, count;
366
11.8k
    if (length > MAX_ARTIFACT) {
  Branch (366:9): [True: 1, False: 11.8k]
367
1
        *error = "artifact exceeds size limit";
368
1
        return false;
369
1
    }
370
11.8k
    if (!take(&r, 9, &magic) || memcmp(magic, "PANACKBC\0", 9)) {
  Branch (370:9): [True: 18, False: 11.7k]
  Branch (370:33): [True: 2.42k, False: 9.37k]
371
2.43k
        *error = "not a Panackelty bytecode file";
372
2.43k
        return false;
373
2.43k
    }
374
9.37k
    if (!u16(&r, &version)) {
  Branch (374:9): [True: 6, False: 9.36k]
375
6
        *error = r.error;
376
6
        return false;
377
6
    }
378
9.36k
    if (version != 9) {
  Branch (378:9): [True: 537, False: 8.82k]
379
537
        *error = "unsupported bytecode version";
380
537
        return false;
381
537
    }
382
8.82k
    if (!u16(&r, &count)) {
  Branch (382:9): [True: 6, False: 8.82k]
383
6
        *error = r.error;
384
6
        return false;
385
6
    }
386
8.82k
    if (count > MAX_FUNCTIONS) {
  Branch (386:9): [True: 248, False: 8.57k]
387
248
        *error = "function count exceeds limit";
388
248
        return false;
389
248
    }
390
8.57k
    p->count = count;
391
8.57k
    p->functions = calloc(count, sizeof(Function));
392
8.57k
    if (count && !p->functions) {
  Branch (392:9): [True: 8.57k, False: 3]
  Branch (392:18): [True: 4, False: 8.56k]
393
4
        *error = "out of memory";
394
4
        return false;
395
4
    }
396
8.57k
    size_t total = 0;
397
48.1k
    for (size_t i = 0; i < count && !r.error; i++) {
  Branch (397:24): [True: 42.2k, False: 5.83k]
  Branch (397:37): [True: 42.1k, False: 136]
398
42.1k
        Function *f = &p->functions[i];
399
42.1k
        uint8_t flags, params;
400
42.1k
        uint32_t ins;
401
42.1k
        f->name = text(&r, true);
402
42.1k
        if (!f->name || !u8(&r, &flags) || flags > 2 || !u8(&r, &params)) {
  Branch (402:13): [True: 1.42k, False: 40.7k]
  Branch (402:25): [True: 5, False: 40.7k]
  Branch (402:44): [True: 288, False: 40.4k]
  Branch (402:57): [True: 4, False: 40.4k]
403
1.72k
            if (!r.error) {
  Branch (403:17): [True: 288, False: 1.43k]
404
288
                fail(&r, "invalid function flags");
405
288
            }
406
1.72k
            break;
407
1.72k
        }
408
40.4k
        f->pure = flags == 1;
409
40.4k
        f->is_async = flags == 2;
410
40.4k
        f->param_count = params;
411
40.4k
        f->params = calloc(params, sizeof(char *));
412
40.4k
        if (params && !f->params) {
  Branch (412:13): [True: 33.5k, False: 6.88k]
  Branch (412:23): [True: 2, False: 33.5k]
413
2
            fail(&r, "out of memory");
414
2
            break;
415
2
        }
416
109k
        for (size_t j = 0; j < params && !r.error; j++) {
  Branch (416:28): [True: 69.8k, False: 40.1k]
  Branch (416:42): [True: 69.5k, False: 277]
417
69.5k
            f->params[j] = text(&r, true);
418
69.5k
        }
419
40.4k
        if (!u32(&r, &ins)) {
  Branch (419:13): [True: 279, False: 40.1k]
420
279
            break;
421
279
        }
422
40.1k
        if (ins > 1000000u || total + ins > MAX_INSTRUCTIONS) {
  Branch (422:13): [True: 592, False: 39.5k]
  Branch (422:31): [True: 0, False: 39.5k]
423
592
            fail(&r, "instruction count exceeds limit");
424
592
            break;
425
592
        }
426
39.5k
        total += ins;
427
39.5k
        f->ins_count = ins;
428
39.5k
        f->ins = calloc(ins, sizeof(Instruction));
429
39.5k
        if (ins && !f->ins) {
  Branch (429:13): [True: 39.5k, False: 5]
  Branch (429:20): [True: 6, False: 39.5k]
430
6
            fail(&r, "out of memory");
431
6
            break;
432
6
        }
433
3.13M
        for (size_t j = 0; j < ins && !r.error; j++) {
  Branch (433:28): [True: 3.09M, False: 36.6k]
  Branch (433:39): [True: 3.09M, False: 2.89k]
434
3.09M
            instruction(&r, &f->ins[j]);
435
3.09M
        }
436
39.5k
    }
437
8.57k
    if (!r.error && r.at != r.len) {
  Branch (437:9): [True: 2.77k, False: 5.79k]
  Branch (437:21): [True: 33, False: 2.74k]
438
33
        fail(&r, "trailing data");
439
33
    }
440
8.57k
    if (r.error) {
  Branch (440:9): [True: 5.83k, False: 2.74k]
441
5.83k
        *error = r.error;
442
5.83k
        free_program(p);
443
5.83k
        return false;
444
5.83k
    }
445
2.74k
    return true;
446
8.57k
}