Coverage Report

Created: 2026-01-10 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vulkan-loader/loader/cJSON.c
Line
Count
Source
1
/*
2
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
  of this software and associated documentation files (the "Software"), to deal
6
  in the Software without restriction, including without limitation the rights
7
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
  copies of the Software, and to permit persons to whom the Software is
9
  furnished to do so, subject to the following conditions:
10
11
  The above copyright notice and this permission notice shall be included in
12
  all copies or substantial portions of the Software.
13
14
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
  THE SOFTWARE.
21
*/
22
23
/* cJSON */
24
/* JSON parser in C. */
25
26
/* disable warnings about old C89 functions in MSVC */
27
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
28
#define _CRT_SECURE_NO_DEPRECATE
29
#endif
30
31
#ifdef __GNUC__
32
#pragma GCC visibility push(default)
33
#endif
34
#if defined(_MSC_VER)
35
#pragma warning(push)
36
/* disable warning about single line comments in system headers */
37
#pragma warning(disable : 4001)
38
#endif
39
40
#include <string.h>
41
#include <stdio.h>
42
#include <math.h>
43
#include <stdlib.h>
44
#include <limits.h>
45
#include <ctype.h>
46
#include <float.h>
47
48
#ifdef ENABLE_LOCALES
49
#include <locale.h>
50
#endif
51
52
#if defined(_MSC_VER)
53
#pragma warning(pop)
54
#endif
55
#ifdef __GNUC__
56
#pragma GCC visibility pop
57
#endif
58
59
#include "cJSON.h"
60
61
#include "allocation.h"
62
63
/* define our own boolean type */
64
#ifdef true
65
#undef true
66
#endif
67
20.0M
#define true ((cJSON_bool)1)
68
69
#ifdef false
70
#undef false
71
#endif
72
2.64M
#define false ((cJSON_bool)0)
73
74
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
75
#ifndef isinf
76
#define isinf(d) (isnan((d - d)) && !isnan(d))
77
#endif
78
#ifndef isnan
79
#define isnan(d) (d != d)
80
#endif
81
82
#ifndef NAN
83
#ifdef _WIN32
84
#define NAN sqrt(-1.0)
85
#else
86
#define NAN 0.0 / 0.0
87
#endif
88
#endif
89
90
typedef struct {
91
    const unsigned char *json;
92
    size_t position;
93
} error;
94
static error global_error = {NULL, 0};
95
96
0
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { return (const char *)(global_error.json + global_error.position); }
97
98
663k
CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
99
663k
    if (!loader_cJSON_IsString(item)) {
100
295k
        return NULL;
101
295k
    }
102
103
367k
    return item->valuestring;
104
663k
}
105
106
0
CJSON_PUBLIC(double) loader_cJSON_GetNumberValue(const cJSON *const item) {
107
0
    if (!loader_cJSON_IsNumber(item)) {
108
0
        return (double)NAN;
109
0
    }
110
111
0
    return item->valuedouble;
112
0
}
113
114
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
115
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18)
116
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
117
#endif
118
119
/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
120
5.62M
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
121
5.62M
    if ((string1 == NULL) || (string2 == NULL)) {
122
236
        return 1;
123
236
    }
124
125
5.62M
    if (string1 == string2) {
126
0
        return 0;
127
0
    }
128
129
13.2M
    for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) {
130
8.70M
        if (*string1 == '\0') {
131
1.12M
            return 0;
132
1.12M
        }
133
8.70M
    }
134
135
4.49M
    return tolower(*string1) - tolower(*string2);
136
5.62M
}
137
138
/* strlen of character literals resolved at compile time */
139
0
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
140
141
/* Internal constructor. */
142
10.7M
static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
143
10.7M
    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
144
10.7M
    if (NULL != node) {
145
10.7M
        node->pAllocator = pAllocator;
146
10.7M
    }
147
10.7M
    return node;
148
10.7M
}
149
150
/* Delete a cJSON structure. */
151
3.60M
TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
152
3.60M
    cJSON *next = NULL;
153
14.3M
    while (item != NULL) {
154
10.7M
        next = item->next;
155
10.7M
        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
156
3.52M
            loader_cJSON_Delete(item->child);
157
3.52M
        }
158
10.7M
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
159
3.05M
            loader_free(item->pAllocator, item->valuestring);
160
3.05M
            item->valuestring = NULL;
161
3.05M
        }
162
10.7M
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
163
5.02M
            loader_free(item->pAllocator, item->string);
164
5.02M
            item->string = NULL;
165
5.02M
        }
166
10.7M
        loader_free(item->pAllocator, item);
167
10.7M
        item = next;
168
10.7M
    }
169
3.60M
}
170
171
/* get the decimal point character of the current locale */
172
4.22M
static unsigned char get_decimal_point(void) {
173
#ifdef ENABLE_LOCALES
174
    struct lconv *lconv = localeconv();
175
    return (unsigned char)lconv->decimal_point[0];
176
#else
177
4.22M
    return '.';
178
4.22M
#endif
179
4.22M
}
180
181
typedef struct {
182
    const unsigned char *content;
183
    size_t length;
184
    size_t offset;
185
    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
186
    const VkAllocationCallbacks *pAllocator;
187
} parse_buffer;
188
189
/* check if the given size is left to read in a given parse buffer (starting with 1) */
190
64.4M
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
191
/* check if the buffer can be accessed at the given index (starting with 0) */
192
251M
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
193
66.5M
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
194
/* get a pointer to the buffer at the position */
195
204M
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
196
197
/* Parse the input text to generate a number, and populate the result into item. */
198
3.73M
static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
199
3.73M
    double number = 0;
200
3.73M
    unsigned char *after_end = NULL;
201
3.73M
    unsigned char number_c_string[64];
202
3.73M
    unsigned char decimal_point = get_decimal_point();
203
3.73M
    size_t i = 0;
204
205
3.73M
    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
206
0
        return false;
207
0
    }
208
209
    /* copy the number into a temporary buffer and replace '.' with the decimal point
210
     * of the current locale (for strtod)
211
     * This also takes care of '\0' not necessarily being available for marking the end of the input */
212
12.4M
    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
213
12.4M
        switch (buffer_at_offset(input_buffer)[i]) {
214
774k
            case '0':
215
3.81M
            case '1':
216
4.49M
            case '2':
217
4.85M
            case '3':
218
5.20M
            case '4':
219
5.49M
            case '5':
220
6.34M
            case '6':
221
6.72M
            case '7':
222
7.08M
            case '8':
223
8.01M
            case '9':
224
8.01M
            case '+':
225
8.05M
            case '-':
226
8.65M
            case 'e':
227
8.65M
            case 'E':
228
8.65M
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
229
8.65M
                break;
230
231
78.8k
            case '.':
232
78.8k
                number_c_string[i] = decimal_point;
233
78.8k
                break;
234
235
3.73M
            default:
236
3.73M
                goto loop_end;
237
12.4M
        }
238
12.4M
    }
239
3.73M
loop_end:
240
3.73M
    number_c_string[i] = '\0';
241
242
3.73M
    number = strtod((const char *)number_c_string, (char **)&after_end);
243
3.73M
    if (number_c_string == after_end) {
244
20
        return false; /* parse_error */
245
20
    }
246
247
3.73M
    item->valuedouble = number;
248
249
    /* use saturation in case of overflow */
250
3.73M
    if (number >= INT_MAX) {
251
273k
        item->valueint = INT_MAX;
252
3.45M
    } else if (number <= (double)INT_MIN) {
253
18.5k
        item->valueint = INT_MIN;
254
3.44M
    } else {
255
3.44M
        item->valueint = (int)number;
256
3.44M
    }
