Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/univalue/lib/univalue_read.cpp
Line
Count
Source
1
// Copyright 2014 BitPay Inc.
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or https://opensource.org/licenses/mit-license.php.
4
5
#include <univalue.h>
6
#include <univalue_utffilter.h>
7
8
#include <cstdint>
9
#include <cstdio>
10
#include <cstring>
11
#include <string>
12
#include <string_view>
13
#include <vector>
14
15
/*
16
 * According to stackexchange, the original json test suite wanted
17
 * to limit depth to 22.  Widely-deployed PHP bails at depth 512,
18
 * so we will follow PHP's lead, which should be more than sufficient
19
 * (further stackexchange comments indicate depth > 32 rarely occurs).
20
 */
21
static constexpr size_t MAX_JSON_DEPTH = 512;
22
23
static bool json_isdigit(int ch)
24
36.1M
{
25
36.1M
    return ((ch >= '0') && (ch <= '9'));
  Branch (25:13): [True: 33.2M, False: 2.88M]
  Branch (25:28): [True: 31.0M, False: 2.27M]
26
36.1M
}
27
28
// convert hexadecimal string to unsigned integer
29
static const char *hatoui(const char *first, const char *last,
30
                          unsigned int& out)
31
0
{
32
0
    unsigned int result = 0;
33
0
    for (; first != last; ++first)
  Branch (33:12): [True: 0, False: 0]
34
0
    {
35
0
        int digit;
36
0
        if (json_isdigit(*first))
  Branch (36:13): [True: 0, False: 0]
37
0
            digit = *first - '0';
38
39
0
        else if (*first >= 'a' && *first <= 'f')
  Branch (39:18): [True: 0, False: 0]
  Branch (39:35): [True: 0, False: 0]
40
0
            digit = *first - 'a' + 10;
41
42
0
        else if (*first >= 'A' && *first <= 'F')
  Branch (42:18): [True: 0, False: 0]
  Branch (42:35): [True: 0, False: 0]
43
0
            digit = *first - 'A' + 10;
44
45
0
        else
46
0
            break;
47
48
0
        result = 16 * result + digit;
49
0
    }
50
0
    out = result;
51
52
0
    return first;
53
0
}
54
55
enum jtokentype getJsonToken(std::string& tokenVal, unsigned int& consumed,
56
                            const char *raw, const char *end)
