Coverage Report

Created: 2026-08-13 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jq/src/jv_parse.c
Line
Count
Source
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <limits.h>
5
#include <assert.h>
6
#include "jv.h"
7
#include "jv_dtoa.h"
8
#include "jv_unicode.h"
9
#include "jv_alloc.h"
10
#include "jv_dtoa.h"
11
12
typedef const char* presult;
13
14
#ifndef MAX_PARSING_DEPTH
15
50.7k
#define MAX_PARSING_DEPTH (10000)
16
#endif
17
18
29.3M
#define TRY(x) do {presult msg__ = (x); if (msg__) return msg__; } while(0)
19
#ifdef __GNUC__
20
#define pfunc __attribute__((warn_unused_result)) presult
21
#else
22
#define pfunc presult
23
#endif
24
25
enum last_seen {
26
  JV_LAST_NONE = 0,
27
  JV_LAST_OPEN_ARRAY = '[',
28
  JV_LAST_OPEN_OBJECT = '{',
29
  JV_LAST_COLON = ':',
30
  JV_LAST_COMMA = ',',
31
  JV_LAST_VALUE = 'V',
32
};
33
34
struct jv_parser {
35
  const char* curr_buf;
36
  int curr_buf_length;
37
  int curr_buf_pos;
38
  int curr_buf_is_partial;
39
  int eof;
40
  unsigned bom_strip_position;
41
42
  int flags;
43
44
  jv* stack;                   // parser
45
  int stackpos;                // parser
46
  int stacklen;                // both (optimization; it's really pathlen for streaming)
47
  jv path;                     // streamer
48
  enum last_seen last_seen;    // streamer
49
  jv output;                   // streamer
50
  jv next;                     // both
51
52
  char* tokenbuf;
53
  int tokenpos;
54
  int tokenlen;
55
56
  int line, column;
57
58
  struct dtoa_context dtoa;
59
60
  enum {
61
    JV_PARSER_NORMAL,
62
    JV_PARSER_STRING,
63
    JV_PARSER_STRING_ESCAPE,
64
    JV_PARSER_WAITING_FOR_RS // parse error, waiting for RS
65
  } st;
66
  unsigned int last_ch_was_ws:1;
67
};
68
69
70
496k
static void parser_init(struct jv_parser* p, int flags) {
71
496k
  p->flags = flags;
72
496k
  if ((p->flags & JV_PARSE_STREAMING)) {
73
0
    p->path = jv_array();
74
496k
  } else {
75
496k
    p->path = jv_invalid();
76
496k
    p->flags &= ~(JV_PARSE_STREAM_ERRORS);
77
496k
  }
78
496k
  p->stack = 0;
79
496k
  p->stacklen = p->stackpos = 0;
80
496k
  p->last_seen = JV_LAST_NONE;
81
496k
  p->output = jv_invalid();
82
496k
  p->next = jv_invalid();
83
496k
  p->tokenlen = 256;
84
496k
  p->tokenbuf = jv_mem_alloc(p->tokenlen);
85
496k
  p->tokenpos = 0;
86
496k
  if ((p->flags & JV_PARSE_SEQ))
87
0
    p->st = JV_PARSER_WAITING_FOR_RS;
88
496k
  else
89
496k
    p->st = JV_PARSER_NORMAL;
90
496k
  p->eof = 0;
91
496k
  p->curr_buf = 0;
92
496k
  p->curr_buf_length = p->curr_buf_pos = p->curr_buf_is_partial = 0;
93
496k
  p->bom_strip_position = 0;
94
496k
  p->last_ch_was_ws = 0;
95
496k
  p->line = 1;
96
496k
  p->column = 0;
97
496k
  jvp_dtoa_context_init(&p->dtoa);
98
496k
}
99
100
525k
static void parser_reset(struct jv_parser* p) {
101
525k
  if ((p->flags & JV_PARSE_STREAMING)) {
102
0
    jv_free(p->path);
103
0
    p->path = jv_array();
104
0
    p->stacklen = 0;
105
0
  }
106
525k
  p->last_seen = JV_LAST_NONE;
107
525k
  jv_free(p->output);
108
525k
  p->output = jv_invalid();
109
525k
  jv_free(p->next);
110
525k
  p->next = jv_invalid();
111
568k
  for (int i=0; i<p->stackpos; i++)
112
42.9k
    jv_free(p->stack[i]);
113
525k
  p->stackpos = 0;
114
525k
  p->tokenpos = 0;
115
525k
  p->st = JV_PARSER_NORMAL;
116
525k
}
117
118
496k
static void parser_free(struct jv_parser* p) {
119
496k
  parser_reset(p);
120
496k
  jv_free(p->path);
121
496k
  jv_free(p->output);
122
496k
  jv_mem_free(p->stack);
123
496k
  jv_mem_free(p->tokenbuf);
124
496k
  jvp_dtoa_context_free(&p->dtoa);
125
496k
}
126
127
501k
static pfunc value(struct jv_parser* p, jv val) {
128
501k
  if ((p->flags & JV_PARSE_STREAMING)) {
129
0
    if (jv_is_valid(p->next) || p->last_seen == JV_LAST_VALUE) {
130
0
      jv_free(val);
131
0
      return "Expected separator between values";
132
0
    }
133
0
    if (p->stacklen > 0)
134
0
      p->last_seen = JV_LAST_VALUE;
135
0
    else
136
0
      p->last_seen = JV_LAST_NONE;
137
501k
  } else {
138
501k
    if (jv_is_valid(p->next)) {
139
2.32k
      jv_free(val);
140
2.32k
      return "Expected separator between values";
141
2.32k
    }
142
501k
  }
143
499k
  jv_free(p->next);
144
499k
  p->next = val;
145
499k
  return 0;
146
501k
}
147
148
50.3k
static void push(struct jv_parser* p, jv v) {
149
50.3k
  assert(p->stackpos <= p->stacklen);
150
50.3k
  if (p->stackpos == p->stacklen) {
151
22.9k
    p->stacklen = p->stacklen * 2 + 10;
152
22.9k
    p->stack = jv_mem_realloc(p->stack, p->stacklen * sizeof(jv));
153
22.9k
  }
154
50.3k
  assert(p->stackpos < p->stacklen);
155
50.3k
  p->stack[p->stackpos++] = v;
156
50.3k
}
157
158
80.9k
static pfunc parse_token(struct jv_parser* p, char ch) {
159
80.9k
  switch (ch) {
160
35.1k
  case '[':
161
35.1k
    if (p->stackpos >= MAX_PARSING_DEPTH) return "Exceeds depth limit for parsing";
162
35.1k
    if (jv_is_valid(p->next)) return "Expected separator between values";
163
34.9k
    push(p, jv_array());
164
34.9k
    break;
165
166
15.5k
  case '{':
167
15.5k
    if (p->stackpos >= MAX_PARSING_DEPTH) return "Exceeds depth limit for parsing";
168
15.5k
    if (jv_is_valid(p->next)) return "Expected separator between values";
169
14.2k
    push(p, jv_object());
170
14.2k
    break;
171
172
3.17k
  case ':':
173
3.17k
    if (!jv_is_valid(p->next))
174
342
      return "Expected string key before ':'";
175
2.83k
    if (p->stackpos == 0 || jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_OBJECT)
176
1.54k
      return "':' not as part of an object";
177
1.28k
    if (jv_get_kind(p->next) != JV_KIND_STRING)
178
112
      return "Object keys must be strings";
179
1.17k
    push(p, p->next);
180
1.17k
    p->next = jv_invalid();
181
1.17k
    break;
182
183
13.7k
  case ',':
184
13.7k
    if (!jv_is_valid(p->next))
185
320
      return "Expected value before ','";
186
13.4k
    if (p->stackpos == 0)
187
0
      return "',' not as part of an object or array";
188
13.4k
    if (jv_get_kind(p->stack[p->stackpos-1]) == JV_KIND_ARRAY) {
189
12.8k
      p->stack[p->stackpos-1] = jv_array_append(p->stack[p->stackpos-1], p->next);
190
12.8k
      p->next = jv_invalid();
191
12.8k
    } else if (jv_get_kind(p->stack[p->stackpos-1]) == JV_KIND_STRING) {
192
476
      assert(p->stackpos > 1 && jv_get_kind(p->stack[p->stackpos-2]) == JV_KIND_OBJECT);
193
476
      p->stack[p->stackpos-2] = jv_object_set(p->stack[p->stackpos-2],
194
476
                                              p->stack[p->stackpos-1], p->next);
195
476
      p->stackpos--;
196
476
      p->next = jv_invalid();
197
476
    } else {
198
      // this case hits on input like {"a", "b"}
199
70
      return "Objects must consist of key:value pairs";
200
70
    }
201
13.3k
    break;
202
203
13.3k
  case ']':
204
12.5k
    if (p->stackpos == 0 || jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_ARRAY)
205
5.87k
      return "Unmatched ']'";
206
6.71k
    if (jv_is_valid(p->next)) {
207
6.22k
      p->stack[p->stackpos-1] = jv_array_append(p->stack[p->stackpos-1], p->next);
208
6.22k
      p->next = jv_invalid();
209
6.22k
    } else {
210
488
      if (jv_array_length(jv_copy(p->stack[p->stackpos-1])) != 0) {
211
        // this case hits on input like [1,2,3,]
212
229
        return "Expected another array element";
213
229
      }
214
488
    }
215
6.48k
    jv_free(p->next);
216
6.48k
    p->next = p->stack[--p->stackpos];
217
6.48k
    break;
218
219
793
  case '}':
220
793
    if (p->stackpos == 0)
221
106
      return "Unmatched '}'";
222
687
    if (jv_is_valid(p->next)) {
223
349
      if (jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_STRING)
224
271
        return "Objects must consist of key:value pairs";
225
349
      assert(p->stackpos > 1 && jv_get_kind(p->stack[p->stackpos-2]) == JV_KIND_OBJECT);
226
78
      p->stack[p->stackpos-2] = jv_object_set(p->stack[p->stackpos-2],
227
78
                                              p->stack[p->stackpos-1], p->next);
228
78
      p->stackpos--;
229
78
      p->next = jv_invalid();
230
338
    } else {
231
338
      if (jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_OBJECT)
232
73
        return "Unmatched '}'";
233
265
      if (jv_object_length(jv_copy(p->stack[p->stackpos-1])) != 0)
234
0
        return "Expected another key-value pair";
235
265
    }
236
343
    jv_free(p->next);
237
343
    p->next = p->stack[--p->stackpos];
238
343
    break;
239
80.9k
  }
240
70.4k
  return 0;
241
80.9k
}
242
243
0
static pfunc stream_token(struct jv_parser* p, char ch) {
244
0
  jv_kind k;
245
0
  jv last;
246
247
0
  switch (ch) {
248
0
  case '[':
249
0
    if (jv_is_valid(p->next))
250
0
      return "Expected a separator between values";
251
0
    if (p->last_seen == JV_LAST_OPEN_OBJECT)
252
      // Looks like {["foo"]}
253
0
      return "Expected string key after '{', not '['";
254
0
    if (p->last_seen == JV_LAST_COMMA) {
255
0
      last = jv_array_get(jv_copy(p->path), p->stacklen - 1);
256
0
      k = jv_get_kind(last);
257
0
      jv_free(last);
258
0
      if (k != JV_KIND_NUMBER)
259
        // Looks like {"x":"y",["foo"]}
260
0
        return "Expected string key after ',' in object, not '['";
261
0
    }
262
0
    p->path = jv_array_append(p->path, jv_number(0)); // push
263
0
    p->last_seen = JV_LAST_OPEN_ARRAY;
264
0
    p->stacklen++;
265
0
    break;
266
267
0
  case '{':
268
0
    if (p->last_seen == JV_LAST_VALUE)
269
0
      return "Expected a separator between values";
270
0
    if (p->last_seen == JV_LAST_OPEN_OBJECT)
271
      // Looks like {{"foo":"bar"}}
272
0
      return "Expected string key after '{', not '{'";
273
0
    if (p->last_seen == JV_LAST_COMMA) {
274
0
      last = jv_array_get(jv_copy(p->path), p->stacklen - 1);
275
0
      k = jv_get_kind(last);
276
0
      jv_free(last);
277
0
      if (k != JV_KIND_NUMBER)
278
        // Looks like {"x":"y",{"foo":"bar"}}
279
0
        return "Expected string key after ',' in object, not '{'";
280
0
    }
281
    // Push object key: null, since we don't know it yet
282
0
    p->path = jv_array_append(p->path, jv_null()); // push
283
0
    p->last_seen = JV_LAST_OPEN_OBJECT;
284
0
    p->stacklen++;
285
0
    break;
286
287
0
  case ':':
288
0
    last = jv_invalid();
289
0
    if (p->stacklen == 0 || jv_get_kind(last = jv_array_get(jv_copy(p->path), p->stacklen - 1)) == JV_KIND_NUMBER) {
290
0
      jv_free(last);
291
0
      return "':' not as part of an object";
292
0
    }
293
0
    jv_free(last);
294
0
    if (!jv_is_valid(p->next) || p->last_seen == JV_LAST_NONE)
295
0
      return "Expected string key before ':'";
296
0
    if (jv_get_kind(p->next) != JV_KIND_STRING)
297
0
      return "Object keys must be strings";
298
0
    if (p->last_seen != JV_LAST_VALUE)
299
0
      return "':' should follow a key";
300
0
    p->last_seen = JV_LAST_COLON;
301
0
    p->path = jv_array_set(p->path, p->stacklen - 1, p->next);
302
0
    p->next = jv_invalid();
303
0
    break;
304
305
0
  case ',':
306
0
    if (p->last_seen != JV_LAST_VALUE)
307
0
      return "Expected value before ','";
308
0
    if (p->stacklen == 0)
309
0
      return "',' not as part of an object or array";
310
0
    last = jv_array_get(jv_copy(p->path), p->stacklen - 1);
311
0
    k = jv_get_kind(last);
312
0
    if (k == JV_KIND_NUMBER) {
313
0
      int idx = jv_number_value(last);
314
315
0
      if (jv_is_valid(p->next)) {
316
0
        p->output = JV_ARRAY(jv_copy(p->path), p->next);
317
0
        p->next = jv_invalid();
318
0
      }
319
0
      p->path = jv_array_set(p->path, p->stacklen - 1, jv_number(idx + 1));
320
0
      p->last_seen = JV_LAST_COMMA;
321
0
    } else if (k == JV_KIND_STRING) {
322
0
      if (jv_is_valid(p->next)) {
323
0
        p->output = JV_ARRAY(jv_copy(p->path), p->next);
324
0
        p->next = jv_invalid();
325
0
      }
326
0
      p->path = jv_array_set(p->path, p->stacklen - 1, jv_null()); // ready for another key:value pair
327
0
      p->last_seen = JV_LAST_COMMA;
328
0
    } else {
329
0
      assert(k == JV_KIND_NULL);
330
      // this case hits on input like {,}
331
      // make sure to handle input like {"a", "b"} and {"a":, ...}
332
0
      jv_free(last);
333
0
      return "Objects must consist of key:value pairs";
334
0
    }
335
0
    jv_free(last);
336
0
    break;
337
338
0
  case ']':
339
0
    if (p->stacklen == 0)
340
0
      return "Unmatched ']' at the top-level";
341
0
    if (p->last_seen == JV_LAST_COMMA)
342
0
      return "Expected another array element";
343
0
    if (p->last_seen == JV_LAST_OPEN_ARRAY)
344
0
      assert(!jv_is_valid(p->next));
345
346
0
    last = jv_array_get(jv_copy(p->path), p->stacklen - 1);
347
0
    k = jv_get_kind(last);
348
0
    jv_free(last);
349
350
0
    if (k != JV_KIND_NUMBER)
351
0
      return "Unmatched ']' in the middle of an object";
352
0
    if (jv_is_valid(p->next)) {
353
0
      p->output = JV_ARRAY(jv_copy(p->path), p->next, jv_true());
354
0
      p->next = jv_invalid();
355
0
    } else if (p->last_seen != JV_LAST_OPEN_ARRAY) {
356
0
      p->output = JV_ARRAY(jv_copy(p->path));
357
0
    }
358
359
0
    p->path = jv_array_slice(p->path, 0, --(p->stacklen)); // pop
360
    //assert(!jv_is_valid(p->next));
361
0
    jv_free(p->next);
362
0
    p->next = jv_invalid();
363
364
0
    if (p->last_seen == JV_LAST_OPEN_ARRAY)
365
0
      p->output = JV_ARRAY(jv_copy(p->path), jv_array()); // Empty arrays are leaves
366
367
0
    if (p->stacklen == 0)
368
0
      p->last_seen = JV_LAST_NONE;
369
0
    else
370
0
      p->last_seen = JV_LAST_VALUE;
371
0
    break;
372
373
0
  case '}':
374
0
    if (p->stacklen == 0)
375
0
      return "Unmatched '}' at the top-level";
376
0
    if (p->last_seen == JV_LAST_COMMA)
377
0
      return "Expected another key:value pair";
378
0
    if (p->last_seen == JV_LAST_OPEN_OBJECT)
379
0
      assert(!jv_is_valid(p->next));
380
381
0
    last = jv_array_get(jv_copy(p->path), p->stacklen - 1);
382
0
    k = jv_get_kind(last);
383
0
    jv_free(last);
384
0
    if (k == JV_KIND_NUMBER)
385
0
      return "Unmatched '}' in the middle of an array";
386
387
0
    if (jv_is_valid(p->next)) {
388
0
      if (k != JV_KIND_STRING)
389
0
        return "Objects must consist of key:value pairs";
390
0
      p->output = JV_ARRAY(jv_copy(p->path), p->next, jv_true());
391
0
      p->next = jv_invalid();
392
0
    } else {
393
      // Perhaps {"a":[]}
394
0
      if (p->last_seen == JV_LAST_COLON)
395
        // Looks like {"a":}
396
0
        return "Missing value in key:value pair";
397
0
      if (p->last_seen == JV_LAST_COMMA)
398
        // Looks like {"a":0,}
399
0
        return "Expected another key-value pair";
400
0
      if (p->last_seen == JV_LAST_OPEN_ARRAY)
401
0
        return "Unmatched '}' in the middle of an array";
402
0
      if (p->last_seen != JV_LAST_VALUE && p->last_seen != JV_LAST_OPEN_OBJECT)
403
0
        return "Unmatched '}'";
404
0
      if (p->last_seen != JV_LAST_OPEN_OBJECT)
405
0
        p->output = JV_ARRAY(jv_copy(p->path));
406
0
    }
407
0
    p->path = jv_array_slice(p->path, 0, --(p->stacklen)); // pop
408
0
    jv_free(p->next);
409
0
    p->next = jv_invalid();
410
411
0
    if (p->last_seen == JV_LAST_OPEN_OBJECT)
412
0
      p->output = JV_ARRAY(jv_copy(p->path), jv_object()); // Empty arrays are leaves
413
414
0
    if (p->stacklen == 0)
415
0
      p->last_seen = JV_LAST_NONE;
416
0
    else
417
0
      p->last_seen = JV_LAST_VALUE;
418
0
    break;
419
0
  }
420
0
  return 0;
421
0
}
422
423
28.6M
static pfunc tokenadd(struct jv_parser* p, char c) {
424
28.6M
  assert(p->tokenpos <= p->tokenlen);
425
28.6M
  if (p->tokenpos >= (p->tokenlen - 1)) {
426
7.50k
    if (p->tokenlen > INT_MAX / 2)
427
0
      return "Token too long";
428
7.50k
    p->tokenlen *= 2;
429
7.50k
    p->tokenbuf = jv_mem_realloc(p->tokenbuf, p->tokenlen);
430
7.50k
  }
431
28.6M
  assert(p->tokenpos < p->tokenlen);
432
28.6M
  p->tokenbuf[p->tokenpos++] = c;
433
28.6M
  return 0;
434
28.6M
}
435
436
4.89k
static int unhex4(char* hex) {
437
4.89k
  int r = 0;
438
23.1k
  for (int i=0; i<4; i++) {
439
19.0k
    char c = *hex++;
440
19.0k
    int n;
441
19.0k
    if ('0' <= c && c <= '9') n = c - '0';
442
10.5k
    else if ('a' <= c && c <= 'f') n = c - 'a' + 10;
443
5.62k
    else if ('A' <= c && c <= 'F') n = c - 'A' + 10;
444
742
    else return -1;
445
18.2k
    r <<= 4;
446
18.2k
    r |= n;
447
18.2k
  }
448
4.15k
  return r;
449
4.89k
}
450
451
9.12k
static pfunc found_string(struct jv_parser* p) {
452
9.12k
  char* in = p->tokenbuf;
453
9.12k
  char* out = p->tokenbuf;
454
9.12k
  char* end = p->tokenbuf + p->tokenpos;
455
456
18.1M
  while (in < end) {
457
18.1M
    char c = *in++;
458
18.1M
    if (c == '\\') {
459
52.2k
      if (in >= end)
460
0
        return "Expected escape character at end of string";
461
52.2k
      c = *in++;
462
52.2k
      switch (c) {
463
45.2k
      case '\\':
464
45.3k
      case '"':
465
45.6k
      case '/': *out++ = c;    break;
466
80
      case 'b': *out++ = '\b'; break;
467
216
      case 'f': *out++ = '\f'; break;
468
261
      case 't': *out++ = '\t'; break;
469
690
      case 'n': *out++ = '\n'; break;
470
235
      case 'r': *out++ = '\r'; break;
471
472
4.34k
      case 'u':
473
        /* ahh, the complicated case */
474
4.34k
        if (in + 4 > end)
475
619
          return "Invalid \\uXXXX escape";
476
3.72k
        int hexvalue = unhex4(in);
477
3.72k
        if (hexvalue < 0)
478
532
          return "Invalid characters in \\uXXXX escape";
479
3.19k
        unsigned long codepoint = (unsigned long)hexvalue;
480
3.19k
        in += 4;
481
3.19k
        if (0xD800 <= codepoint && codepoint <= 0xDBFF) {
482
          /* who thought UTF-16 surrogate pairs were a good idea? */
483
1.68k
          if (in + 6 > end || in[0] != '\\' || in[1] != 'u')
484
513
            return "Invalid \\uXXXX\\uXXXX surrogate pair escape";
485
1.16k
          unsigned long surrogate = unhex4(in+2);
486
1.16k
          if (!(0xDC00 <= surrogate && surrogate <= 0xDFFF))
487
467
            return "Invalid \\uXXXX\\uXXXX surrogate pair escape";
488
701
          in += 6;
489
701
          codepoint = 0x10000 + (((codepoint - 0xD800) << 10)
490
701
                                 |(surrogate - 0xDC00));
491
701
        }
492
2.21k
        if (codepoint > 0x10FFFF)
493
0
          codepoint = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER
494
2.21k
        out += jvp_utf8_encode(codepoint, out);
495
2.21k
        break;
496
497
718
      default:
498
718
        return "Invalid escape";
499
52.2k
      }
500
18.0M
    } else {
501
18.0M
      if (!(c & ~0x1F))
502
3
        return "Invalid string: control characters from U+0000 through U+001F must be escaped";
503
18.0M
      *out++ = c;
504
18.0M
    }
505
18.1M
  }
506
6.26k
  TRY(value(p, jv_string_sized(p->tokenbuf, out - p->tokenbuf)));
507
6.26k
  p->tokenpos = 0;
508
6.26k
  return 0;
509
6.26k
}
510
511
579k
static pfunc check_literal(struct jv_parser* p) {
512
579k
  if (p->tokenpos == 0) return 0;
513
514
508k
  const char* pattern = 0;
515
508k
  int plen;
516
508k
  jv v;
517
508k
  switch (p->tokenbuf[0]) {
518
249
  case 't': pattern = "true"; plen = 4; v = jv_true(); break;
519
245
  case 'f': pattern = "false"; plen = 5; v = jv_false(); break;
520
244
  case '\'':
521
244
    return "Invalid string literal; expected \", but got '";
522
5.45k
  case 'n':
523
    // if it starts with 'n', it could be a literal "nan"
524
5.45k
    if (p->tokenpos > 1 && p->tokenbuf[1] == 'u') {
525
201
      pattern = "null"; plen = 4; v = jv_null();
526
201
    }
527
508k
  }
528
507k
  if (pattern) {
529
695
    if (p->tokenpos != plen) return "Invalid literal";
530
892
    for (int i=0; i<plen; i++)
531
814
      if (p->tokenbuf[i] != pattern[i])
532
212
        return "Invalid literal";
533
78
    TRY(value(p, v));
534
507k
  } else {
535
    // FIXME: better parser
536
507k
    p->tokenbuf[p->tokenpos] = 0;
537
507k
#ifdef USE_DECNUM
538
507k
    jv number = jv_number_with_literal(p->tokenbuf);
539
507k
    if (jv_get_kind(number) == JV_KIND_INVALID) {
540
11.8k
      return "Invalid numeric literal";
541
11.8k
    }
542
495k
    TRY(value(p, number));
543
#else
544
    char *end = 0;
545
    double d = jvp_strtod(&p->dtoa, p->tokenbuf, &end);
546
    if (end == 0 || *end != 0) {
547
      return "Invalid numeric literal";
548
    }
549
    TRY(value(p, jv_number(d)));
550
#endif
551
495k
  }
552
492k
  p->tokenpos = 0;
553
492k
  return 0;
554
507k
}
555
556
typedef enum {
557
  LITERAL,
558
  WHITESPACE,
559
  STRUCTURE,
560
  QUOTE,
561
  INVALID
562
} chclass;
563
564
9.98M
static chclass classify(char c) {
565
9.98M
  switch (c) {
566
13.6k
  case ' ':
567
13.6k
  case '\t':
568
13.6k
  case '\r':
569
13.8k
  case '\n':
570
13.8k
    return WHITESPACE;
571
9.35k
  case '"':
572
9.35k
    return QUOTE;
573
35.6k
  case '[':
574
55.7k
  case ',':
575
68.9k
  case ']':
576
84.7k
  case '{':
577
88.6k
  case ':':
578
89.4k
  case '}':
579
89.4k
    return STRUCTURE;
580
9.86M
  default:
581
9.86M
    return LITERAL;
582
9.98M
  }
583
9.98M
}
584
585
586
static const presult OK = "output produced";
587
588
10.0M
static int parse_check_done(struct jv_parser* p, jv* out) {
589
10.0M
  if (p->stackpos == 0 && jv_is_valid(p->next)) {
590
13.4k
    *out = p->next;
591
13.4k
    p->next = jv_invalid();
592
13.4k
    return 1;
593
10.0M
  } else {
594
10.0M
    return 0;
595
10.0M
  }
596
10.0M
}
597
598
0
static int stream_check_done(struct jv_parser* p, jv* out) {
599
0
  if (p->stacklen == 0 && jv_is_valid(p->next)) {
600
0
    *out = JV_ARRAY(jv_copy(p->path),p->next);
601
0
    p->next = jv_invalid();
602
0
    return 1;
603
0
  } else if (jv_is_valid(p->output)) {
604
0
    if (jv_array_length(jv_copy(p->output)) > 2) {
605
      // At end of an array or object, necessitating one more output by
606
      // which to indicate this
607
0
      *out = jv_array_slice(jv_copy(p->output), 0, 2);
608
0
      p->output = jv_array_slice(p->output, 0, 1);      // arrange one more output
609
0
    } else {
610
      // No further processing needed
611
0
      *out = p->output;
612
0
      p->output = jv_invalid();
613
0
    }
614
0
    return 1;
615
0
  } else {
616
0
    return 0;
617
0
  }
618
0
}
619
620
0
static int seq_check_truncation(struct jv_parser* p) {
621
0
  return (!p->last_ch_was_ws && (p->stackpos > 0 || p->tokenpos > 0 || jv_get_kind(p->next) == JV_KIND_NUMBER));
622
0
}
623
624
0
static int stream_seq_check_truncation(struct jv_parser* p) {
625
0
  jv_kind k = jv_get_kind(p->next);
626
0
  return (p->stacklen > 0 || k == JV_KIND_NUMBER || k == JV_KIND_TRUE || k == JV_KIND_FALSE || k == JV_KIND_NULL);
627
0
}
628
629
0
static int parse_is_top_num(struct jv_parser* p) {
630
0
  return (p->stackpos == 0 && jv_get_kind(p->next) == JV_KIND_NUMBER);
631
0
}
632
633
0
static int stream_is_top_num(struct jv_parser* p) {
634
0
  return (p->stacklen == 0 && jv_get_kind(p->next) == JV_KIND_NUMBER);
635
0
}
636
637
#define check_done(p, o) \
638
10.0M
   (((p)->flags & JV_PARSE_STREAMING) ? stream_check_done((p), (o)) : parse_check_done((p), (o)))