257
258
3.73M
    item->type = cJSON_Number;
259
260
3.73M
    input_buffer->offset += (size_t)(after_end - number_c_string);
261
3.73M
    return true;
262
3.73M
}
263
264
typedef struct {
265
    unsigned char *buffer;
266
    size_t length;
267
    size_t offset;
268
    size_t depth; /* current nesting depth (for formatted printing) */
269
    cJSON_bool noalloc;
270
    cJSON_bool format; /* is this print a formatted print */
271
    const VkAllocationCallbacks *pAllocator;
272
} printbuffer;
273
274
/* realloc printbuffer if necessary to have at least "needed" bytes more */
275
6.99M
static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
276
6.99M
    unsigned char *newbuffer = NULL;
277
6.99M
    size_t newsize = 0;
278
279
6.99M
    if ((p == NULL) || (p->buffer == NULL)) {
280
0
        return NULL;
281
0
    }
282
283
6.99M
    if ((p->length > 0) && (p->offset >= p->length)) {
284
        /* make sure that offset is valid */
285
0
        return NULL;
286
0
    }
287
288
6.99M
    if (needed > INT_MAX) {
289
        /* sizes bigger than INT_MAX are currently not supported */
290
0
        return NULL;
291
0
    }
292
293
6.99M
    needed += p->offset + 1;
294
6.99M
    if (needed <= p->length) {
295
6.98M
        return p->buffer + p->offset;
296
6.98M
    }
297
298
9.85k
    if (p->noalloc) {
299
1.49k
        return NULL;
300
1.49k
    }
301
302
    /* calculate new buffer size */
303
8.36k
    if (needed > (INT_MAX / 2)) {
304
        /* overflow of int, use INT_MAX if possible */
305
0
        if (needed <= INT_MAX) {
306
0
            newsize = INT_MAX;
307
0
        } else {
308
0
            return NULL;
309
0
        }
310
8.36k
    } else {
311
8.36k
        newsize = needed * 2;
312
8.36k
    }
313
314
8.36k
    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
315
8.36k
    if (newbuffer == NULL) {
316
0
        *out_of_memory = true;
317
0
        loader_free(p->pAllocator, p->buffer);
318
0
        p->length = 0;
319
0
        p->buffer = NULL;
320
321
0
        return NULL;
322
0
    }
323
324
8.36k
    p->length = newsize;
325
8.36k
    p->buffer = newbuffer;
326
327
8.36k
    return newbuffer + p->offset;
328
8.36k
}
329
330
/* calculate the new length of the string in a printbuffer and update the offset */
331
2.90M
static void update_offset(printbuffer *const buffer) {
332
2.90M
    const unsigned char *buffer_pointer = NULL;
333
2.90M
    if ((buffer == NULL) || (buffer->buffer == NULL)) {
334
0
        return;
335
0
    }
336
2.90M
    buffer_pointer = buffer->buffer + buffer->offset;
337
338
2.90M
    buffer->offset += strlen((const char *)buffer_pointer);
339
2.90M
}
340
341
/* securely comparison of floating-point variables */
342
69.3k
static cJSON_bool compare_double(double a, double b) {
343
69.3k
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
344
69.3k
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
345
69.3k
}
346
347
/* Render the number nicely from the given item into a string. */
348
489k
static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
349
489k
    unsigned char *output_pointer = NULL;
350
489k
    double d = item->valuedouble;
351
489k
    int length = 0;
352
489k
    size_t i = 0;
353
489k
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
354
489k
    unsigned char decimal_point = get_decimal_point();
355
489k
    double test = 0.0;
356
357
489k
    if (output_buffer == NULL) {
358
0
        return false;
359
0
    }
360
361
    /* This checks for NaN and Infinity */
362
489k
    if (isnan(d) || isinf(d)) {
363
470
        length = snprintf((char *)number_buffer, 26, "null");
364
489k
    } else if (d == (double)item->valueint) {
365
420k
        length = snprintf((char *)number_buffer, 26, "%d", item->valueint);
366
420k
    } else {
367
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
368
69.3k
        length = snprintf((char *)number_buffer, 26, "%1.15g", d);
369
370
        /* Check whether the original double can be recovered */
371
69.3k
        if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) {
372
            /* If not, print with 17 decimal places of precision */
373
3.98k
            length = snprintf((char *)number_buffer, 26, "%1.17g", d);
374
3.98k
        }
375
69.3k
    }
376
377
    /* snprintf failed or buffer overrun occurred */
378
489k
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
379
0
        return false;
380
0
    }
381
382
    /* reserve appropriate space in the output */
383
489k
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""), out_of_memory);
384
489k
    if (output_pointer == NULL) {
385
0
        return false;
386
0
    }
387
388
    /* copy the printed number to the output and replace locale
389
     * dependent decimal point with '.' */
390
1.46M
    for (i = 0; i < ((size_t)length); i++) {
391
970k
        if (number_buffer[i] == decimal_point) {
392
15.3k
            output_pointer[i] = '.';
393
15.3k
            continue;
394
15.3k
        }
395
396
955k
        output_pointer[i] = number_buffer[i];
397
955k
    }
398
489k
    output_pointer[i] = '\0';
399
400
489k
    output_buffer->offset += (size_t)length;
401
402
489k
    return true;
403
489k
}
404
405
/* parse 4 digit hexadecimal number */
406
175k
static unsigned parse_hex4(const unsigned char *const input) {
407
175k
    unsigned int h = 0;
408
175k
    size_t i = 0;
409
410
637k
    for (i = 0; i < 4; i++) {
411
        /* parse digit */
412
567k
        if ((input[i] >= '0') && (input[i] <= '9')) {
413
228k
            h += (unsigned int)input[i] - '0';
414
338k
        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
415
60.5k
            h += (unsigned int)10 + input[i] - 'A';
416
278k
        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
417
172k
            h += (unsigned int)10 + input[i] - 'a';
418
172k
        } else /* invalid */
419
105k
        {
420
105k
            return 0;
421
105k
        }
422
423
462k
        if (i < 3) {
424
            /* shift left to make place for the next nibble */
425
392k
            h = h << 4;
426
392k
        }
427
462k
    }
428
429
69.6k
    return h;
430
175k
}
431
432
/* converts a UTF-16 literal to UTF-8
433
 * A literal can be one or two sequences of the form \uXXXX */
434
static unsigned char utf16_literal_to_utf8(const unsigned char *const input_pointer, const unsigned char *const input_end,
435
170k
                                           unsigned char **output_pointer) {
436
170k
    long unsigned int codepoint = 0;
437
170k
    unsigned int first_code = 0;
438
170k
    const unsigned char *first_sequence = input_pointer;
439
170k
    unsigned char utf8_length = 0;
440
170k
    unsigned char utf8_position = 0;
441
170k
    unsigned char sequence_length = 0;
442
170k
    unsigned char first_byte_mark = 0;
443
444
170k
    if ((input_end - first_sequence) < 6) {
445
        /* input ends unexpectedly */
446
26
        goto fail;
447
26
    }
448
449
    /* get the first utf16 sequence */
450
170k
    first_code = parse_hex4(first_sequence + 2);
451
452
    /* check that the code is valid */
453
170k
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
454
16
        goto fail;
455
16
    }
456
457
    /* UTF16 surrogate pair */
458
170k
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
459
4.52k
        const unsigned char *second_sequence = first_sequence + 6;
460
4.52k
        unsigned int second_code = 0;
461
4.52k
        sequence_length = 12; /* \uXXXX\uXXXX */