57
48.3M
{
58
48.3M
    tokenVal.clear();
59
48.3M
    consumed = 0;
60
61
48.3M
    const char *rawStart = raw;
62
63
48.3M
    while (raw < end && (json_isspace(*raw)))          // skip whitespace
  Branch (63:12): [True: 45.9M, False: 2.35M]
  Branch (63:25): [True: 0, False: 45.9M]
64
0
        raw++;
65
66
48.3M
    if (raw >= end)
  Branch (66:9): [True: 2.35M, False: 45.9M]
67
2.35M
        return JTOK_NONE;
68
69
45.9M
    switch (*raw) {
70
71
2.35M
    case '{':
  Branch (71:5): [True: 2.35M, False: 43.5M]
72
2.35M
        raw++;
73
2.35M
        consumed = (raw - rawStart);
74
2.35M
        return JTOK_OBJ_OPEN;
75
2.35M
    case '}':
  Branch (75:5): [True: 2.35M, False: 43.5M]
76
2.35M
        raw++;
77
2.35M
        consumed = (raw - rawStart);
78
2.35M
        return JTOK_OBJ_CLOSE;
79
2.35M
    case '[':
  Branch (79:5): [True: 2.35M, False: 43.5M]
80
2.35M
        raw++;
81
2.35M
        consumed = (raw - rawStart);
82
2.35M
        return JTOK_ARR_OPEN;
83
2.35M
    case ']':
  Branch (83:5): [True: 2.35M, False: 43.5M]
84
2.35M
        raw++;
85
2.35M
        consumed = (raw - rawStart);
86
2.35M
        return JTOK_ARR_CLOSE;
87
88
9.43M
    case ':':
  Branch (88:5): [True: 9.43M, False: 36.5M]
89
9.43M
        raw++;
90
9.43M
        consumed = (raw - rawStart);
91
9.43M
        return JTOK_COLON;
92
7.16M
    case ',':
  Branch (92:5): [True: 7.16M, False: 38.7M]
93
7.16M
        raw++;
94
7.16M
        consumed = (raw - rawStart);
95
7.16M
        return JTOK_COMMA;
96
97
0
    case 'n':
  Branch (97:5): [True: 0, False: 45.9M]
98
0
    case 't':
  Branch (98:5): [True: 0, False: 45.9M]
99
44.3k
    case 'f':
  Branch (99:5): [True: 44.3k, False: 45.8M]
100
44.3k
        if (!strncmp(raw, "null", 4)) {
  Branch (100:13): [True: 0, False: 44.3k]
101
0
            raw += 4;
102
0
            consumed = (raw - rawStart);
103
0
            return JTOK_KW_NULL;
104
44.3k
        } else if (!strncmp(raw, "true", 4)) {
  Branch (104:20): [True: 0, False: 44.3k]
105
0
            raw += 4;
106
0
            consumed = (raw - rawStart);
107
0
            return JTOK_KW_TRUE;
108
44.3k
        } else if (!strncmp(raw, "false", 5)) {
  Branch (108:20): [True: 44.3k, False: 0]
109
44.3k
            raw += 5;
110
44.3k
            consumed = (raw - rawStart);
111
44.3k
            return JTOK_KW_FALSE;
112
44.3k
        } else
113
0
            return JTOK_ERR;
114
115
26.9k
    case '-':
  Branch (115:5): [True: 26.9k, False: 45.9M]
116
492k
    case '0':
  Branch (116:5): [True: 465k, False: 45.4M]
117
4.36M
    case '1':
  Branch (117:5): [True: 3.86M, False: 42.0M]
118
4.63M
    case '2':
  Branch (118:5): [True: 276k, False: 45.6M]
119
4.76M
    case '3':
  Branch (119:5): [True: 122k, False: 45.8M]
120
4.96M
    case '4':
  Branch (120:5): [True: 200k, False: 45.7M]
121
5.08M
    case '5':
  Branch (121:5): [True: 123k, False: 45.8M]
122
5.20M
    case '6':
  Branch (122:5): [True: 123k, False: 45.8M]
123
5.32M
    case '7':
  Branch (123:5): [True: 122k, False: 45.8M]
124
5.45M
    case '8':
  Branch (124:5): [True: 124k, False: 45.8M]
125
5.59M
    case '9': {
  Branch (125:5): [True: 144k, False: 45.7M]
126
        // part 1: int
127
5.59M
        std::string numStr;
128
129
5.59M
        const char *first = raw;
130
131
5.59M
        const char *firstDigit = first;
132
5.59M
        if (!json_isdigit(*firstDigit))
  Branch (132:13): [True: 26.9k, False: 5.57M]
133
26.9k
            firstDigit++;
134
5.59M
        if ((*firstDigit == '0') && json_isdigit(firstDigit[1]))
  Branch (134:13): [True: 465k, False: 5.13M]
  Branch (134:37): [True: 0, False: 465k]
135
0
            return JTOK_ERR;
136
137
5.59M
        numStr += *raw;                       // copy first char
138
5.59M
        raw++;
139
140
5.59M
        if ((*first == '-') && (raw < end) && (!json_isdigit(*raw)))
  Branch (140:13): [True: 26.9k, False: 5.57M]
  Branch (140:32): [True: 26.9k, False: 0]
  Branch (140:47): [True: 0, False: 26.9k]
141
0
            return JTOK_ERR;
142
143
30.7M
        while (raw < end && json_isdigit(*raw)) {  // copy digits
  Branch (143:16): [True: 29.7M, False: 947k]
  Branch (143:29): [True: 25.1M, False: 4.65M]
144
25.1M
            numStr += *raw;
145
25.1M
            raw++;
146
25.1M
        }
147
148
        // part 2: frac
149
5.59M
        if (raw < end && *raw == '.') {
  Branch (149:13): [True: 4.65M, False: 947k]
  Branch (149:26): [True: 33.2k, False: 4.61M]
150
33.2k
            numStr += *raw;                   // copy .
151
33.2k
            raw++;
152
153
33.2k
            if (raw >= end || !json_isdigit(*raw))
  Branch (153:17): [True: 0, False: 33.2k]
  Branch (153:31): [True: 0, False: 33.2k]
154
0
                return JTOK_ERR;
155
244k
            while (raw < end && json_isdigit(*raw)) { // copy digits
  Branch (155:20): [True: 221k, False: 22.1k]
  Branch (155:33): [True: 210k, False: 11.0k]
156
210k
                numStr += *raw;
157
210k
                raw++;
158
210k
            }
159
33.2k
        }
160
161
        // part 3: exp
162
5.59M
        if (raw < end && (*raw == 'e' || *raw == 'E')) {
  Branch (162:13): [True: 4.62M, False: 969k]
  Branch (162:27): [True: 11.0k, False: 4.61M]
  Branch (162:42): [True: 0, False: 4.61M]
163
11.0k
            numStr += *raw;                   // copy E
164
11.0k
            raw++;
165
166
11.0k
            if (raw < end && (*raw == '-' || *raw == '+')) { // copy +/-
  Branch (166:17): [True: 11.0k, False: 0]
  Branch (166:31): [True: 11.0k, False: 0]
  Branch (166:46): [True: 0, False: 0]
167
11.0k
                numStr += *raw;
168
11.0k
                raw++;
169
11.0k
            }
170
171
11.0k
            if (raw >= end || !json_isdigit(*raw))
  Branch (171:17): [True: 0, False: 11.0k]
  Branch (171:31): [True: 0, False: 11.0k]
172
0
                return JTOK_ERR;
173
33.2k
            while (raw < end && json_isdigit(*raw)) { // copy digits
  Branch (173:20): [True: 22.1k, False: 11.0k]
  Branch (173:33): [True: 22.1k, False: 0]
174
22.1k
                numStr += *raw;
175
22.1k
                raw++;
176
22.1k
            }
177
11.0k
        }
178
179
5.59M
        tokenVal = numStr;
180
5.59M
        consumed = (raw - rawStart);
181
5.59M
        return JTOK_NUMBER;
182
5.59M
        }
183
184
14.2M
    case '"': {
  Branch (184:5): [True: 14.2M, False: 31.6M]
185
14.2M
        raw++;                                // skip "
186
187
14.2M
        std::string valStr;
188
14.2M
        JSONUTF8StringFilter writer(valStr);
189
190
100M
        while (true) {
  Branch (190:16): [Folded - Ignored]
191
100M
            if (raw >= end || (unsigned char)*raw < 0x20)
  Branch (191:17): [True: 0, False: 100M]
  Branch (191:31): [True: 0, False: 100M]
192
0
                return JTOK_ERR;
193
194
100M
            else if (*raw == '\\') {
  Branch (194:22): [True: 55.4k, False: 100M]
195
55.4k
                raw++;                        // skip backslash
196
197
55.4k
                if (raw >= end)
  Branch (197:21): [True: 0, False: 55.4k]
198
0
                    return JTOK_ERR;
199
200
55.4k
                switch (*raw) {
201
0
                case '"':  writer.push_back('\"'); break;
  Branch (201:17): [True: 0, False: 55.4k]
202
0
                case '\\': writer.push_back('\\'); break;
  Branch (202:17): [True: 0, False: 55.4k]
203
0
                case '/':  writer.push_back('/'); break;
  Branch (203:17): [True: 0, False: 55.4k]
204
0
                case 'b':  writer.push_back('\b'); break;
  Branch (204:17): [True: 0, False: 55.4k]
205
0
                case 'f':  writer.push_back('\f'); break;
  Branch (205:17): [True: 0, False: 55.4k]
206
55.4k
                case 'n':  writer.push_back('\n'); break;
  Branch (206:17): [True: 55.4k, False: 0]
207
0
                case 'r':  writer.push_back('\r'); break;
  Branch (207:17): [True: 0, False: 55.4k]
208
0
                case 't':  writer.push_back('\t'); break;
  Branch (208:17): [True: 0, False: 55.4k]
209
210
0
                case 'u': {
  Branch (210:17): [True: 0, False: 55.4k]
211
0
                    unsigned int codepoint;
212
0
                    if (raw + 1 + 4 >= end ||
  Branch (212:25): [True: 0, False: 0]
213
0
                        hatoui(raw + 1, raw + 1 + 4, codepoint) !=
  Branch (213:25): [True: 0, False: 0]
214
0
                               raw + 1 + 4)
215
0
                        return JTOK_ERR;
216
0
                    writer.push_back_u(codepoint);
217
0
                    raw += 4;
218
0
                    break;
219
0
                    }
220
0
                default:
  Branch (220:17): [True: 0, False: 55.4k]
221
0
                    return JTOK_ERR;
222
223
55.4k
                }
224
225
55.4k
                raw++;                        // skip esc'd char
226
55.4k
            }
227
228
100M
            else if (*raw == '"') {
  Branch (228:22): [True: 14.2M, False: 86.1M]
229
14.2M
                raw++;                        // skip "
230
14.2M
                break;                        // stop scanning
231
14.2M
            }
232
233
86.1M
            else {
234
86.1M
                writer.push_back(static_cast<unsigned char>(*raw));
235
86.1M
                raw++;
236
86.1M
            }
237
100M
        }
238
239
14.2M
        if (!writer.finalize())
  Branch (239:13): [True: 0, False: 14.2M]
240
0
            return JTOK_ERR;
241
14.2M
        tokenVal = valStr;
242
14.2M
        consumed = (raw - rawStart);
243
14.2M
        return JTOK_STRING;
244
14.2M
        }
245
246
0
    default:
  Branch (246:5): [True: 0, False: 45.9M]
247
0
        return JTOK_ERR;
248
45.9M
    }
249
45.9M
}
250
251
enum expect_bits : unsigned {
252
    EXP_OBJ_NAME = (1U << 0),
253
    EXP_COLON = (1U << 1),
254
    EXP_ARR_VALUE = (1U << 2),
255
    EXP_VALUE = (1U << 3),
256
    EXP_NOT_VALUE = (1U << 4),
257
};
258
259
224M
#define expect(bit) (expectMask & (EXP_##bit))
260
54.3M
#define setExpect(bit) (expectMask |= EXP_##bit)
261
56.7M
#define clearExpect(bit) (expectMask &= ~EXP_##bit)
262
263
bool UniValue::read(std::string_view str_in)
264
2.35M
{
265
2.35M
    clear();
266
267
2.35M
    uint32_t expectMask = 0;
268
2.35M
    std::vector<UniValue*> stack;
269
270
2.35M
    std::string tokenVal;
271
2.35M
    unsigned int consumed;
272
2.35M
    enum jtokentype tok = JTOK_NONE;
273
2.35M
    enum jtokentype last_tok = JTOK_NONE;
274
2.35M
    const char* raw{str_in.data()};
275
2.35M
    const char* end{raw + str_in.size()};
276
44.9M
    do {
277
44.9M
        last_tok = tok;
278
279
44.9M
        tok = getJsonToken(tokenVal, consumed, raw, end);
280
44.9M
        if (tok == JTOK_NONE || tok == JTOK_ERR)
  Branch (280:13): [True: 0, False: 44.9M]
  Branch (280:33): [True: 0, False: 44.9M]
281
0
            return false;
282
44.9M
        raw += consumed;
283
284
44.9M
        bool isValueOpen = jsonTokenIsValue(tok) ||
  Branch (284:28): [True: 18.9M, False: 26.0M]
285
44.9M
            tok == JTOK_OBJ_OPEN || tok == JTOK_ARR_OPEN;
  Branch (285:13): [True: 2.35M, False: 23.6M]
  Branch (285:37): [True: 2.35M, False: 21.3M]
286
287
44.9M
        if (expect(VALUE)) {
288
9.43M
            if (!isValueOpen)
  Branch (288:17): [True: 0, False: 9.43M]
289
0
                return false;
290
9.43M
            clearExpect(VALUE);
291
292
35.5M
        } else if (expect(ARR_VALUE)) {
293
2.44M
            bool isArrValue = isValueOpen || (tok == JTOK_ARR_CLOSE);
  Branch (293:31): [True: 2.41M, False: 33.2k]
  Branch (293:46): [True: 33.2k, False: 0]
294
2.44M
            if (!isArrValue)
  Branch (294:17): [True: 0, False: 2.44M]
295
0
                return false;
296
297
2.44M
            clearExpect(ARR_VALUE);
298
299
33.0M
        } else if (expect(OBJ_NAME)) {
300
9.43M
            bool isObjName = (tok == JTOK_OBJ_CLOSE || tok == JTOK_STRING);
  Branch (300:31): [True: 0, False: 9.43M]
  Branch (300:56): [True: 9.43M, False: 0]
301
9.43M
            if (!isObjName)
  Branch (301:17): [True: 0, False: 9.43M]
302
0
                return false;
303
304
23.6M
        } else if (expect(COLON)) {
305
9.43M
            if (tok != JTOK_COLON)
  Branch (305:17): [True: 0, False: 9.43M]
306
0
                return false;
307
9.43M
            clearExpect(COLON);
308
309
14.2M
        } else if (!expect(COLON) && (tok == JTOK_COLON)) {
  Branch (309:20): [True: 14.2M, False: 0]
  Branch (309:38): [True: 0, False: 14.2M]
310
0
            return false;
311
0
        }
312
313
44.9M
        if (expect(NOT_VALUE)) {
314
21.2M
            if (isValueOpen)
  Branch (314:17): [True: 0, False: 21.2M]
315
0
                return false;
316
21.2M
            clearExpect(NOT_VALUE);
317
21.2M
        }
318
319
44.9M
        switch (tok) {
320
321
2.35M
        case JTOK_OBJ_OPEN:
  Branch (321:9): [True: 2.35M, False: 42.6M]
322
4.71M
        case JTOK_ARR_OPEN: {
  Branch (322:9): [True: 2.35M, False: 42.6M]
323
4.71M
            VType utyp = (tok == JTOK_OBJ_OPEN ? VOBJ : VARR);
  Branch (323:27): [True: 2.35M, False: 2.35M]
324
4.71M
            if (!stack.size()) {
  Branch (324:17): [True: 2.35M, False: 2.35M]
325
2.35M
                if (utyp == VOBJ)
  Branch (325:21): [True: 2.35M, False: 0]
326
2.35M
                    setObject();
327
0
                else
328
0
                    setArray();
329
2.35M
                stack.push_back(this);
330
2.35M
            } else {
331
2.35M
                UniValue tmpVal(utyp);
332
2.35M
                UniValue *top = stack.back();
333
2.35M
                top->values.push_back(tmpVal);
334
335
2.35M
                UniValue *newTop = &(top->values.back());
336
2.35M
                stack.push_back(newTop);
337
2.35M
            }
338
339
4.71M
            if (stack.size() > MAX_JSON_DEPTH)
  Branch (339:17): [True: 0, False: 4.71M]
340
0
                return false;
341
342
4.71M
            if (utyp == VOBJ)
  Branch (342:17): [True: 2.35M, False: 2.35M]
343
2.35M
                setExpect(OBJ_NAME);
344
2.35M
            else
345
2.35M
                setExpect(ARR_VALUE);
346
4.71M
            break;
347
4.71M
            }
348
349
2.35M
        case JTOK_OBJ_CLOSE:
  Branch (349:9): [True: 2.35M, False: 42.6M]
350
4.71M
        case JTOK_ARR_CLOSE: {
  Branch (350:9): [True: 2.35M, False: 42.6M]
351
4.71M
            if (!stack.size() || (last_tok == JTOK_COMMA))
  Branch (351:17): [True: 0, False: 4.71M]
  Branch (351:34): [True: 0, False: 4.71M]
352
0
                return false;
353
354
4.71M
            VType utyp = (tok == JTOK_OBJ_CLOSE ? VOBJ : VARR);
  Branch (354:27): [True: 2.35M, False: 2.35M]
355
4.71M
            UniValue *top = stack.back();
356
4.71M
            if (utyp != top->getType())
  Branch (356:17): [True: 0, False: 4.71M]
357
0
                return false;
358
359
4.71M
            stack.pop_back();
360
4.71M
            clearExpect(OBJ_NAME);
361
4.71M
            setExpect(NOT_VALUE);
362
4.71M
            break;
363
4.71M
            }
364
365
9.43M
        case JTOK_COLON: {
  Branch (365:9): [True: 9.43M, False: 35.5M]
366
9.43M
            if (!stack.size())
  Branch (366:17): [True: 0, False: 9.43M]
367
0
                return false;
368
369
9.43M
            UniValue *top = stack.back();
370
9.43M
            if (top->getType() != VOBJ)
  Branch (370:17): [True: 0, False: 9.43M]
371
0
                return false;
372
373
9.43M
            setExpect(VALUE);
374
9.43M
            break;
375
9.43M
            }
376
377
7.16M
        case JTOK_COMMA: {
  Branch (377:9): [True: 7.16M, False: 37.7M]
378
7.16M
            if (!stack.size() ||
  Branch (378:17): [True: 0, False: 7.16M]
379
7.16M
                (last_tok == JTOK_COMMA) || (last_tok == JTOK_ARR_OPEN))
  Branch (379:17): [True: 0, False: 7.16M]
  Branch (379:45): [True: 0, False: 7.16M]
380
0
                return false;
381
382
7.16M
            UniValue *top = stack.back();
383
7.16M
            if (top->getType() == VOBJ)
  Branch (383:17): [True: 7.07M, False: 88.7k]
384
7.07M
                setExpect(OBJ_NAME);
385
88.7k
            else
386
88.7k
                setExpect(ARR_VALUE);
387
7.16M
            break;
388
7.16M
            }
389
390
0
        case JTOK_KW_NULL:
  Branch (390:9): [True: 0, False: 44.9M]
391
0
        case JTOK_KW_TRUE:
  Branch (391:9): [True: 0, False: 44.9M]
392
44.3k
        case JTOK_KW_FALSE: {
  Branch (392:9): [True: 44.3k, False: 44.9M]
393
44.3k
            UniValue tmpVal;
394
44.3k
            switch (tok) {
395
0
            case JTOK_KW_NULL:
  Branch (395:13): [True: 0, False: 44.3k]
396
                // do nothing more
397
0
                break;
398
0
            case JTOK_KW_TRUE:
  Branch (398:13): [True: 0, False: 44.3k]
399
0
                tmpVal.setBool(true);
400
0
                break;
401
44.3k
            case JTOK_KW_FALSE:
  Branch (401:13): [True: 44.3k, False: 0]
402
44.3k
                tmpVal.setBool(false);
403
44.3k
                break;
404
0
            default: /* impossible */ break;
  Branch (404:13): [True: 0, False: 44.3k]
405
44.3k
            }
406
407
44.3k
            if (!stack.size()) {
  Branch (407:17): [True: 0, False: 44.3k]
408
0
                *this = tmpVal;
409
0
                break;
410
0
            }
411
412
44.3k
            UniValue *top = stack.back();
413
44.3k
            top->values.push_back(tmpVal);
414
415
44.3k
            setExpect(NOT_VALUE);
416
44.3k
            break;
417
44.3k
            }
418
419
4.61M
        case JTOK_NUMBER: {
  Branch (419:9): [True: 4.61M, False: 40.3M]
420
4.61M
            UniValue tmpVal(VNUM, tokenVal);
421
4.61M
            if (!stack.size()) {
  Branch (421:17): [True: 0, False: 4.61M]
422
0
                *this = tmpVal;
423
0
                break;
424
0
            }
425
426
4.61M
            UniValue *top = stack.back();
427
4.61M
            top->values.push_back(tmpVal);
428
429
4.61M
            setExpect(NOT_VALUE);
430
4.61M
            break;
431
4.61M
            }
432
433
14.2M
        case JTOK_STRING: {
  Branch (433:9): [True: 14.2M, False: 30.6M]
434
14.2M
            if (expect(OBJ_NAME)) {
435
9.43M
                UniValue *top = stack.back();
436
9.43M
                top->keys.push_back(tokenVal);
437
9.43M
                clearExpect(OBJ_NAME);
438
9.43M
                setExpect(COLON);
439
9.43M
            } else {
440
4.82M
                UniValue tmpVal(VSTR, tokenVal);
441
4.82M
                if (!stack.size()) {
  Branch (441:21): [True: 0, False: 4.82M]
442
0
                    *this = tmpVal;
443
0
                    break;
444
0
                }
445
4.82M
                UniValue *top = stack.back();
446
4.82M
                top->values.push_back(tmpVal);
447
4.82M
            }
448
449
14.2M
            setExpect(NOT_VALUE);
450
14.2M
            break;
451
14.2M
            }
452
453
0
        default:
  Branch (453:9): [True: 0, False: 44.9M]
454
0
            return false;
455
44.9M
        }
456
44.9M
    } while (!stack.empty ());
  Branch (456:14): [True: 42.6M, False: 2.35M]
457
458
    /* Check that nothing follows the initial construct (parsed above).  */
459
2.35M
    tok = getJsonToken(tokenVal, consumed, raw, end);
460
2.35M
    if (tok != JTOK_NONE)
  Branch (460:9): [True: 0, False: 2.35M]
461
0
        return false;
462
463
2.35M
    return true;
464
2.35M
}
465