Coverage Report

Created: 2026-09-14 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jansson/src/pack_unpack.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
3
 * Copyright (c) 2011-2012 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
4
 *
5
 * Jansson is free software; you can redistribute it and/or modify
6
 * it under the terms of the MIT license. See LICENSE for details.
7
 */
8
9
#include "jansson.h"
10
#include "jansson_private.h"
11
#include "utf.h"
12
#include <string.h>
13
14
typedef struct {
15
    int line;
16
    int column;
17
    size_t pos;
18
    char token;
19
} token_t;
20
21
typedef struct {
22
    const char *start;
23
    const char *fmt;
24
    token_t prev_token;
25
    token_t token;
26
    token_t next_token;
27
    json_error_t *error;
28
    size_t flags;
29
    int line;
30
    int column;
31
    size_t pos;
32
    int has_error;
33
} scanner_t;
34
35
100k
#define token(scanner) ((scanner)->token.token)
36
37
static const char *const type_names[] = {"object", "array", "string", "integer",
38
                                         "real",   "true",  "false",  "null"};
39
40
0
#define type_name(x) type_names[json_typeof(x)]
41
42
static const char unpack_value_starters[] = "{[siIbfFOon";
43
44
static void scanner_init(scanner_t *s, json_error_t *error, size_t flags,
45
4.82k
                         const char *fmt) {
46
4.82k
    s->error = error;
47
4.82k
    s->flags = flags;
48
4.82k
    s->fmt = s->start = fmt;
49
4.82k
    memset(&s->prev_token, 0, sizeof(token_t));
50
4.82k
    memset(&s->token, 0, sizeof(token_t));
51
4.82k
    memset(&s->next_token, 0, sizeof(token_t));
52
4.82k
    s->line = 1;
53
4.82k
    s->column = 0;
54
4.82k
    s->pos = 0;
55
4.82k
    s->has_error = 0;
56
4.82k
}
57
58
22.4k
static void next_token(scanner_t *s) {
59
22.4k
    const char *t;
60
22.4k
    s->prev_token = s->token;
61
62
22.4k
    if (s->next_token.line) {
63
0
        s->token = s->next_token;
64
0
        s->next_token.line = 0;
65
0
        return;
66
0
    }
67
68
22.4k
    if (!token(s) && !*s->fmt)
69
0
        return;
70
71
22.4k
    t = s->fmt;
72
22.4k
    s->column++;
73
22.4k
    s->pos++;
74
75
    /* skip space and ignored chars */
76
22.4k
    while (*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') {
77
0
        if (*t == '\n') {
78
0
            s->line++;
79
0
            s->column = 1;
80
0
        } else
81
0
            s->column++;
82
83
0
        s->pos++;
84
0
        t++;
85
0
    }
86
87
22.4k
    s->token.token = *t;
88
22.4k
    s->token.line = s->line;
89
22.4k
    s->token.column = s->column;
90
22.4k
    s->token.pos = s->pos;
91
92
22.4k
    if (*t)
93
18.4k
        t++;
94
22.4k
    s->fmt = t;
95
22.4k
}
96
97
0
static void prev_token(scanner_t *s) {
98
0
    s->next_token = s->token;
99
0
    s->token = s->prev_token;
100
0
}
101
102
static void set_error(scanner_t *s, const char *source, enum json_error_code code,
103
829
                      const char *fmt, ...) {
104
829
    va_list ap;
105
829
    va_start(ap, fmt);
106
107
829
    jsonp_error_vset(s->error, s->token.line, s->token.column, s->token.pos, code, fmt,
108
829
                     ap);
109
110
829
    jsonp_error_set_source(s->error, source);
111
112
829
    va_end(ap);
113
829
}
114
115
static json_t *pack(scanner_t *s, va_list *ap);
116
117
/* ours will be set to 1 if jsonp_free() must be called for the result
118
   afterwards */