639
640
#define token(p, ch) \
641
   (((p)->flags & JV_PARSE_STREAMING) ? stream_token((p), (ch)) : parse_token((p), (ch)))
642
643
#define check_truncation(p) \
644
0
   (((p)->flags & JV_PARSE_STREAMING) ? stream_seq_check_truncation((p)) : seq_check_truncation((p)))
645
646
#define is_top_num(p) \
647
0
   (((p)->flags & JV_PARSE_STREAMING) ? stream_is_top_num((p)) : parse_is_top_num((p)))
648
649
28.7M
static pfunc scan(struct jv_parser* p, char ch, jv* out) {
650
28.7M
  p->column++;
651
28.7M
  if (ch == '\n') {
652
207
    p->line++;
653
207
    p->column = 0;
654
207
  }
655
28.7M
  if ((p->flags & JV_PARSE_SEQ)
656
0
      && ch == '\036' /* ASCII RS; see draft-ietf-json-sequence-07 */) {
657
0
    if (check_truncation(p)) {
658
0
      if (check_literal(p) == 0 && is_top_num(p))
659
0
        return "Potentially truncated top-level numeric value";
660
0
      return "Truncated value";
661
0
    }
662
0
    TRY(check_literal(p));
663
0
    if (p->st == JV_PARSER_NORMAL && check_done(p, out))
664
0
      return OK;
665
    // shouldn't happen?
666
0
    assert(!jv_is_valid(*out));
667
0
    parser_reset(p);
668
0
    jv_free(*out);
669
0
    *out = jv_invalid();
670
0
    return OK;
671
0
  }
672
28.7M
  presult answer = 0;
673
28.7M
  p->last_ch_was_ws = 0;
674
28.7M
  if (p->st == JV_PARSER_NORMAL) {
675
9.98M
    chclass cls = classify(ch);
676
9.98M
    if (cls == WHITESPACE)
677
13.8k
      p->last_ch_was_ws = 1;
678
9.98M
    if (cls != LITERAL) {
679
112k
      TRY(check_literal(p));
680
97.9k
      if (check_done(p, out)) answer = OK;
681
97.9k
    }
682
9.96M
    switch (cls) {
683
9.86M
    case LITERAL:
684
9.86M
      TRY(tokenadd(p, ch));
685
9.86M
      break;
686
9.86M
    case WHITESPACE:
687
7.62k
      break;
688
9.35k
    case QUOTE:
689
9.35k
      p->st = JV_PARSER_STRING;
690
9.35k
      break;
691
80.9k
    case STRUCTURE:
692
80.9k
      TRY(token(p, ch));
693
70.4k
      break;
694
70.4k
    case INVALID:
695
0
      return "Invalid character";
696
9.96M
    }
697
9.95M
    if (check_done(p, out)) answer = OK;
698
18.8M
  } else {
699
18.8M
    if (ch == '"' && p->st == JV_PARSER_STRING) {
700
9.12k
      TRY(found_string(p));
701
6.26k
      p->st = JV_PARSER_NORMAL;
702
6.26k
      if (check_done(p, out)) answer = OK;
703
18.8M
    } else {
704
18.8M
      TRY(tokenadd(p, ch));
705
18.8M
      if (ch == '\\' && p->st == JV_PARSER_STRING) {
706
56.9k
        p->st = JV_PARSER_STRING_ESCAPE;
707
18.7M
      } else {
708
18.7M
        p->st = JV_PARSER_STRING;
709
18.7M
      }
710
18.8M
    }
711
18.8M
  }
712
28.7M
  return answer;
713
28.7M
}
714
715
0
struct jv_parser* jv_parser_new(int flags) {
716
0
  struct jv_parser* p = jv_mem_alloc(sizeof(struct jv_parser));
717
0
  parser_init(p, flags);
718
0
  p->flags = flags;
719
0
  return p;
720
0
}
721
722
0
void jv_parser_free(struct jv_parser* p) {
723
0
  parser_free(p);
724
0
  jv_mem_free(p);
725
0
}
726
727
static const unsigned char UTF8_BOM[] = {0xEF,0xBB,0xBF};
728
729
0
int jv_parser_remaining(struct jv_parser* p) {
730
0
  if (p->curr_buf == 0)
731
0
    return 0;
732
0
  return (p->curr_buf_length - p->curr_buf_pos);
733
0
}
734
735
496k
void jv_parser_set_buf(struct jv_parser* p, const char* buf, int length, int is_partial) {
736
496k
  assert((p->curr_buf == 0 || p->curr_buf_pos == p->curr_buf_length)
737
496k
         && "previous buffer not exhausted");
738
994k
  while (length > 0 && p->bom_strip_position < sizeof(UTF8_BOM)) {
739
497k
    if ((unsigned char)*buf == UTF8_BOM[p->bom_strip_position]) {
740
      // matched a BOM character
741
1.25k
      buf++;
742
1.25k
      length--;
743
1.25k
      p->bom_strip_position++;
744
496k
    } else {
745
496k
      if (p->bom_strip_position == 0) {
746
        // no BOM in this document
747
495k
        p->bom_strip_position = sizeof(UTF8_BOM);
748
495k
      } else {
749
        // malformed BOM (prefix present, rest missing)
750
1.25k
        p->bom_strip_position = 0xff;
751
1.25k
      }
752
496k
    }
753
497k
  }
754
496k
  p->curr_buf = buf;
755
496k
  p->curr_buf_length = length;
756
496k
  p->curr_buf_pos = 0;
757
496k
  p->curr_buf_is_partial = is_partial;
758
496k
}
759
760
static jv make_error(struct jv_parser*, const char *, ...) JV_PRINTF_LIKE(2, 3);
761
762
28.7k
static jv make_error(struct jv_parser* p, const char *fmt, ...) {
763
28.7k
  va_list ap;
764
28.7k
  va_start(ap, fmt);
765
28.7k
  jv e = jv_string_vfmt(fmt, ap);
766
28.7k
  va_end(ap);
767
28.7k
  if ((p->flags & JV_PARSE_STREAM_ERRORS))
768
0
    return JV_ARRAY(e, jv_copy(p->path));
769
28.7k
  return jv_invalid_with_msg(e);
770
28.7k
}
771
772
970k
jv jv_parser_next(struct jv_parser* p) {
773
970k
  if (p->eof)
774
460k
    return jv_invalid();
775
509k
  if (!p->curr_buf)
776
0
    return jv_invalid(); // Need a buffer
777
509k
  if (p->bom_strip_position == 0xff) {
778
1.25k
    if (!(p->flags & JV_PARSE_SEQ))
779
1.25k
      return jv_invalid_with_msg(jv_string("Malformed BOM"));
780
0
    p->st =JV_PARSER_WAITING_FOR_RS;
781
0
    parser_reset(p);
782
0
  }
783
508k
  jv value = jv_invalid();
784
508k
  if ((p->flags & JV_PARSE_STREAMING) && stream_check_done(p, &value))
785
0
    return value;
786
508k
  char ch;
787
508k
  presult msg = 0;
788
29.3M
  while (!msg && p->curr_buf_pos < p->curr_buf_length) {
789
28.7M
    ch = p->curr_buf[p->curr_buf_pos++];
790
28.7M
    if (p->st == JV_PARSER_WAITING_FOR_RS) {
791
0
      if (ch == '\n') {
792
0
        p->line++;
793
0
        p->column = 0;
794
0
      } else {
795
0
        p->column++;
796
0
      }
797
0
      if (ch == '\036')
798
0
        p->st = JV_PARSER_NORMAL;
799
0
      continue; // need to resync, wait for RS
800
0
    }
801
28.7M
    msg = scan(p, ch, &value);
802
28.7M
  }
803
508k
  if (msg == OK) {
804
13.3k
    return value;
805
495k
  } else if (msg) {
806
28.1k
    jv_free(value);
807
28.1k
    if (ch != '\036' && (p->flags & JV_PARSE_SEQ)) {
808
      // Skip to the next RS
809
0
      p->st = JV_PARSER_WAITING_FOR_RS;
810
0
      value = make_error(p, "%s at line %d, column %d (need RS to resync)", msg, p->line, p->column);
811
0
      parser_reset(p);
812
0
      return value;
813
0
    }
814
28.1k
    value = make_error(p, "%s at line %d, column %d", msg, p->line, p->column);
815
28.1k
    parser_reset(p);
816
28.1k
    if (!(p->flags & JV_PARSE_SEQ)) {
817
      // We're not parsing a JSON text sequence; throw this buffer away.
818
      // XXX We should fail permanently here.
819
28.1k
      p->curr_buf = 0;
820
28.1k
      p->curr_buf_pos = 0;
821
28.1k
    } // Else ch must be RS; don't clear buf so we can start parsing again after this ch
822
28.1k
    return value;
823
467k
  } else if (p->curr_buf_is_partial) {
824
0
    assert(p->curr_buf_pos == p->curr_buf_length);
825
    // need another buffer
826
0
    return jv_invalid();
827
467k
  } else {
828
    // at EOF
829
467k
    p->eof = 1;
830
467k
    assert(p->curr_buf_pos == p->curr_buf_length);
831
467k
    jv_free(value);
832
467k
    if (p->st == JV_PARSER_WAITING_FOR_RS)
833
0
      return make_error(p, "Unfinished abandoned text at EOF at line %d, column %d", p->line, p->column);
834
467k
    if (p->st != JV_PARSER_NORMAL) {
835
236
      value = make_error(p, "Unfinished string at EOF at line %d, column %d", p->line, p->column);
836
236
      parser_reset(p);
837
236
      p->st = JV_PARSER_WAITING_FOR_RS;
838
236
      return value;
839
236
    }
840
466k
    if ((msg = check_literal(p))) {
841
275
      value = make_error(p, "%s at EOF at line %d, column %d", msg, p->line, p->column);
842
275
      parser_reset(p);
843
275
      p->st = JV_PARSER_WAITING_FOR_RS;
844
275
      return value;
845
275
    }
846
466k
    if (((p->flags & JV_PARSE_STREAMING) && p->stacklen != 0) ||
847
466k
        (!(p->flags & JV_PARSE_STREAMING) && p->stackpos != 0)) {
848
157
      value = make_error(p, "Unfinished JSON term at EOF at line %d, column %d", p->line, p->column);
849
157
      parser_reset(p);
850
157
      p->st = JV_PARSER_WAITING_FOR_RS;
851
157
      return value;
852
157
    }
853
    // p->next is either invalid (nothing here, but no syntax error)
854
    // or valid (this is the value). either way it's the thing to return
855
466k
    if ((p->flags & JV_PARSE_STREAMING) && jv_is_valid(p->next)) {
856
0
      value = JV_ARRAY(jv_copy(p->path), p->next); // except in streaming mode we've got to make it [path,value]
857
466k
    } else {
858
466k
      value = p->next;
859
466k
    }
860
466k
    p->next = jv_invalid();
861
466k
    if ((p->flags & JV_PARSE_SEQ) && !p->last_ch_was_ws && jv_get_kind(value) == JV_KIND_NUMBER) {
862
0
      jv_free(value);
863
0
      return make_error(p, "Potentially truncated top-level numeric value at EOF at line %d, column %d", p->line, p->column);
864
0
    }
865
466k
    return value;
866
466k
  }
867
508k
}
868
869
496k
jv jv_parse_sized_custom_flags(const char* string, int length, int flags) {
870
496k
  struct jv_parser parser;
871
496k
  parser_init(&parser, flags);
872
496k
  jv_parser_set_buf(&parser, string, length, 0);
873
496k
  jv value = jv_parser_next(&parser);
874
496k
  if (jv_is_valid(value)) {
875
474k
    jv next = jv_parser_next(&parser);
876
474k
    if (jv_is_valid(next)) {
877
      // multiple JSON values, we only wanted one
878
225
      jv_free(value);
879
225
      jv_free(next);
880
225
      value = jv_invalid_with_msg(jv_string("Unexpected extra JSON values"));
881
473k
    } else if (jv_invalid_has_msg(jv_copy(next))) {
882
      // parser error after the first JSON value
883
7.57k
      jv_free(value);
884
7.57k
      value = next;
885
466k
    } else {
886
      // a single valid JSON value
887
466k
      jv_free(next);
888
466k
    }
889
474k
  } else if (jv_invalid_has_msg(jv_copy(value))) {
890
    // parse error, we'll return it
891
22.4k
  } else {
892
    // no value at all
893
255
    jv_free(value);
894
255
    value = jv_invalid_with_msg(jv_string("Expected JSON value"));
895
255
  }
896
496k
  parser_free(&parser);
897
898
496k
  if (!jv_is_valid(value) && jv_invalid_has_msg(jv_copy(value))) {
899
30.5k
    jv msg = jv_invalid_get_msg(value);
900
30.5k
    value = jv_invalid_with_msg(jv_string_fmt("%s (while parsing '%.*s')",
901
30.5k
                                              jv_string_value(msg),
902
30.5k
                                              length,
903
30.5k
                                              string));
904
30.5k
    jv_free(msg);
905
30.5k
  }
906
496k
  return value;
907
496k
}
908
909
496k
jv jv_parse_sized(const char* string, int length) {
910
496k
  return jv_parse_sized_custom_flags(string, length, 0);
911
496k
}
912
913
7.30k
jv jv_parse(const char* string) {
914
7.30k
  return jv_parse_sized(string, strlen(string));
915
7.30k
}
916
917
0
jv jv_parse_custom_flags(const char* string, int flags) {
918
0
  return jv_parse_sized_custom_flags(string, strlen(string), flags);
919
0
}