462
463
4.52k
        if ((input_end - second_sequence) < 6) {
464
            /* input ends unexpectedly */
465
2
            goto fail;
466
2
        }
467
468
4.52k
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
469
            /* missing second half of the surrogate pair */
470
38
            goto fail;
471
38
        }
472
473
        /* get the second utf16 sequence */
474
4.48k
        second_code = parse_hex4(second_sequence + 2);
475
        /* check that the code is valid */
476
4.48k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
477
            /* invalid second half of the surrogate pair */
478
74
            goto fail;
479
74
        }
480
481
        /* calculate the unicode codepoint from the surrogate pair */
482
4.41k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
483
166k
    } else {
484
166k
        sequence_length = 6; /* \uXXXX */
485
166k
        codepoint = first_code;
486
166k
    }
487
488
    /* encode as UTF-8
489
     * takes at maximum 4 bytes to encode:
490
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
491
170k
    if (codepoint < 0x80) {
492
        /* normal ascii, encoding 0xxxxxxx */
493
105k
        utf8_length = 1;
494
105k
    } else if (codepoint < 0x800) {
495
        /* two bytes, encoding 110xxxxx 10xxxxxx */
496
10.1k
        utf8_length = 2;
497
10.1k
        first_byte_mark = 0xC0; /* 11000000 */
498
54.3k
    } else if (codepoint < 0x10000) {
499
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
500
49.9k
        utf8_length = 3;
501
49.9k
        first_byte_mark = 0xE0; /* 11100000 */
502
49.9k
    } else if (codepoint <= 0x10FFFF) {
503
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
504
4.41k
        utf8_length = 4;
505
4.41k
        first_byte_mark = 0xF0; /* 11110000 */
506
4.41k
    } else {
507
        /* invalid unicode codepoint */
508
0
        goto fail;
509
0
    }
510
511
    /* encode as utf8 */
512
293k
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
513
        /* 10xxxxxx */
514
123k
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
515
123k
        codepoint >>= 6;
516
123k
    }
517
    /* encode first byte */
518
170k
    if (utf8_length > 1) {
519
64.4k
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
520
105k
    } else {
521
105k
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
522
105k
    }
523
524
170k
    *output_pointer += utf8_length;
525
526
170k
    return sequence_length;
527
528
156
fail:
529
156
    return 0;
530
170k
}
531
532
/* Parse the input text into an unescaped cinput, and populate item. */
533
8.07M
static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
534
8.07M
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
535
8.07M
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
536
8.07M
    unsigned char *output_pointer = NULL;
537
8.07M
    unsigned char *output = NULL;
538
539
    /* not a string */
540
8.07M
    if (buffer_at_offset(input_buffer)[0] != '\"') {
541
377
        goto fail;
542
377
    }
543
544
8.07M
    {
545
        /* calculate approximate size of the output (overestimate) */
546
8.07M
        size_t allocation_length = 0;
547
8.07M
        size_t skipped_bytes = 0;
548
301M
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
549
            /* is escape sequence */
550
293M
            if (input_end[0] == '\\') {
551
507k
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
552
                    /* prevent buffer overflow when last input character is a backslash */
553
0
                    goto fail;
554
0
                }
555
507k
                skipped_bytes++;
556
507k
                input_end++;
557
507k
            }
558
293M
            input_end++;
559
293M
        }
560
8.07M
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
561
115
            goto fail; /* string ended unexpectedly */
562
115
        }
563
564
        /* This is at most how much we need for the output */
565
8.07M
        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
566
8.07M
        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
567
8.07M
                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
568
8.07M
        if (output == NULL) {
569
0
            *out_of_memory = true;
570
0
            goto fail; /* allocation failure */
571
0
        }
572
8.07M
    }
573
574
8.07M
    output_pointer = output;
575
    /* loop through the string literal */
576
282M
    while (input_pointer < input_end) {
577
274M
        if (*input_pointer != '\\') {
578
274M
            *output_pointer++ = *input_pointer++;
579
274M
        }
580
        /* escape sequence */
581
351k
        else {
582
351k
            unsigned char sequence_length = 2;
583
351k
            if ((input_end - input_pointer) < 1) {
584
0
                goto fail;
585
0
            }
586
587
351k
            switch (input_pointer[1]) {
588
8.08k
                case 'b':
589
8.08k
                    *output_pointer++ = '\b';
590
8.08k
                    break;
591
7.15k
                case 'f':
592
7.15k
                    *output_pointer++ = '\f';
593
7.15k
                    break;
594
1.06k
                case 'n':
595
1.06k
                    *output_pointer++ = '\n';
596
1.06k
                    break;
597
133k
                case 'r':
598
133k
                    *output_pointer++ = '\r';
599
133k
                    break;
600
5.87k
                case 't':
601
5.87k
                    *output_pointer++ = '\t';
602
5.87k
                    break;
603
1.92k
                case '\"':
604
23.5k
                case '\\':
605
25.9k
                case '/':
606
25.9k
                    *output_pointer++ = input_pointer[1];
607
25.9k
                    break;
608
609
                /* UTF-16 literal */
610
170k
                case 'u':
611
170k
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
612
170k
                    if (sequence_length == 0) {
613
                        /* failed to convert UTF16-literal to UTF-8 */
614
156
                        goto fail;
615
156
                    }
616
170k
                    break;
617
618
170k
                default:
619
52
                    goto fail;
620
351k
            }
621
351k
            input_pointer += sequence_length;
622
351k
        }
623
274M
    }
624
625
    /* zero terminate the output */
626
8.07M
    *output_pointer = '\0';
627
628
8.07M
    item->type = cJSON_String;
629
8.07M
    item->valuestring = (char *)output;
630
631
8.07M
    input_buffer->offset = (size_t)(input_end - input_buffer->content);
632
8.07M
    input_buffer->offset++;
633
634
8.07M
    return true;
635
636
700
fail:
637
700
    if (output != NULL) {
638
208
        loader_free(input_buffer->pAllocator, output);
639
208
        output = NULL;
640
208
    }
641
642
700
    if (input_pointer != NULL) {
643
700
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
644
700
    }
645
646
700
    return false;
647
8.07M
}
648
649
/* Render the cstring provided to an escaped version that can be printed. */
650
1.94M
static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
651
1.94M
    const unsigned char *input_pointer = NULL;
652
1.94M
    unsigned char *output = NULL;
653
1.94M
    unsigned char *output_pointer = NULL;
654
1.94M
    size_t output_length = 0;
655
    /* numbers of additional characters needed for escaping */
656
1.94M
    size_t escape_characters = 0;
657
658
1.94M
    if (output_buffer == NULL) {
659
0
        return false;
660
0
    }
661
662
    /* empty string */
663
1.94M
    if (input == NULL) {
664
0
        output = ensure(output_buffer, sizeof(""), out_of_memory);
665
0
        if (output == NULL) {
666
0
            return false;
667
0
        }
668
669
0
        return true;
670
0
    }
671
672
    /* set "flag" to 1 if something needs to be escaped */
673
63.1M
    for (input_pointer = input; *input_pointer; input_pointer++) {
674
61.1M
        switch (*input_pointer) {
675
196
            case '\"':
676
5.39k
            case '\\':
677
8.47k
            case '\b':
678
30.6k
            case '\f':
679
120k
            case '\n':
680
172k
            case '\r':
681
173k
            case '\t':
682
                /* one character escape sequence */
683
173k
                escape_characters++;
684
173k
                break;
685
61.0M
            default:
686
61.0M
                if (*input_pointer < 32) {
687
                    /* UTF-16 escape sequence uXXXX */
688
40.6M
                    escape_characters += 5;
689
40.6M
                }
690
61.0M
                break;
691
61.1M
        }
692
61.1M
    }