119
static char *read_string(scanner_t *s, va_list *ap, const char *purpose, size_t *out_len,
120
0
                         int *ours, int optional) {
121
0
    char t;
122
0
    strbuffer_t strbuff;
123
0
    const char *str;
124
0
    size_t length;
125
126
0
    next_token(s);
127
0
    t = token(s);
128
0
    prev_token(s);
129
130
0
    *ours = 0;
131
0
    if (t != '#' && t != '%' && t != '+') {
132
        /* Optimize the simple case */
133
0
        str = va_arg(*ap, const char *);
134
135
0
        if (!str) {
136
0
            if (!optional) {
137
0
                set_error(s, "<args>", json_error_null_value, "NULL %s", purpose);
138
0
                s->has_error = 1;
139
0
            }
140
0
            return NULL;
141
0
        }
142
143
0
        length = strlen(str);
144
145
0
        if (!utf8_check_string(str, length)) {
146
0
            set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
147
0
            s->has_error = 1;
148
0
            return NULL;
149
0
        }
150
151
0
        *out_len = length;
152
0
        return (char *)str;
153
0
    } else if (optional) {
154
0
        set_error(s, "<format>", json_error_invalid_format,
155
0
                  "Cannot use '%c' on optional strings", t);
156
0
        s->has_error = 1;
157
158
0
        return NULL;
159
0
    }
160
161
0
    if (strbuffer_init(&strbuff)) {
162
0
        set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
163
0
        s->has_error = 1;
164
0
    }
165
166
0
    while (1) {
167
0
        str = va_arg(*ap, const char *);
168
0
        if (!str) {
169
0
            set_error(s, "<args>", json_error_null_value, "NULL %s", purpose);
170
0
            s->has_error = 1;
171
0
        }
172
173
0
        next_token(s);
174
175
0
        if (token(s) == '#') {
176
0
            int len = va_arg(*ap, int);
177
0
            if (len < 0) {
178
0
                set_error(s, "<args>", json_error_invalid_argument,
179
0
                          "Invalid length for %s: %d", purpose, len);
180
0
                s->has_error = 1;
181
0
                length = 0;
182
0
            } else {
183
0
                length = (size_t)len;
184
0
            }
185
0
        } else if (token(s) == '%') {
186
0
            length = va_arg(*ap, size_t);
187
0
        } else {
188
0
            prev_token(s);
189
0
            length = s->has_error ? 0 : strlen(str);
190
0
        }
191
192
0
        if (!s->has_error && strbuffer_append_bytes(&strbuff, str, length) == -1) {
193
0
            set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
194
0
            s->has_error = 1;
195
0
        }
196
197
0
        next_token(s);
198
0
        if (token(s) != '+') {
199
0
            prev_token(s);
200
0
            break;
201
0
        }
202
0
    }
203
204
0
    if (s->has_error) {
205
0
        strbuffer_close(&strbuff);
206
0
        return NULL;
207
0
    }
208
209
0
    if (!utf8_check_string(strbuff.value, strbuff.length)) {
210
0
        set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
211
0
        strbuffer_close(&strbuff);
212
0
        s->has_error = 1;
213
0
        return NULL;
214
0
    }
215
216
0
    *out_len = strbuff.length;
217
0
    *ours = 1;
218
0
    return strbuffer_steal_value(&strbuff);
219
0
}
220
221
0
static json_t *pack_object(scanner_t *s, va_list *ap) {
222
0
    json_t *object = json_object();
223
0
    next_token(s);
224
225
0
    while (token(s) != '}') {
226
0
        char *key;
227
0
        size_t len;
228
0
        int ours;
229
0
        json_t *value;
230
0
        char valueOptional;
231
232
0
        if (!token(s)) {
233
0
            set_error(s, "<format>", json_error_invalid_format,
234
0
                      "Unexpected end of format string");
235
0
            goto error;
236
0
        }
237
238
0
        if (token(s) != 's') {
239
0
            set_error(s, "<format>", json_error_invalid_format,
240
0
                      "Expected format 's', got '%c'", token(s));
241
0
            goto error;
242
0
        }
243
244
0
        key = read_string(s, ap, "object key", &len, &ours, 0);
245
246
0
        next_token(s);
247
248
0
        next_token(s);
249
0
        valueOptional = token(s);
250
0
        prev_token(s);
251
252
0
        value = pack(s, ap);
253
0
        if (!value) {
254
0
            if (ours)
255
0
                jsonp_free(key);
256
257
0
            if (valueOptional != '*') {
258
0
                set_error(s, "<args>", json_error_null_value, "NULL object value");
259
0
                s->has_error = 1;
260
0
            }
261
262
0
            next_token(s);
263
0
            continue;
264
0
        }
265
266
0
        if (s->has_error)
267
0
            json_decref(value);
268
269
0
        if (!s->has_error && json_object_setn_new_nocheck(object, key, len, value)) {
270
0
            set_error(s, "<internal>", json_error_out_of_memory,
271
0
                      "Unable to add key \"%s\"", key);
272
0
            s->has_error = 1;
273
0
        }
274
275
0
        if (ours)
276
0
            jsonp_free(key);
277
278
0
        next_token(s);
279
0
    }
280
281
0
    if (!s->has_error)
282
0
        return object;
283
284
0
error:
285
0
    json_decref(object);
286
0
    return NULL;
287
0
}
288
289
0
static json_t *pack_array(scanner_t *s, va_list *ap) {
290
0
    json_t *array = json_array();
291
0
    next_token(s);
292
293
0
    while (token(s) != ']') {
294
0
        json_t *value;
295
0
        char valueOptional;
296
297
0
        if (!token(s)) {
298
0
            set_error(s, "<format>", json_error_invalid_format,
299
0
                      "Unexpected end of format string");
300
            /* Format string errors are unrecoverable. */
301
0
            goto error;
302
0
        }
303
304
0
        next_token(s);
305
0
        valueOptional = token(s);
306
0
        prev_token(s);
307
308
0
        value = pack(s, ap);
309
0
        if (!value) {
310
0
            if (valueOptional != '*') {
311
0
                s->has_error = 1;
312
0
            }
313
314
0
            next_token(s);
315
0
            continue;
316
0
        }
317
318
0
        if (s->has_error)
319
0
            json_decref(value);
320
321
0
        if (!s->has_error && json_array_append_new(array, value)) {
322
0
            set_error(s, "<internal>", json_error_out_of_memory,
323
0
                      "Unable to append to array");
324
0
            s->has_error = 1;
325
0
        }
326
327
0
        next_token(s);
328
0
    }
329
330
0
    if (!s->has_error)
331
0
        return array;
332
333
0
error:
334
0
    json_decref(array);
335
0
    return NULL;
336
0
}
337
338
0
static json_t *pack_string(scanner_t *s, va_list *ap) {
339
0
    char *str;
340
0
    char t;
341
0
    size_t len;
342
0
    int ours;
343
0
    int optional;
344
345
0
    next_token(s);
346
0
    t = token(s);
347
0
    optional = t == '?' || t == '*';
348
0
    if (!optional)
349
0
        prev_token(s);
350
351
0
    str = read_string(s, ap, "string", &len, &ours, optional);
352
353
0
    if (!str)
354
0
        return t == '?' && !s->has_error ? json_null() : NULL;
355
356
0
    if (s->has_error) {
357
        /* It's impossible to reach this point if ours != 0, do not free str. */
358
0
        return NULL;
359
0
    }
360
361
0
    if (ours)
362
0
        return jsonp_stringn_nocheck_own(str, len);
363
364
0
    return json_stringn_nocheck(str, len);
365
0
}
366
367
0
static json_t *pack_object_inter(scanner_t *s, va_list *ap, int need_incref) {
368
0
    json_t *json;
369
0
    char ntoken;
370
371
0
    next_token(s);
372
0
    ntoken = token(s);
373
374
0
    if (ntoken != '?' && ntoken != '*')
375
0
        prev_token(s);
376
377
0
    json = va_arg(*ap, json_t *);
378
379
0
    if (json)
380
0
        return need_incref ? json_incref(json) : json;
381
382
0
    switch (ntoken) {
383
0
        case '?':
384
0
            return json_null();
385
0
        case '*':
386
0
            return NULL;
387
0
        default:
388
0
            break;
389
0
    }
390
391
0
    set_error(s, "<args>", json_error_null_value, "NULL object");
392
0
    s->has_error = 1;
393
0
    return NULL;
394
0
}
395
396
0
static json_t *pack_integer(scanner_t *s, json_int_t value) {
397
0
    json_t *json = json_integer(value);
398
399
0
    if (!json) {
400
0
        set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
401
0
        s->has_error = 1;
402
0
    }
403
404
0
    return json;
405
0
}
406
407
0
static json_t *pack_real(scanner_t *s, double value) {
408
    /* Allocate without setting value so we can identify OOM error. */
409
0
    json_t *json = json_real(0.0);
410
411
0
    if (!json) {
412
0
        set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
413
0
        s->has_error = 1;
414
415
0
        return NULL;
416
0
    }
417
418
0
    if (json_real_set(json, value)) {
419
0
        json_decref(json);
420
421
0
        set_error(s, "<args>", json_error_numeric_overflow,
422
0
                  "Invalid floating point value");
423
0
        s->has_error = 1;
424
425
0
        return NULL;
426
0
    }
427
428
0
    return json;
429
0
}
430
431
0
static json_t *pack(scanner_t *s, va_list *ap) {
432
0
    switch (token(s)) {
433
0
        case '{':
434
0
            return pack_object(s, ap);
435
436
0
        case '[':
437
0
            return pack_array(s, ap);
438
439
0
        case 's': /* string */
440
0
            return pack_string(s, ap);
441
442
0
        case 'n': /* null */
443
0
            return json_null();
444
445
0
        case 'b': /* boolean */
446
0
            return va_arg(*ap, int) ? json_true() : json_false();
447
448
0
        case 'i': /* integer from int */
449
0
            return pack_integer(s, va_arg(*ap, int));
450
451
0
        case 'I': /* integer from json_int_t */
452
0
            return pack_integer(s, va_arg(*ap, json_int_t));
453
454
0
        case 'f': /* real */
455
0
            return pack_real(s, va_arg(*ap, double));
456
457
0
        case 'O': /* a json_t object; increments refcount */
458
0
            return pack_object_inter(s, ap, 1);
459
460
0
        case 'o': /* a json_t object; doesn't increment refcount */
461
0
            return pack_object_inter(s, ap, 0);
462
463
0
        default:
464
0
            set_error(s, "<format>", json_error_invalid_format,
465
0
                      "Unexpected format character '%c'", token(s));
466
0
            s->has_error = 1;
467
0
            return NULL;
468
0
    }
469
0
}
470
471
static int unpack(scanner_t *s, json_t *root, va_list *ap, const char *key);
472
473
static int unpack_object(scanner_t *s, json_t *root, va_list *ap,
474
441
                         const char *parent_key) {
475
441
    int ret = -1;
476
441
    int strict = 0;
477
441
    int gotopt = 0;
478
479
    /* Use a set (emulated by a hashtable) to check that all object
480
       keys are accessed. Checking that the correct number of keys
481
       were accessed is not enough, as the same key can be unpacked
482
       multiple times.
483
    */
484
441
    hashtable_t key_set;
485
486
441
    if (hashtable_init(&key_set)) {
487
0
        set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
488
0
        return -1;
489
0
    }
490
491
441
    if (root && !json_is_object(root)) {
492
0
        set_error(s, "<validation>", json_error_wrong_type, "Expected object, got %s%s%s",
493
0
                  type_name(root), parent_key ? " for key " : "",
494
0
                  parent_key ? parent_key : "");
495
0
        goto out;
496
0
    }
497
441
    next_token(s);
498
499
882
    while (token(s) != '}') {
500
441
        const char *key;
501
441
        size_t key_len;
502
441
        json_t *value;
503
441
        int opt = 0;
504
505
441
        if (strict != 0) {
506
0
            set_error(s, "<format>", json_error_invalid_format,
507
0
                      "Expected '}' after '%c', got '%c'", (strict == 1 ? '!' : '*'),
508
0
                      token(s));
509
0
            goto out;
510
0
        }
511
512
441
        if (!token(s)) {
513
0
            set_error(s, "<format>", json_error_invalid_format,
514
0
                      "Unexpected end of format string");
515
0
            goto out;
516
0
        }
517
518
441
        if (token(s) == '!' || token(s) == '*') {
519
0
            strict = (token(s) == '!' ? 1 : -1);
520
0
            next_token(s);
521
0
            continue;
522
0
        }
523
524
441
        if (token(s) != 's') {
525
0
            set_error(s, "<format>", json_error_invalid_format,
526
0
                      "Expected format 's', got '%c'", token(s));
527
0
            goto out;
528
0
        }
529
530
441
        key = va_arg(*ap, const char *);
531
441
        if (!key) {
532
0
            set_error(s, "<args>", json_error_null_value, "NULL object key");
533
0
            goto out;
534
0
        }
535
441
        key_len = strlen(key);
536
537
441
        next_token(s);
538
539
441
        if (token(s) == '?') {
540
441
            opt = gotopt = 1;
541
441
            next_token(s);
542
441
        }
543
544
441
        if (!root) {
545
            /* skipping */
546
0
            value = NULL;
547
441
        } else {
548
441
            value = json_object_getn(root, key, key_len);
549
441
            if (!value && !opt) {
550
0
                set_error(s, "<validation>", json_error_item_not_found,
551
0
                          "Object item not found: %s", key);
552
0
                goto out;
553
0
            }
554
441
        }
555
556
441
        if (unpack(s, value, ap, key))
557
0
            goto out;
558
559
441
        hashtable_set(&key_set, key, key_len, json_null());
560
441
        next_token(s);
561
441
    }
562
563
441
    if (strict == 0 && (s->flags & JSON_STRICT))
564
0
        strict = 1;
565
566
441
    if (root && strict == 1) {
567
        /* We need to check that all non optional items have been parsed */
568
0
        const char *key;
569
0
        size_t key_len;
570
        /* keys_res is 1 for uninitialized, 0 for success, -1 for error. */
571
0
        int keys_res = 1;
572
0
        strbuffer_t unrecognized_keys;
573
0
        json_t *value;
574
0
        long unpacked = 0;
575
576
0
        if (gotopt || json_object_size(root) != key_set.size) {
577
0
            json_object_keylen_foreach(root, key, key_len, value) {
578
0
                if (!hashtable_get(&key_set, key, key_len)) {
579
0
                    unpacked++;
580
581
                    /* Save unrecognized keys for the error message */
582
0
                    if (keys_res == 1) {
583
0
                        keys_res = strbuffer_init(&unrecognized_keys);
584
0
                    } else if (!keys_res) {
585
0
                        keys_res = strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
586
0
                    }
587
588
0
                    if (!keys_res)
589
0
                        keys_res =
590
0
                            strbuffer_append_bytes(&unrecognized_keys, key, key_len);
591
0
                }
592
0
            }
593
0
        }
594
0
        if (unpacked) {
595
0
            set_error(s, "<validation>", json_error_end_of_input_expected,
596
0
                      "%li object item(s) left unpacked: %s", unpacked,
597
0
                      keys_res ? "<unknown>" : strbuffer_value(&unrecognized_keys));
598
0
            strbuffer_close(&unrecognized_keys);
599
0
            goto out;
600
0
        }
601
0
    }
602
603
441
    ret = 0;
604
605
441
out:
606
441
    hashtable_close(&key_set);
607
441
    return ret;
608
441
}
609
610
3.94k
static int unpack_array(scanner_t *s, json_t *root, va_list *ap, const char *parent_key) {
611
3.94k
    size_t i = 0;
612
3.94k
    int strict = 0;
613
614
3.94k
    if (root && !json_is_array(root)) {
615
0
        set_error(s, "<validation>", json_error_wrong_type, "Expected array, got %s%s%s",
616
0
                  type_name(root), parent_key ? " for key " : "",
617
0
                  parent_key ? parent_key : "");
618
0
        return -1;
619
0
    }
620
3.94k
    next_token(s);
621
622
11.8k
    while (token(s) != ']') {
623
7.88k
        json_t *value;
624
625
7.88k
        if (strict != 0) {
626
0
            set_error(s, "<format>", json_error_invalid_format,
627
0
                      "Expected ']' after '%c', got '%c'", (strict == 1 ? '!' : '*'),
628
0
                      token(s));
629
0
            return -1;
630
0
        }
631
632
7.88k
        if (!token(s)) {
633
0
            set_error(s, "<format>", json_error_invalid_format,
634
0
                      "Unexpected end of format string");
635
0
            return -1;
636
0
        }
637
638
7.88k
        if (token(s) == '!' || token(s) == '*') {
639
3.94k
            strict = (token(s) == '!' ? 1 : -1);
640
3.94k
            next_token(s);
641
3.94k
            continue;
642
3.94k
        }
643
644
3.94k
        if (!strchr(unpack_value_starters, token(s))) {
645
0
            set_error(s, "<format>", json_error_invalid_format,
646
0
                      "Unexpected format character '%c'", token(s));
647
0
            return -1;
648
0
        }
649
650
3.94k
        if (!root) {
651
            /* skipping */
652
0
            value = NULL;
653
3.94k
        } else {
654
3.94k
            value = json_array_get(root, i);
655
3.94k
            if (!value) {
656
0
                set_error(s, "<validation>", json_error_index_out_of_range,
657
0
                          "Array index %lu out of range", (unsigned long)i);
658
0
                return -1;
659
0
            }
660
3.94k
        }
661
662
3.94k
        if (unpack(s, value, ap, NULL))
663
0
            return -1;
664
665
3.94k
        next_token(s);
666
3.94k
        i++;
667
3.94k
    }
668
669
3.94k
    if (strict == 0 && (s->flags & JSON_STRICT))
670
0
        strict = 1;
671
672
3.94k
    if (root && strict == 1 && i != json_array_size(root)) {
673
829
        long diff = (long)json_array_size(root) - (long)i;
674
829
        set_error(s, "<validation>", json_error_end_of_input_expected,
675
829
                  "%li array item(s) left unpacked", diff);
676
829
        return -1;
677
829
    }
678
679
3.11k
    return 0;
680
3.94k
}
681
682
9.20k
static int unpack(scanner_t *s, json_t *root, va_list *ap, const char *key) {
683
9.20k
    switch (token(s)) {
684
441
        case '{':
685
441
            return unpack_object(s, root, ap, key);
686
687
3.94k
        case '[':
688
3.94k
            return unpack_array(s, root, ap, key);
689
690
0
        case 's':
691
0
            if (root && !json_is_string(root)) {
692
0
                set_error(s, "<validation>", json_error_wrong_type,
693
0
                          "Expected string, got %s%s%s", type_name(root),
694
0
                          key ? " for key " : "", key ? key : "");
695
0
                return -1;
696
0
            }
697
698
0
            if (!(s->flags & JSON_VALIDATE_ONLY)) {
699
0
                const char **str_target;
700
0
                size_t *len_target = NULL;
701
702
0
                str_target = va_arg(*ap, const char **);
703
0
                if (!str_target) {
704
0
                    set_error(s, "<args>", json_error_null_value, "NULL string argument");
705
0
                    return -1;
706
0
                }
707
708
0
                next_token(s);
709
710
0
                if (token(s) == '%') {
711
0
                    len_target = va_arg(*ap, size_t *);
712
0
                    if (!len_target) {
713
0
                        set_error(s, "<args>", json_error_null_value,
714
0
                                  "NULL string length argument");
715
0
                        return -1;
716
0
                    }
717
0
                } else
718
0
                    prev_token(s);
719
720
0
                if (root) {
721
0
                    *str_target = json_string_value(root);
722
0
                    if (len_target)
723
0
                        *len_target = json_string_length(root);
724
0
                }
725
0
            }
726
0
            return 0;
727
728
0
        case 'i':
729
0
            if (root && !json_is_integer(root)) {
730
0
                set_error(s, "<validation>", json_error_wrong_type,
731
0
                          "Expected integer, got %s%s%s", type_name(root),
732
0
                          key ? " for key " : "", key ? key : "");
733
0
                return -1;
734
0
            }
735
736
0
            if (!(s->flags & JSON_VALIDATE_ONLY)) {
737
0
                int *target = va_arg(*ap, int *);
738
0
                if (root)
739
0
                    *target = (int)json_integer_value(root);
740
0
            }
741
742
0
            return 0;
743
744
0
        case 'I':
745
0
            if (root && !json_is_integer(root)) {
746
0
                set_error(s, "<validation>", json_error_wrong_type,
747
0
                          "Expected integer, got %s%s%s", type_name(root),
748
0
                          key ? " for key " : "", key ? key : "");
749
0
                return -1;
750
0
            }
751
752
0
            if (!(s->flags & JSON_VALIDATE_ONLY)) {
753
0
                json_int_t *target = va_arg(*ap, json_int_t *);
754
0
                if (root)
755
0
                    *target = json_integer_value(root);
756
0
            }
757
758
0
            return 0;
759
760
0
        case 'b':
761
0
            if (root && !json_is_boolean(root)) {
762
0
                set_error(s, "<validation>", json_error_wrong_type,
763
0
                          "Expected true or false, got %s%s%s", type_name(root),
764
0
                          key ? " for key " : "", key ? key : "");
765
0
                return -1;
766
0
            }
767
768
0
            if (!(s->flags & JSON_VALIDATE_ONLY)) {
769
0
                int *target = va_arg(*ap, int *);
770
0
                if (root)
771
0
                    *target = json_is_true(root);
772
0
            }
773
774
0
            return 0;
775
776
0
        case 'f':
777
0
            if (root && !json_is_real(root)) {
778
0
                set_error(s, "<validation>", json_error_wrong_type,
779
0
                          "Expected real, got %s%s%s", type_name(root),
780
0
                          key ? " for key " : "", key ? key : "");
781
0
                return -1;
782
0
            }
783
784
0
            if (!(s->flags & JSON_VALIDATE_ONLY)) {
785
0
                double *target = va_arg(*ap, double *);
786
0
                if (root)
787
0
                    *target = json_real_value(root);
788
0
            }
789
790
0
            return 0;
791
792
0
        case 'F':
793
0
            if (root && !json_is_number(root)) {
794
0
                set_error(s, "<validation>", json_error_wrong_type,
795
0
                          "Expected real or integer, got %s%s%s", type_name(root),
796
0
                          key ? " for key " : "", key ? key : "");
797
0
                return -1;
798
0
            }
799
800
0
            if (!(s->flags & JSON_VALIDATE_ONLY)) {
801
0
                double *target = va_arg(*ap, double *);
802
0
                if (root)
803
0
                    *target = json_number_value(root);
804
0
            }
805
806
0
            return 0;
807
808
0
        case 'O':
809
0
            if (root && !(s->flags & JSON_VALIDATE_ONLY))
810
0
                json_incref(root);
811
            /* Fall through */
812
813
4.82k
        case 'o':
814
4.82k
            if (!(s->flags & JSON_VALIDATE_ONLY)) {
815
4.82k
                json_t **target = va_arg(*ap, json_t **);
816
4.82k
                if (root)
817
4.38k
                    *target = root;
818
4.82k
            }
819
820
4.82k
            return 0;
821
822
0
        case 'n':
823
            /* Never assign, just validate */
824
0
            if (root && !json_is_null(root)) {
825
0
                set_error(s, "<validation>", json_error_wrong_type,
826
0
                          "Expected null, got %s%s%s", type_name(root),
827
0
                          key ? " for key " : "", key ? key : "");
828
0
                return -1;
829
0
            }
830
0
            return 0;
831
832
0
        default:
833
0
            set_error(s, "<format>", json_error_invalid_format,
834
0
                      "Unexpected format character '%c'", token(s));
835
0
            return -1;
836
9.20k
    }
837
9.20k
}
838
839
0
json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap) {
840
0
    scanner_t s;
841
0
    va_list ap_copy;
842
0
    json_t *value;
843
844
0
    if (!fmt || !*fmt) {
845
0
        jsonp_error_init(error, "<format>");
846
0
        jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument,
847
0
                        "NULL or empty format string");
848
0
        return NULL;
849
0
    }
850
0
    jsonp_error_init(error, NULL);
851
852
0
    scanner_init(&s, error, flags, fmt);
853
0
    next_token(&s);
854
855
0
    va_copy(ap_copy, ap);
856
0
    value = pack(&s, &ap_copy);
857
0
    va_end(ap_copy);
858
859
    /* This will cover all situations where s.has_error is true */
860
0
    if (!value)
861
0
        return NULL;
862
863
0
    next_token(&s);
864
0
    if (token(&s)) {
865
0
        json_decref(value);
866
0
        set_error(&s, "<format>", json_error_invalid_format,
867
0
                  "Garbage after format string");
868
0
        return NULL;
869
0
    }
870
871
0
    return value;
872
0
}
873
874
0
json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) {
875
0
    json_t *value;
876
0
    va_list ap;
877
878
0
    va_start(ap, fmt);
879
0
    value = json_vpack_ex(error, flags, fmt, ap);
880
0
    va_end(ap);
881
882
0
    return value;
883
0
}
884
885
0
json_t *json_pack(const char *fmt, ...) {
886
0
    json_t *value;
887
0
    va_list ap;
888
889
0
    va_start(ap, fmt);
890
0
    value = json_vpack_ex(NULL, 0, fmt, ap);
891
0
    va_end(ap);
892
893
0
    return value;
894
0
}
895
896
int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt,
897
4.82k
                    va_list ap) {
898
4.82k
    scanner_t s;
899
4.82k
    va_list ap_copy;
900
901
4.82k
    if (!root) {
902
0
        jsonp_error_init(error, "<root>");
903
0
        jsonp_error_set(error, -1, -1, 0, json_error_null_value, "NULL root value");
904
0
        return -1;
905
0
    }
906
907
4.82k
    if (!fmt || !*fmt) {
908
0
        jsonp_error_init(error, "<format>");
909
0
        jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument,
910
0
                        "NULL or empty format string");
911
0
        return -1;
912
0
    }