693
1.94M
    output_length = (size_t)(input_pointer - input) + escape_characters;
694
695
1.94M
    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
696
1.94M
    if (output == NULL) {
697
1.49k
        return false;
698
1.49k
    }
699
700
    /* no characters have to be escaped */
701
1.94M
    if (escape_characters == 0) {
702
1.79M
        memcpy(output, input, output_length);
703
1.79M
        output[output_length] = '\0';
704
705
1.79M
        return true;
706
1.79M
    }
707
708
148k
    output_pointer = output;
709
    /* copy the string */
710
46.7M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
711
46.6M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
712
            /* normal character, copy */
713
6.76M
            *output_pointer = *input_pointer;
714
39.8M
        } else {
715
            // Loader specific modification - don't add a backslash because that will 'double up' any existing back slashes.
716
            // This change was added right after vulkan's public release, so while it may not be a problem, there are plenty
717
            // of API calls made which might not work if the paths have "\\"" in them
718
            /* character needs to be escaped */
719
            //*output_pointer++ = '\\';
720
39.8M
            switch (*input_pointer) {
721
5.19k
                case '\\':
722
5.19k
                    *output_pointer = '\\';
723
5.19k
                    break;
724
196
                case '\"':
725
196
                    *output_pointer = '\"';
726
196
                    break;
727
3.05k
                case '\b':
728
3.05k
                    *output_pointer = '\b';
729
3.05k
                    break;
730
22.2k
                case '\f':
731
22.2k
                    *output_pointer = '\f';
732
22.2k
                    break;
733
70.1k
                case '\n':
734
70.1k
                    *output_pointer = '\n';
735
70.1k
                    break;
736
51.1k
                case '\r':
737
51.1k
                    *output_pointer = '\r';
738
51.1k
                    break;
739
1.75k
                case '\t':
740
1.75k
                    *output_pointer = '\t';
741
1.75k
                    break;
742
39.7M
                default:
743
                    /* escape and print as unicode codepoint */
744
39.7M
                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
745
39.7M
                    output_pointer += 4;
746
39.7M
                    break;
747
39.8M
            }
748
39.8M
        }
749
46.6M
    }
750
148k
    output[output_length] = '\0';
751
752
148k
    return true;
753
148k
}
754
755
/* Invoke print_string_ptr (which is useful) on an item. */
756
1.10M
static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
757
1.10M
    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
758
1.10M
}
759
760
/* Predeclare these prototypes. */
761
static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
762
static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
763
static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
764
static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
765
static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
766
static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
767
768
/* Utility to jump whitespace and cr/lf */
769
35.2M
static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
770
35.2M
    if ((buffer == NULL) || (buffer->content == NULL)) {
771
0
        return NULL;
772
0
    }
773
774
35.2M
    if (cannot_access_at_index(buffer, 0)) {
775
0
        return buffer;
776
0
    }
777
778
52.6M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
779
17.4M
        buffer->offset++;
780
17.4M
    }
781
782
35.2M
    if (buffer->offset == buffer->length) {
783
1.72k
        buffer->offset--;
784
1.72k
    }
785
786
35.2M
    return buffer;
787
35.2M
}
788
789
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
790
15.6k
static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
791
15.6k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
792
0
        return NULL;
793
0
    }
794
795
15.6k
    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
796
285
        buffer->offset += 3;
797
285
    }
798
799
15.6k
    return buffer;
800
15.6k
}
801
802
CJSON_PUBLIC(cJSON *)
803
loader_cJSON_ParseWithOpts(const VkAllocationCallbacks *pAllocator, const char *value, const char **return_parse_end,
804
0
                           cJSON_bool require_null_terminated, bool *out_of_memory) {
805
0
    size_t buffer_length;
806
807
0
    if (NULL == value) {
808
0
        return NULL;
809
0
    }
810
811
    /* Adding null character size due to require_null_terminated. */
812
0
    buffer_length = strlen(value) + sizeof("");
813
814
0
    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, return_parse_end, require_null_terminated,
815
0
                                            out_of_memory);
816
0
}
817
818
/* Parse an object - create a new root, and populate. */
819
CJSON_PUBLIC(cJSON *)
820
loader_cJSON_ParseWithLengthOpts(const VkAllocationCallbacks *pAllocator, const char *value, size_t buffer_length,
821
15.6k
                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
822
15.6k
    parse_buffer buffer = {0, 0, 0, 0, 0};
823
15.6k
    cJSON *item = NULL;
824
825
    /* reset error position */
826
15.6k
    global_error.json = NULL;
827
15.6k
    global_error.position = 0;
828
829
15.6k
    if (value == NULL || 0 == buffer_length) {
830
0
        goto fail;
831
0
    }
832
833
15.6k
    buffer.content = (const unsigned char *)value;
834
15.6k
    buffer.length = buffer_length;
835
15.6k
    buffer.offset = 0;
836
15.6k
    buffer.pAllocator = pAllocator;
837
838
15.6k
    item = cJSON_New_Item(pAllocator);
839
15.6k
    if (item == NULL) /* memory fail */
840
0
    {
841
0
        *out_of_memory = true;
842
0
        goto fail;
843
0
    }
844
845
15.6k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
846
        /* parse failure. ep is set. */
847
2.85k
        goto fail;
848
2.85k
    }
849
850
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
851
12.7k
    if (require_null_terminated) {
852
0
        buffer_skip_whitespace(&buffer);
853
0
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
854
0
            goto fail;
855
0
        }
856
0
    }
857
12.7k
    if (return_parse_end) {
858
0
        *return_parse_end = (const char *)buffer_at_offset(&buffer);
859
0
    }
860
861
12.7k
    return item;
862
863
2.85k
fail:
864
2.85k
    if (item != NULL) {
865
2.85k
        loader_cJSON_Delete(item);
866
2.85k
    }
867
868
2.85k
    if (value != NULL) {
869
2.85k
        error local_error;
870
2.85k
        local_error.json = (const unsigned char *)value;
871
2.85k
        local_error.position = 0;
872
873
2.85k
        if (buffer.offset < buffer.length) {
874
2.49k
            local_error.position = buffer.offset;
875
2.49k
        } else if (buffer.length > 0) {
876
365
            local_error.position = buffer.length - 1;
877
365
        }
878
879
2.85k
        if (return_parse_end != NULL) {
880
0
            *return_parse_end = (const char *)local_error.json + local_error.position;
881
0
        }
882
883
2.85k
        global_error = local_error;
884
2.85k
    }
885
886
2.85k
    return NULL;
887
12.7k
}
888
889
/* Default options for loader_cJSON_Parse */
890
0
CJSON_PUBLIC(cJSON *) loader_cJSON_Parse(const VkAllocationCallbacks *pAllocator, const char *value, bool *out_of_memory) {
891
0
    return loader_cJSON_ParseWithOpts(pAllocator, value, 0, 0, out_of_memory);
892
0
}
893
894
CJSON_PUBLIC(cJSON *)
895
loader_cJSON_ParseWithLength(const VkAllocationCallbacks *pAllocator, const char *value, size_t buffer_length,
896
15.6k
                             bool *out_of_memory) {
897
15.6k
    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
898
15.6k
}
899
900
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
901
902
641k
static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
903
641k
    static const size_t default_buffer_size = 256;
904
641k
    printbuffer buffer[1];
905
641k
    unsigned char *printed = NULL;
906
907
641k
    memset(buffer, 0, sizeof(buffer));
908
909
    /* create buffer */
910
641k
    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
911
641k
    buffer->length = default_buffer_size;
912
641k
    buffer->format = format;
913
641k
    buffer->pAllocator = item->pAllocator;
914
641k
    if (buffer->buffer == NULL) {
915
0
        *out_of_memory = true;
916
0
        goto fail;
917
0
    }
918
919
    /* print the value */
920
641k
    if (!print_value(item, buffer, out_of_memory)) {
921
0
        goto fail;
922
0
    }
923
641k
    update_offset(buffer);
924
925
641k
    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
926
641k
                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
927
641k
    if (printed == NULL) {
928
0
        *out_of_memory = true;
929
0
        goto fail;
930
0
    }
931
641k
    buffer->buffer = NULL;
932
933
641k
    return printed;
934
935
0
fail:
936
0
    if (buffer->buffer != NULL) {
937
0
        loader_free(item->pAllocator, buffer->buffer);
938
0
        buffer->buffer = NULL;
939
0
    }
940
941
0
    if (printed != NULL) {
942
0
        loader_free(item->pAllocator, printed);
943
0
        printed = NULL;
944
0
    }
945
946
0
    return NULL;
947
641k
}
948
949
/* Render a cJSON item/entity/structure to text. */
950
641k
TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
951
641k
    return (char *)print(item, true, out_of_memory);
952
641k
}
953
954
0
CJSON_PUBLIC(char *) loader_cJSON_PrintUnformatted(const cJSON *item, bool *out_of_memory) {
955
0
    return (char *)print(item, false, out_of_memory);
956
0
}
957
958
CJSON_PUBLIC(char *)
959
0
loader_cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt, bool *out_of_memory) {
960
0
    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
961
962
0
    if (prebuffer < 0) {
963
0
        return NULL;
964
0
    }
965
966
0
    p.buffer = (unsigned char *)loader_alloc(item->pAllocator, (size_t)prebuffer, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
967
0
    if (!p.buffer) {
968
0
        return NULL;
969
0
    }
970
971
0
    p.length = (size_t)prebuffer;
972
0
    p.offset = 0;
973
0
    p.noalloc = false;
974
0
    p.format = fmt;
975
0
    p.pAllocator = item->pAllocator;
976
977
0
    if (!print_value(item, &p, out_of_memory)) {
978
0
        loader_free(item->pAllocator, p.buffer);
979
0
        p.buffer = NULL;
980
0
        return NULL;
981
0
    }
982
983
0
    return (char *)p.buffer;
984
0
}
985
986
CJSON_PUBLIC(cJSON_bool)
987
401k
loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
988
401k
    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
989
990
401k
    if ((length < 0) || (buffer == NULL)) {
991
0
        return false;
992
0
    }
993
994
401k
    p.buffer = (unsigned char *)buffer;
995
401k
    p.length = (size_t)length;
996
401k
    p.offset = 0;
997
401k
    p.noalloc = true;
998
401k
    p.format = format;
999
401k
    p.pAllocator = item->pAllocator;
1000
401k
    bool out_of_memory = false;
1001
401k
    return print_value(item, &p, &out_of_memory);
1002
401k
}
1003
1004
/* Parser core - when encountering text, process appropriately. */
1005
10.7M
static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1006
10.7M
    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
1007
0
        return false; /* no input */
1008
0
    }
1009
1010
    /* parse the different types of values */
1011
    /* null */
1012
10.7M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
1013
18.2k
        item->type = cJSON_NULL;
1014
18.2k
        input_buffer->offset += 4;
1015
18.2k
        return true;
1016
18.2k
    }
1017
    /* false */
1018
10.7M
    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
1019
18.4k
        item->type = cJSON_False;
1020
18.4k
        input_buffer->offset += 5;
1021
18.4k
        return true;
1022
18.4k
    }
1023
    /* true */
1024
10.7M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
1025
147k
        item->type = cJSON_True;
1026
147k
        item->valueint = 1;
1027
147k
        input_buffer->offset += 4;
1028
147k
        return true;
1029
147k
    }
1030
    /* string */
1031
10.5M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
1032
3.05M
        return parse_string(item, input_buffer, out_of_memory);
1033
3.05M
    }
1034
    /* number */
1035
7.51M
    if (can_access_at_index(input_buffer, 0) &&
1036
7.51M
        ((buffer_at_offset(input_buffer)[0] == '-') ||
1037
7.47M
         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
1038
3.73M
        return parse_number(item, input_buffer);
1039
3.73M
    }
1040
    /* array */
1041
3.78M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
1042
977k
        return parse_array(item, input_buffer, out_of_memory);
1043
977k
    }
1044
    /* object */
1045
2.80M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
1046
2.80M
        return parse_object(item, input_buffer, out_of_memory);
1047
2.80M
    }
1048
1049
1.80k
    return false;
1050
2.80M
}
1051
1052
/* Render a value to text. */
1053
2.47M
static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1054
2.47M
    unsigned char *output = NULL;
1055
1056
2.47M
    if ((item == NULL) || (output_buffer == NULL)) {
1057
0
        return false;
1058
0
    }
1059
1060
2.47M
    switch ((item->type) & 0xFF) {
1061
5.42k
        case cJSON_NULL:
1062
5.42k
            output = ensure(output_buffer, 5, out_of_memory);
1063
5.42k
            if (output == NULL) {
1064
0
                return false;
1065
0
            }
1066
5.42k
            strcpy((char *)output, "null");
1067
5.42k
            return true;
1068
1069
4.94k
        case cJSON_False:
1070
4.94k
            output = ensure(output_buffer, 6, out_of_memory);
1071
4.94k
            if (output == NULL) {
1072
0
                return false;
1073
0
            }
1074
4.94k
            strcpy((char *)output, "false");
1075
4.94k
            return true;
1076
1077
43.8k
        case cJSON_True:
1078
43.8k
            output = ensure(output_buffer, 5, out_of_memory);
1079
43.8k
            if (output == NULL) {
1080
0
                return false;
1081
0
            }
1082
43.8k
            strcpy((char *)output, "true");
1083
43.8k
            return true;
1084
1085
489k
        case cJSON_Number:
1086
489k
            return print_number(item, output_buffer, out_of_memory);
1087
1088
0
        case cJSON_Raw: {
1089
0
            size_t raw_length = 0;
1090
0
            if (item->valuestring == NULL) {
1091
0
                return false;
1092
0
            }
1093
1094
0
            raw_length = strlen(item->valuestring) + sizeof("");
1095
0
            output = ensure(output_buffer, raw_length, out_of_memory);
1096
0
            if (output == NULL) {
1097
0
                return false;
1098
0
            }
1099
0
            memcpy(output, item->valuestring, raw_length);
1100
0
            return true;
1101
0
        }
1102
1103
1.10M
        case cJSON_String:
1104
1.10M
            return print_string(item, output_buffer, out_of_memory);
1105
1106
254k
        case cJSON_Array:
1107
254k
            return print_array(item, output_buffer, out_of_memory);
1108
1109
570k
        case cJSON_Object:
1110
570k
            return print_object(item, output_buffer, out_of_memory);
1111
1112
0
        default:
1113
0
            return false;
1114
2.47M
    }
1115
2.47M
}
1116
1117
/* Build an array from input text. */
1118
977k
static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1119
977k
    cJSON *head = NULL; /* head of the linked list */
1120
977k
    cJSON *current_item = NULL;
1121
1122
977k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1123
2
        return false; /* to deeply nested */
1124
2
    }
1125
977k
    input_buffer->depth++;