913
4.82k
    jsonp_error_init(error, NULL);
914
915
4.82k
    scanner_init(&s, error, flags, fmt);
916
4.82k
    next_token(&s);
917
918
4.82k
    va_copy(ap_copy, ap);
919
4.82k
    if (unpack(&s, root, &ap_copy, NULL)) {
920
829
        va_end(ap_copy);
921
829
        return -1;
922
829
    }
923
4.82k
    va_end(ap_copy);
924
925
3.99k
    next_token(&s);
926
3.99k
    if (token(&s)) {
927
0
        set_error(&s, "<format>", json_error_invalid_format,
928
0
                  "Garbage after format string");
929
0
        return -1;
930
0
    }
931
932
3.99k
    return 0;
933
3.99k
}
934
935
int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt,
936
0
                   ...) {
937
0
    int ret;
938
0
    va_list ap;
939
940
0
    va_start(ap, fmt);
941
0
    ret = json_vunpack_ex(root, error, flags, fmt, ap);
942
0
    va_end(ap);
943
944
0
    return ret;
945
0
}
946
947
4.82k
int json_unpack(json_t *root, const char *fmt, ...) {
948
4.82k
    int ret;
949
4.82k
    va_list ap;
950
951
4.82k
    va_start(ap, fmt);
952
4.82k
    ret = json_vunpack_ex(root, NULL, 0, fmt, ap);
953
4.82k
    va_end(ap);
954
955
4.82k
    return ret;
956
4.82k
}