1126
1127
977k
    if (buffer_at_offset(input_buffer)[0] != '[') {
1128
        /* not an array */
1129
0
        goto fail;
1130
0
    }
1131
1132
977k
    input_buffer->offset++;
1133
977k
    buffer_skip_whitespace(input_buffer);
1134
977k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
1135
        /* empty array */
1136
73.0k
        goto success;
1137
73.0k
    }
1138
1139
    /* check if we skipped to the end of the buffer */
1140
904k
    if (cannot_access_at_index(input_buffer, 0)) {
1141
0
        input_buffer->offset--;
1142
0
        goto fail;
1143
0
    }
1144
1145
    /* step back to character in front of the first element */
1146
904k
    input_buffer->offset--;
1147
    /* loop through the comma separated array elements */
1148
5.71M
    do {
1149
        /* allocate next item */
1150
5.71M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1151
5.71M
        if (new_item == NULL) {
1152
0
            *out_of_memory = true;
1153
0
            goto fail; /* allocation failure */
1154
0
        }
1155
1156
        /* attach next item to list */
1157
5.71M
        if (head == NULL) {
1158
            /* start the linked list */
1159
904k
            current_item = head = new_item;
1160
4.81M
        } else {
1161
            /* add to the end and advance */
1162
4.81M
            current_item->next = new_item;
1163
4.81M
            new_item->prev = current_item;
1164
4.81M
            current_item = new_item;
1165
4.81M
        }
1166
1167
        /* parse next value */
1168
5.71M
        input_buffer->offset++;
1169
5.71M
        buffer_skip_whitespace(input_buffer);
1170
5.71M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1171
52.1k
            goto fail; /* failed to parse value */
1172
52.1k
        }
1173
5.66M
        buffer_skip_whitespace(input_buffer);
1174
5.66M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1175
1176
851k
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
1177
251
        goto fail; /* expected end of array */
1178
251
    }
1179
1180
924k
success:
1181
924k
    input_buffer->depth--;
1182
1183
924k
    if (head != NULL) {
1184
851k
        head->prev = current_item;
1185
851k
    }
1186
1187
924k
    item->type = cJSON_Array;
1188
924k
    item->child = head;
1189
1190
924k
    input_buffer->offset++;
1191
1192
924k
    return true;
1193
1194
52.4k
fail:
1195
52.4k
    if (head != NULL) {
1196
52.4k
        loader_cJSON_Delete(head);
1197
52.4k
    }
1198
1199
52.4k
    return false;
1200
851k
}
1201
1202
/* Render an array to text */
1203
254k
static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1204
254k
    unsigned char *output_pointer = NULL;
1205
254k
    size_t length = 0;
1206
254k
    cJSON *current_element = item->child;
1207
1208
254k
    if (output_buffer == NULL) {
1209
0
        return false;
1210
0
    }
1211
1212
    /* Compose the output array. */
1213
    /* opening square bracket */
1214
254k
    output_pointer = ensure(output_buffer, 1, out_of_memory);
1215
254k
    if (output_pointer == NULL) {
1216
0
        return false;
1217
0
    }
1218
1219
254k
    *output_pointer = '[';
1220
254k
    output_buffer->offset++;
1221
254k
    output_buffer->depth++;
1222
1223
841k
    while (current_element != NULL) {
1224
587k
        if (!print_value(current_element, output_buffer, out_of_memory)) {
1225
0
            return false;
1226
0
        }
1227
587k
        update_offset(output_buffer);
1228
587k
        if (current_element->next) {
1229
337k
            length = (size_t)(output_buffer->format ? 2 : 1);
1230
337k
            output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1231
337k
            if (output_pointer == NULL) {
1232
0
                return false;
1233
0
            }
1234
337k
            *output_pointer++ = ',';
1235
337k
            if (output_buffer->format) {
1236
337k
                *output_pointer++ = ' ';
1237
337k
            }
1238
337k
            *output_pointer = '\0';
1239
337k
            output_buffer->offset += length;
1240
337k
        }
1241
587k
        current_element = current_element->next;
1242
587k
    }
1243
1244
254k
    output_pointer = ensure(output_buffer, 2, out_of_memory);
1245
254k
    if (output_pointer == NULL) {
1246
0
        return false;
1247
0
    }
1248
254k
    *output_pointer++ = ']';
1249
254k
    *output_pointer = '\0';
1250
254k
    output_buffer->depth--;
1251
1252
254k
    return true;
1253
254k
}
1254
1255
/* Build an object from the text. */
1256
2.80M
static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1257
2.80M
    cJSON *head = NULL; /* linked list head */
1258
2.80M
    cJSON *current_item = NULL;
1259
1260
2.80M
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1261
6
        return false; /* to deeply nested */
1262
6
    }
1263
2.80M
    input_buffer->depth++;
1264
1265
2.80M
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
1266
0
        goto fail; /* not an object */
1267
0
    }
1268
1269
2.80M
    input_buffer->offset++;
1270
2.80M
    buffer_skip_whitespace(input_buffer);
1271
2.80M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
1272
115k
        goto success; /* empty object */
1273
115k
    }
1274
1275
    /* check if we skipped to the end of the buffer */
1276
2.68M
    if (cannot_access_at_index(input_buffer, 0)) {
1277
0
        input_buffer->offset--;
1278
0
        goto fail;
1279
0
    }
1280
1281
    /* step back to character in front of the first element */
1282
2.68M
    input_buffer->offset--;
1283
    /* loop through the comma separated array elements */
1284
5.02M
    do {
1285
        /* allocate next item */
1286
5.02M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1287
5.02M
        if (new_item == NULL) {
1288
0
            *out_of_memory = true;
1289
0
            goto fail; /* allocation failure */
1290
0
        }
1291
1292
        /* attach next item to list */
1293
5.02M
        if (head == NULL) {
1294
            /* start the linked list */
1295
2.68M
            current_item = head = new_item;
1296
2.68M
        } else {
1297
            /* add to the end and advance */
1298
2.33M
            current_item->next = new_item;
1299
2.33M
            new_item->prev = current_item;
1300
2.33M
            current_item = new_item;
1301
2.33M
        }
1302
1303
5.02M
        if (cannot_access_at_index(input_buffer, 1)) {
1304
0
            goto fail; /* nothing comes after the comma */
1305
0
        }
1306
1307
        /* parse the name of the child */
1308
5.02M
        input_buffer->offset++;
1309
5.02M
        buffer_skip_whitespace(input_buffer);
1310
5.02M
        if (!parse_string(current_item, input_buffer, out_of_memory)) {
1311
462
            goto fail; /* failed to parse name */
1312
462
        }
1313
5.02M
        buffer_skip_whitespace(input_buffer);
1314
1315
        /* swap valuestring and string, because we parsed the name */
1316
5.02M
        current_item->string = current_item->valuestring;
1317
5.02M
        current_item->valuestring = NULL;
1318
1319
5.02M
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
1320
40
            goto fail; /* invalid object */
1321
40
        }
1322
1323
        /* parse the value */
1324
5.02M
        input_buffer->offset++;
1325
5.02M
        buffer_skip_whitespace(input_buffer);
1326
5.02M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1327
16.7k
            goto fail; /* failed to parse value */
1328
16.7k
        }
1329
5.00M
        buffer_skip_whitespace(input_buffer);
1330
5.00M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1331
1332
2.67M
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
1333
28
        goto fail; /* expected end of object */
1334
28
    }
1335
1336
2.78M
success:
1337
2.78M
    input_buffer->depth--;
1338
1339
2.78M
    if (head != NULL) {
1340
2.67M
        head->prev = current_item;
1341
2.67M
    }
1342
1343
2.78M
    item->type = cJSON_Object;
1344
2.78M
    item->child = head;
1345
1346
2.78M
    input_buffer->offset++;
1347
2.78M
    return true;
1348
1349
17.2k
fail:
1350
17.2k
    if (head != NULL) {
1351
17.2k
        loader_cJSON_Delete(head);
1352
17.2k
    }
1353
1354
17.2k
    return false;
1355
2.67M
}
1356
1357
/* Render an object to text. */
1358
570k
static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1359
570k
    unsigned char *output_pointer = NULL;
1360
570k
    size_t length = 0;
1361
570k
    cJSON *current_item = item->child;
1362
1363
570k
    if (output_buffer == NULL) {
1364
0
        return false;
1365
0
    }
1366
1367
    /* Compose the output: */
1368
570k
    length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
1369
570k
    output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1370
570k
    if (output_pointer == NULL) {
1371
0
        return false;
1372
0
    }
1373
1374
570k
    *output_pointer++ = '{';
1375
570k
    output_buffer->depth++;
1376
570k
    if (output_buffer->format) {
1377
570k
        *output_pointer++ = '\n';
1378
570k
    }
1379
570k
    output_buffer->offset += length;
1380
1381
1.41M
    while (current_item) {
1382
839k
        if (output_buffer->format) {
1383
839k
            size_t i;
1384
839k
            output_pointer = ensure(output_buffer, output_buffer->depth, out_of_memory);
1385
839k
            if (output_pointer == NULL) {
1386
0
                return false;
1387
0
            }
1388
324M
            for (i = 0; i < output_buffer->depth; i++) {
1389
323M
                *output_pointer++ = '\t';
1390
323M
            }
1391
839k
            output_buffer->offset += output_buffer->depth;
1392
839k
        }
1393
1394
        /* print key */
1395
839k
        if (!print_string_ptr((unsigned char *)current_item->string, output_buffer, out_of_memory)) {
1396
0
            return false;
1397
0
        }
1398
839k
        update_offset(output_buffer);
1399
1400
839k
        length = (size_t)(output_buffer->format ? 2 : 1);
1401
839k
        output_pointer = ensure(output_buffer, length, out_of_memory);
1402
839k
        if (output_pointer == NULL) {
1403
0
            return false;
1404
0
        }
1405
839k
        *output_pointer++ = ':';
1406
839k
        if (output_buffer->format) {
1407
839k
            *output_pointer++ = '\t';
1408
839k
        }
1409
839k
        output_buffer->offset += length;
1410
1411
        /* print value */
1412
839k
        if (!print_value(current_item, output_buffer, out_of_memory)) {
1413
0
            return false;
1414
0
        }
1415
839k
        update_offset(output_buffer);
1416
1417
        /* print comma if not last */
1418
839k
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1419
839k
        output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1420
839k
        if (output_pointer == NULL) {
1421
0
            return false;
1422
0
        }
1423
839k
        if (current_item->next) {
1424
300k
            *output_pointer++ = ',';
1425
300k
        }
1426
1427
839k
        if (output_buffer->format) {
1428
839k
            *output_pointer++ = '\n';
1429
839k
        }
1430
839k
        *output_pointer = '\0';
1431
839k
        output_buffer->offset += length;
1432
1433
839k
        current_item = current_item->next;
1434
839k
    }
1435
1436
570k
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2, out_of_memory);
1437
570k
    if (output_pointer == NULL) {
1438
0
        return false;
1439
0
    }
1440
570k
    if (output_buffer->format) {
1441
570k
        size_t i;
1442
210M
        for (i = 0; i < (output_buffer->depth - 1); i++) {
1443
209M
            *output_pointer++ = '\t';
1444
209M
        }
1445
570k
    }
1446
570k
    *output_pointer++ = '}';
1447
570k
    *output_pointer = '\0';
1448
570k
    output_buffer->depth--;
1449
1450
570k
    return true;
1451
570k
}
1452
1453
/* Get Array size/item / object item. */
1454
26.0k
CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
1455
26.0k
    cJSON *child = NULL;
1456
26.0k
    size_t size = 0;
1457
1458
26.0k
    if (array == NULL) {
1459
0
        return 0;
1460
0
    }
1461
1462
26.0k
    child = array->child;
1463
1464
1.02M
    while (child != NULL) {
1465
1.00M
        size++;
1466
1.00M
        child = child->next;
1467
1.00M
    }
1468
1469
    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1470
1471
26.0k
    return (int)size;
1472
26.0k
}
1473
1474
0
static cJSON *get_array_item(const cJSON *array, size_t index) {
1475
0
    cJSON *current_child = NULL;
1476
1477
0
    if (array == NULL) {
1478
0
        return NULL;
1479
0
    }
1480
1481
0
    current_child = array->child;
1482
0
    while ((current_child != NULL) && (index > 0)) {
1483
0
        index--;
1484
0
        current_child = current_child->next;
1485
0
    }
1486
1487
0
    return current_child;
1488
0
}
1489
1490
0
CJSON_PUBLIC(cJSON *) loader_cJSON_GetArrayItem(const cJSON *array, int index) {
1491
0
    if (index < 0) {
1492
0
        return NULL;
1493
0
    }
1494
1495
0
    return get_array_item(array, (size_t)index);
1496
0
}
1497
1498
1.87M
static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
1499
1.87M
    cJSON *current_element = NULL;
1500
1501
1.87M
    if ((object == NULL) || (name == NULL)) {
1502
0
        return NULL;
1503
0
    }
1504
1505
1.87M
    current_element = object->child;
1506
1.87M
    if (case_sensitive) {
1507
0
        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) {
1508
0
            current_element = current_element->next;
1509
0
        }
1510
1.87M
    } else {
1511
6.37M
        while ((current_element != NULL) &&
1512
5.62M
               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
1513
4.49M
            current_element = current_element->next;
1514
4.49M
        }
1515
1.87M
    }
1516
1517
1.87M
    if ((current_element == NULL) || (current_element->string == NULL)) {
1518
751k
        return NULL;
1519
751k
    }
1520
1521
1.12M
    return current_element;
1522
1.87M
}
1523
1524
1.87M
CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
1525
1.87M
    return get_object_item(object, string, false);
1526
1.87M
}
1527
1528
0
CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string) {
1529
0
    return get_object_item(object, string, true);
1530
0
}
1531
1532
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_HasObjectItem(const cJSON *object, const char *string) {
1533
0
    return loader_cJSON_GetObjectItem(object, string) ? 1 : 0;
1534
0
}
1535
1536
0
static void skip_oneline_comment(char **input) {
1537
0
    *input += static_strlen("//");
1538
1539
0
    for (; (*input)[0] != '\0'; ++(*input)) {
1540
0
        if ((*input)[0] == '\n') {
1541
0
            *input += static_strlen("\n");
1542
0
            return;
1543
0
        }
1544
0
    }
1545
0
}
1546
1547
0
static void skip_multiline_comment(char **input) {
1548
0
    *input += static_strlen("/*");
1549
1550
0
    for (; (*input)[0] != '\0'; ++(*input)) {
1551
0
        if (((*input)[0] == '*') && ((*input)[1] == '/')) {
1552
0
            *input += static_strlen("*/");
1553
0
            return;
1554
0
        }
1555
0
    }
1556
0
}
1557
1558
0
static void minify_string(char **input, char **output) {
1559
0
    (*output)[0] = (*input)[0];
1560
0
    *input += static_strlen("\"");
1561
0
    *output += static_strlen("\"");
1562
1563
0
    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
1564
0
        (*output)[0] = (*input)[0];
1565
1566
0
        if ((*input)[0] == '\"') {
1567
0
            (*output)[0] = '\"';
1568
0
            *input += static_strlen("\"");
1569
0
            *output += static_strlen("\"");
1570
0
            return;
1571
0
        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
1572
0
            (*output)[1] = (*input)[1];
1573
0
            *input += static_strlen("\"");
1574
0
            *output += static_strlen("\"");
1575
0
        }
1576
0
    }
1577
0
}
1578
1579
0
CJSON_PUBLIC(void) loader_cJSON_Minify(char *json) {
1580
0
    char *into = json;
1581
1582
0
    if (json == NULL) {
1583
0
        return;
1584
0
    }
1585
1586
0
    while (json[0] != '\0') {
1587
0
        switch (json[0]) {
1588
0
            case ' ':
1589
0
            case '\t':
1590
0
            case '\r':
1591
0
            case '\n':
1592
0
                json++;
1593
0
                break;
1594
1595
0
            case '/':
1596
0
                if (json[1] == '/') {
1597
0
                    skip_oneline_comment(&json);
1598
0
                } else if (json[1] == '*') {
1599
0
                    skip_multiline_comment(&json);
1600
0
                } else {
1601
0
                    json++;
1602
0
                }
1603
0
                break;
1604
1605
0
            case '\"':
1606
0
                minify_string(&json, (char **)&into);
1607
0
                break;
1608
1609
0
            default:
1610
0
                into[0] = json[0];
1611
0
                json++;
1612
0
                into++;
1613
0
        }
1614
0
    }
1615
1616
    /* and null-terminate. */
1617
0
    *into = '\0';
1618
0
}
1619
1620
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsInvalid(const cJSON *const item) {
1621
0
    if (item == NULL) {
1622
0
        return false;
1623
0
    }
1624
1625
0
    return (item->type & 0xFF) == cJSON_Invalid;
1626
0
}
1627
1628
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsFalse(const cJSON *const item) {
1629
0
    if (item == NULL) {
1630
0
        return false;
1631
0
    }
1632
1633
0
    return (item->type & 0xFF) == cJSON_False;
1634
0
}
1635
1636
55
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsTrue(const cJSON *const item) {
1637
55
    if (item == NULL) {
1638
55
        return false;
1639
55
    }
1640
1641
0
    return (item->type & 0xff) == cJSON_True;
1642
55
}
1643
1644
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsBool(const cJSON *const item) {
1645
0
    if (item == NULL) {
1646
0
        return false;
1647
0
    }
1648
1649
0
    return (item->type & (cJSON_True | cJSON_False)) != 0;
1650
0
}
1651
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsNull(const cJSON *const item) {
1652
0
    if (item == NULL) {
1653
0
        return false;
1654
0
    }
1655
1656
0
    return (item->type & 0xFF) == cJSON_NULL;
1657
0
}
1658
1659
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsNumber(const cJSON *const item) {
1660
0
    if (item == NULL) {
1661
0
        return false;
1662
0
    }
1663
1664
0
    return (item->type & 0xFF) == cJSON_Number;
1665
0
}
1666
1667
663k
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
1668
663k
    if (item == NULL) {
1669
294k
        return false;
1670
294k
    }
1671
1672
368k
    return (item->type & 0xFF) == cJSON_String;
1673
663k
}
1674
1675
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsArray(const cJSON *const item) {
1676
0
    if (item == NULL) {
1677
0
        return false;
1678
0
    }
1679
1680
0
    return (item->type & 0xFF) == cJSON_Array;
1681
0
}
1682
1683
0
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) {
1684
0
    if (item == NULL) {
1685
0
        return false;
1686
0
    }
1687
1688
0
    return (item->type & 0xFF) == cJSON_Object;
1689
0
}
1690
1691
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsRaw(const cJSON *const item) {
1692
0
    if (item == NULL) {
1693
0
        return false;
1694
0
    }
1695
1696
0
    return (item->type & 0xFF) == cJSON_Raw;
1697
0
}
1698
1699
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) {
1700
0
    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) {
1701
0
        return false;
1702
0
    }
1703
1704
    /* check if type is valid */
1705
0
    switch (a->type & 0xFF) {
1706
0
        case cJSON_False:
1707
0
        case cJSON_True:
1708
0
        case cJSON_NULL:
1709
0
        case cJSON_Number:
1710
0
        case cJSON_String:
1711
0
        case cJSON_Raw:
1712
0
        case cJSON_Array:
1713
0
        case cJSON_Object:
1714
0
            break;
1715
1716
0
        default:
1717
0
            return false;
1718
0
    }
1719
1720
    /* identical objects are equal */
1721
0
    if (a == b) {
1722
0
        return true;
1723
0
    }
1724
1725
0
    switch (a->type & 0xFF) {
1726
        /* in these cases and equal type is enough */
1727
0
        case cJSON_False:
1728
0
        case cJSON_True:
1729
0
        case cJSON_NULL:
1730
0
            return true;
1731
1732
0
        case cJSON_Number:
1733
0
            if (compare_double(a->valuedouble, b->valuedouble)) {
1734
0
                return true;
1735
0
            }
1736
0
            return false;
1737
1738
0
        case cJSON_String:
1739
0
        case cJSON_Raw:
1740
0
            if ((a->valuestring == NULL) || (b->valuestring == NULL)) {
1741
0
                return false;
1742
0
            }
1743
0
            if (strcmp(a->valuestring, b->valuestring) == 0) {
1744
0
                return true;
1745
0
            }
1746
1747
0
            return false;
1748
1749
0
        case cJSON_Array: {
1750
0
            cJSON *a_element = a->child;
1751
0
            cJSON *b_element = b->child;
1752
1753
0
            for (; (a_element != NULL) && (b_element != NULL);) {
1754
0
                if (!loader_cJSON_Compare(a_element, b_element, case_sensitive)) {
1755
0
                    return false;
1756
0
                }
1757
1758
0
                a_element = a_element->next;
1759
0
                b_element = b_element->next;
1760
0
            }
1761
1762
            /* one of the arrays is longer than the other */
1763
0
            if (a_element != b_element) {
1764
0
                return false;
1765
0
            }
1766
1767
0
            return true;
1768
0
        }
1769
1770
0
        case cJSON_Object: {
1771
0
            cJSON *a_element = NULL;
1772
0
            cJSON *b_element = NULL;
1773
0
            cJSON_ArrayForEach(a_element, a) {
1774
                /* TODO This has O(n^2) runtime, which is horrible! */
1775
0
                b_element = get_object_item(b, a_element->string, case_sensitive);
1776
0
                if (b_element == NULL) {
1777
0
                    return false;
1778
0
                }
1779
1780
0
                if (!loader_cJSON_Compare(a_element, b_element, case_sensitive)) {
1781
0
                    return false;
1782
0
                }
1783
0
            }
1784
1785
            /* doing this twice, once on a and b to prevent true comparison if a subset of b
1786
             * TODO: Do this the proper way, this is just a fix for now */
1787
0
            cJSON_ArrayForEach(b_element, b) {
1788
0
                a_element = get_object_item(a, b_element->string, case_sensitive);
1789
0
                if (a_element == NULL) {
1790
0
                    return false;
1791
0
                }
1792
1793
0
                if (!loader_cJSON_Compare(b_element, a_element, case_sensitive)) {
1794
0
                    return false;
1795
0
                }
1796
0
            }
1797
1798
0
            return true;
1799
0
        }
1800
1801
0
        default:
1802
0
            return false;
1803
0
    }
1804
0
}