Coverage Report

Created: 2026-07-16 07:05

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
68.2M
#define true ((cJSON_bool)1)
68
69
#ifdef false
70
#undef false
71
#endif
72
10.9M
#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
2.74M
CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
99
2.74M
    if (!loader_cJSON_IsString(item)) {
100
1.19M
        return NULL;
101
1.19M
    }
102
103
1.54M
    return item->valuestring;
104
2.74M
}
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
22.1M
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
121
22.1M
    if ((string1 == NULL) || (string2 == NULL)) {
122
877
        return 1;
123
877
    }
124
125
22.1M
    if (string1 == string2) {
126
0
        return 0;
127
0
    }
128
129
54.1M
    for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) {
130
36.9M
        if (*string1 == '\0') {
131
4.97M
            return 0;
132
4.97M
        }
133
36.9M
    }
134
135
17.2M
    return tolower(*string1) - tolower(*string2);
136
22.1M
}
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
33.4M
static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
143
33.4M
    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
144
33.4M
    if (NULL != node) {
145
33.4M
        node->pAllocator = pAllocator;
146
33.4M
    }
147
33.4M
    return node;
148
33.4M
}
149
150
/* Delete a cJSON structure. */
151
8.04M
TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
152
8.04M
    cJSON *next = NULL;
153
41.4M
    while (item != NULL) {
154
33.4M
        next = item->next;
155
33.4M
        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
156
7.47M
            loader_cJSON_Delete(item->child);
157
7.47M
        }
158
33.4M
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
159
10.8M
            loader_free(item->pAllocator, item->valuestring);
160
10.8M
            item->valuestring = NULL;
161
10.8M
        }
162
33.4M
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
163
13.0M
            loader_free(item->pAllocator, item->string);
164
13.0M
            item->string = NULL;
165
13.0M
        }
166
33.4M
        loader_free(item->pAllocator, item);
167
33.4M
        item = next;
168
33.4M
    }
169
8.04M
}
170
171
/* get the decimal point character of the current locale */
172
10.3M
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
10.3M
    return '.';
178
10.3M
#endif
179
10.3M
}
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
200M
#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
765M
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
193
192M
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
194
/* get a pointer to the buffer at the position */
195
621M
#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
8.26M
static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
199
8.26M
    double number = 0;
200
8.26M
    unsigned char *after_end = NULL;
201
8.26M
    unsigned char number_c_string[64];
202
8.26M
    unsigned char decimal_point = get_decimal_point();
203
8.26M
    size_t i = 0;
204
205
8.26M
    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
35.5M
    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
213
35.5M
        switch (buffer_at_offset(input_buffer)[i]) {
214
3.08M
            case '0':
215
6.48M
            case '1':
216
8.50M
            case '2':
217
10.9M
            case '3':
218
13.3M
            case '4':
219
14.3M
            case '5':
220
18.6M
            case '6':
221
21.6M
            case '7':
222
23.5M
            case '8':
223
26.0M
            case '9':
224
26.0M
            case '+':
225
26.4M
            case '-':
226
27.1M
            case 'e':
227
27.1M
            case 'E':
228
27.1M
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
229
27.1M
                break;
230
231
152k
            case '.':
232
152k
                number_c_string[i] = decimal_point;
233
152k
                break;
234
235
8.25M
            default:
236
8.25M
                goto loop_end;
237
35.5M
        }
238
35.5M
    }
239
8.26M
loop_end:
240
8.26M
    number_c_string[i] = '\0';
241
242
8.26M
    number = strtod((const char *)number_c_string, (char **)&after_end);
243
8.26M
    if (number_c_string == after_end) {
244
330
        return false; /* parse_error */
245
330
    }
246
247
8.26M
    item->valuedouble = number;
248
249
    /* use saturation in case of overflow */
250
8.26M
    if (number >= INT_MAX) {
251
472k
        item->valueint = INT_MAX;
252
7.78M
    } else if (number <= (double)INT_MIN) {
253
280k
        item->valueint = INT_MIN;
254
7.50M
    } else {
255
7.50M
        item->valueint = (int)number;
256
7.50M
    }
257
258
8.26M
    item->type = cJSON_Number;
259
260
8.26M
    input_buffer->offset += (size_t)(after_end - number_c_string);
261
8.26M
    return true;
262
8.26M
}
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
39.0M
static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
276
39.0M
    unsigned char *newbuffer = NULL;
277
39.0M
    size_t newsize = 0;
278
279
39.0M
    if ((p == NULL) || (p->buffer == NULL)) {
280
0
        return NULL;
281
0
    }
282
283
39.0M
    if ((p->length > 0) && (p->offset >= p->length)) {
284
        /* make sure that offset is valid */
285
0
        return NULL;
286
0
    }
287
288
39.0M
    if (needed > INT_MAX) {
289
        /* sizes bigger than INT_MAX are currently not supported */
290
0
        return NULL;
291
0
    }
292
293
39.0M
    needed += p->offset + 1;
294
39.0M
    if (needed <= p->length) {
295
39.0M
        return p->buffer + p->offset;
296
39.0M
    }
297
298
29.6k
    if (p->noalloc) {
299
3.77k
        return NULL;
300
3.77k
    }
301
302
    /* calculate new buffer size */
303
25.8k
    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
25.8k
    } else {
311
25.8k
        newsize = needed * 2;
312
25.8k
    }
313
314
25.8k
    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
315
25.8k
    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
25.8k
    p->length = newsize;
325
25.8k
    p->buffer = newbuffer;
326
327
25.8k
    return newbuffer + p->offset;
328
25.8k
}
329
330
/* calculate the new length of the string in a printbuffer and update the offset */
331
15.7M
static void update_offset(printbuffer *const buffer) {
332
15.7M
    const unsigned char *buffer_pointer = NULL;
333
15.7M
    if ((buffer == NULL) || (buffer->buffer == NULL)) {
334
0
        return;
335
0
    }
336
15.7M
    buffer_pointer = buffer->buffer + buffer->offset;
337
338
15.7M
    buffer->offset += strlen((const char *)buffer_pointer);
339
15.7M
}
340
341
/* securely comparison of floating-point variables */
342
80.7k
static cJSON_bool compare_double(double a, double b) {
343
80.7k
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
344
80.7k
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
345
80.7k
}
346
347
/* Render the number nicely from the given item into a string. */
348
2.11M
static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
349
2.11M
    unsigned char *output_pointer = NULL;
350
2.11M
    double d = item->valuedouble;
351
2.11M
    int length = 0;
352
2.11M
    size_t i = 0;
353
2.11M
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
354
2.11M
    unsigned char decimal_point = get_decimal_point();
355
2.11M
    double test = 0.0;
356
357
2.11M
    if (output_buffer == NULL) {
358
0
        return false;
359
0
    }
360
361
    /* This checks for NaN and Infinity */
362
2.11M
    if (isnan(d) || isinf(d)) {
363
1.66k
        length = snprintf((char *)number_buffer, 26, "null");
364
2.11M
    } else if (d == (double)item->valueint) {
365
2.03M
        length = snprintf((char *)number_buffer, 26, "%d", item->valueint);
366
2.03M
    } else {
367
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
368
80.7k
        length = snprintf((char *)number_buffer, 26, "%1.15g", d);
369
370
        /* Check whether the original double can be recovered */
371
80.7k
        if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) {
372
            /* If not, print with 17 decimal places of precision */
373
8.66k
            length = snprintf((char *)number_buffer, 26, "%1.17g", d);
374
8.66k
        }
375
80.7k
    }
376
377
    /* snprintf failed or buffer overrun occurred */
378
2.11M
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
379
0
        return false;
380
0
    }
381
382
    /* reserve appropriate space in the output */
383
2.11M
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""), out_of_memory);
384
2.11M
    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
4.87M
    for (i = 0; i < ((size_t)length); i++) {
391
2.75M
        if (number_buffer[i] == decimal_point) {
392
16.6k
            output_pointer[i] = '.';
393
16.6k
            continue;
394
16.6k
        }
395
396
2.74M
        output_pointer[i] = number_buffer[i];
397
2.74M
    }
398
2.11M
    output_pointer[i] = '\0';
399
400
2.11M
    output_buffer->offset += (size_t)length;
401
402
2.11M
    return true;
403
2.11M
}
404
405
/* parse 4 digit hexadecimal number */
406
2.23M
static unsigned parse_hex4(const unsigned char *const input) {
407
2.23M
    unsigned int h = 0;
408
2.23M
    size_t i = 0;
409
410
9.43M
    for (i = 0; i < 4; i++) {
411
        /* parse digit */
412
7.84M
        if ((input[i] >= '0') && (input[i] <= '9')) {
413
4.76M
            h += (unsigned int)input[i] - '0';
414
4.76M
        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
415
582k
            h += (unsigned int)10 + input[i] - 'A';
416
2.49M
        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
417
1.85M
            h += (unsigned int)10 + input[i] - 'a';
418
1.85M
        } else /* invalid */
419
643k
        {
420
643k
            return 0;
421
643k
        }
422
423
7.20M
        if (i < 3) {
424
            /* shift left to make place for the next nibble */
425
5.61M
            h = h << 4;
426
5.61M
        }
427
7.20M
    }
428
429
1.58M
    return h;
430
2.23M
}
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
2.21M
                                           unsigned char **output_pointer) {
436
2.21M
    long unsigned int codepoint = 0;
437
2.21M
    unsigned int first_code = 0;
438
2.21M
    const unsigned char *first_sequence = input_pointer;
439
2.21M
    unsigned char utf8_length = 0;
440
2.21M
    unsigned char utf8_position = 0;
441
2.21M
    unsigned char sequence_length = 0;
442
2.21M
    unsigned char first_byte_mark = 0;
443
444
2.21M
    if ((input_end - first_sequence) < 6) {
445
        /* input ends unexpectedly */
446
158
        goto fail;
447
158
    }
448
449
    /* get the first utf16 sequence */
450
2.21M
    first_code = parse_hex4(first_sequence + 2);
451
452
    /* check that the code is valid */
453
2.21M
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
454
195
        goto fail;
455
195
    }
456
457
    /* UTF16 surrogate pair */
458
2.21M
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
459
17.7k
        const unsigned char *second_sequence = first_sequence + 6;
460
17.7k
        unsigned int second_code = 0;
461
17.7k
        sequence_length = 12; /* \uXXXX\uXXXX */
462
463
17.7k
        if ((input_end - second_sequence) < 6) {
464
            /* input ends unexpectedly */
465
171
            goto fail;
466
171
        }
467
468
17.5k
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
469
            /* missing second half of the surrogate pair */
470
323
            goto fail;
471
323
        }
472
473
        /* get the second utf16 sequence */
474
17.2k
        second_code = parse_hex4(second_sequence + 2);
475
        /* check that the code is valid */
476
17.2k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
477
            /* invalid second half of the surrogate pair */
478
485
            goto fail;
479
485
        }
480
481
        /* calculate the unicode codepoint from the surrogate pair */
482
16.7k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
483
2.19M
    } else {
484
2.19M
        sequence_length = 6; /* \uXXXX */
485
2.19M
        codepoint = first_code;
486
2.19M
    }
487
488
    /* encode as UTF-8
489
     * takes at maximum 4 bytes to encode:
490
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
491
2.21M
    if (codepoint < 0x80) {
492
        /* normal ascii, encoding 0xxxxxxx */
493
659k
        utf8_length = 1;
494
1.55M
    } else if (codepoint < 0x800) {
495
        /* two bytes, encoding 110xxxxx 10xxxxxx */
496
274k
        utf8_length = 2;
497
274k
        first_byte_mark = 0xC0; /* 11000000 */
498
1.28M
    } else if (codepoint < 0x10000) {
499
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
500
1.26M
        utf8_length = 3;
501
1.26M
        first_byte_mark = 0xE0; /* 11100000 */
502
1.26M
    } else if (codepoint <= 0x10FFFF) {
503
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
504
16.7k
        utf8_length = 4;
505
16.7k
        first_byte_mark = 0xF0; /* 11110000 */
506
16.7k
    } else {
507
        /* invalid unicode codepoint */
508
0
        goto fail;
509
0
    }
510
511
    /* encode as utf8 */
512
5.06M
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
513
        /* 10xxxxxx */
514
2.85M
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
515
2.85M
        codepoint >>= 6;
516
2.85M
    }
517
    /* encode first byte */
518
2.21M
    if (utf8_length > 1) {
519
1.55M
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
520
1.55M
    } else {
521
659k
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
522
659k
    }
523
524
2.21M
    *output_pointer += utf8_length;
525
526
2.21M
    return sequence_length;
527
528
1.33k
fail:
529
1.33k
    return 0;
530
2.21M
}
531
532
/* Parse the input text into an unescaped cinput, and populate item. */
533
23.9M
static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
534
23.9M
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
535
23.9M
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
536
23.9M
    unsigned char *output_pointer = NULL;
537
23.9M
    unsigned char *output = NULL;
538
539
    /* not a string */
540
23.9M
    if (buffer_at_offset(input_buffer)[0] != '\"') {
541
1.32k
        goto fail;
542
1.32k
    }
543
544
23.9M
    {
545
        /* calculate approximate size of the output (overestimate) */
546
23.9M
        size_t allocation_length = 0;
547
23.9M
        size_t skipped_bytes = 0;
548
676M
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
549
            /* is escape sequence */
550
652M
            if (input_end[0] == '\\') {
551
3.78M
                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
3.78M
                skipped_bytes++;
556
3.78M
                input_end++;
557
3.78M
            }
558
652M
            input_end++;
559
652M
        }
560
23.9M
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
561
873
            goto fail; /* string ended unexpectedly */
562
873
        }
563
564
        /* This is at most how much we need for the output */
565
23.9M
        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
566
23.9M
        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
567
23.9M
                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
568
23.9M
        if (output == NULL) {
569
0
            *out_of_memory = true;
570
0
            goto fail; /* allocation failure */
571
0
        }
572
23.9M
    }
573
574
23.9M
    output_pointer = output;
575
    /* loop through the string literal */
576
580M
    while (input_pointer < input_end) {
577
556M
        if (*input_pointer != '\\') {
578
553M
            *output_pointer++ = *input_pointer++;
579
553M
        }
580
        /* escape sequence */
581
2.57M
        else {
582
2.57M
            unsigned char sequence_length = 2;
583
2.57M
            if ((input_end - input_pointer) < 1) {
584
0
                goto fail;
585
0
            }
586
587
2.57M
            switch (input_pointer[1]) {
588
75.9k
                case 'b':
589
75.9k
                    *output_pointer++ = '\b';
590
75.9k
                    break;
591
26.9k
                case 'f':
592
26.9k
                    *output_pointer++ = '\f';
593
26.9k
                    break;
594
9.43k
                case 'n':
595
9.43k
                    *output_pointer++ = '\n';
596
9.43k
                    break;
597
146k
                case 'r':
598
146k
                    *output_pointer++ = '\r';
599
146k
                    break;
600
38.5k
                case 't':
601
38.5k
                    *output_pointer++ = '\t';
602
38.5k
                    break;
603
8.03k
                case '\"':
604
49.7k
                case '\\':
605
56.5k
                case '/':
606
56.5k
                    *output_pointer++ = input_pointer[1];
607
56.5k
                    break;
608
609
                /* UTF-16 literal */
610
2.21M
                case 'u':
611
2.21M
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
612
2.21M
                    if (sequence_length == 0) {
613
                        /* failed to convert UTF16-literal to UTF-8 */
614
1.33k
                        goto fail;
615
1.33k
                    }
616
2.21M
                    break;
617
618
2.21M
                default:
619
256
                    goto fail;
620
2.57M
            }
621
2.56M
            input_pointer += sequence_length;
622
2.56M
        }
623
556M
    }
624
625
    /* zero terminate the output */
626
23.9M
    *output_pointer = '\0';
627
628
23.9M
    item->type = cJSON_String;
629
23.9M
    item->valuestring = (char *)output;
630
631
23.9M
    input_buffer->offset = (size_t)(input_end - input_buffer->content);
632
23.9M
    input_buffer->offset++;
633
634
23.9M
    return true;
635
636
3.78k
fail:
637
3.78k
    if (output != NULL) {
638
1.58k
        loader_free(input_buffer->pAllocator, output);
639
1.58k
        output = NULL;
640
1.58k
    }
641
642
3.78k
    if (input_pointer != NULL) {
643
3.78k
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
644
3.78k
    }
645
646
3.78k
    return false;
647
23.9M
}
648
649
/* Render the cstring provided to an escaped version that can be printed. */
650
7.63M
static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
651
7.63M
    const unsigned char *input_pointer = NULL;
652
7.63M
    unsigned char *output = NULL;
653
7.63M
    unsigned char *output_pointer = NULL;
654
7.63M
    size_t output_length = 0;
655
    /* numbers of additional characters needed for escaping */
656
7.63M
    size_t escape_characters = 0;
657
658
7.63M
    if (output_buffer == NULL) {
659
0
        return false;
660
0
    }
661
662
    /* empty string */
663
7.63M
    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
141M
    for (input_pointer = input; *input_pointer; input_pointer++) {
674
133M
        switch (*input_pointer) {
675
1.90k
            case '\"':
676
20.3k
            case '\\':
677
92.5k
            case '\b':
678
163k
            case '\f':
679
287k
            case '\n':
680
385k
            case '\r':
681
406k
            case '\t':
682
                /* one character escape sequence */
683
406k
                escape_characters++;
684
406k
                break;
685
133M
            default:
686
133M
                if (*input_pointer < 32) {
687
                    /* UTF-16 escape sequence uXXXX */
688
85.8M
                    escape_characters += 5;
689
85.8M
                }
690
133M
                break;
691
133M
        }
692
133M
    }
693
7.63M
    output_length = (size_t)(input_pointer - input) + escape_characters;
694
695
7.63M
    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
696
7.63M
    if (output == NULL) {
697
3.77k
        return false;
698
3.77k
    }
699
700
    /* no characters have to be escaped */
701
7.63M
    if (escape_characters == 0) {
702
7.34M
        memcpy(output, input, output_length);
703
7.34M
        output[output_length] = '\0';
704
705
7.34M
        return true;
706
7.34M
    }
707
708
285k
    output_pointer = output;
709
    /* copy the string */
710
102M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
711
102M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
712
            /* normal character, copy */
713
17.3M
            *output_pointer = *input_pointer;
714
85.0M
        } 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
85.0M
            switch (*input_pointer) {
721
18.4k
                case '\\':
722
18.4k
                    *output_pointer = '\\';
723
18.4k
                    break;
724
1.90k
                case '\"':
725
1.90k
                    *output_pointer = '\"';
726
1.90k
                    break;
727
72.2k
                case '\b':
728
72.2k
                    *output_pointer = '\b';
729
72.2k
                    break;
730
71.2k
                case '\f':
731
71.2k
                    *output_pointer = '\f';
732
71.2k
                    break;
733
116k
                case '\n':
734
116k
                    *output_pointer = '\n';
735
116k
                    break;
736
97.7k
                case '\r':
737
97.7k
                    *output_pointer = '\r';
738
97.7k
                    break;
739
20.2k
                case '\t':
740
20.2k
                    *output_pointer = '\t';
741
20.2k
                    break;
742
84.6M
                default:
743
                    /* escape and print as unicode codepoint */
744
84.6M
                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
745
84.6M
                    output_pointer += 4;
746
84.6M
                    break;
747
85.0M
            }
748
85.0M
        }
749
102M
    }
750
285k
    output[output_length] = '\0';
751
752
285k
    return true;
753
285k
}
754
755
/* Invoke print_string_ptr (which is useful) on an item. */
756
5.10M
static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
757
5.10M
    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
758
5.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
106M
static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
770
106M
    if ((buffer == NULL) || (buffer->content == NULL)) {
771
0
        return NULL;
772
0
    }
773
774
106M
    if (cannot_access_at_index(buffer, 0)) {
775
0
        return buffer;
776
0
    }
777
778
156M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
779
50.6M
        buffer->offset++;
780
50.6M
    }
781
782
106M
    if (buffer->offset == buffer->length) {
783
20.8k
        buffer->offset--;
784
20.8k
    }
785
786
106M
    return buffer;
787
106M
}
788
789
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
790
102k
static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
791
102k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
792
0
        return NULL;
793
0
    }
794
795
102k
    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
796
955
        buffer->offset += 3;
797
955
    }
798
799
102k
    return buffer;
800
102k
}
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
102k
                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
822
102k
    parse_buffer buffer = {0, 0, 0, 0, 0};
823
102k
    cJSON *item = NULL;
824
825
    /* reset error position */
826
    // global_error.json = NULL;
827
    // global_error.position = 0;
828
829
102k
    if (value == NULL || 0 == buffer_length) {
830
0
        goto fail;
831
0
    }
832
833
102k
    buffer.content = (const unsigned char *)value;
834
102k
    buffer.length = buffer_length;
835
102k
    buffer.offset = 0;
836
102k
    buffer.pAllocator = pAllocator;
837
838
102k
    item = cJSON_New_Item(pAllocator);
839
102k
    if (item == NULL) /* memory fail */
840
0
    {
841
0
        *out_of_memory = true;
842
0
        goto fail;
843
0
    }
844
845
102k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
846
        /* parse failure. ep is set. */
847
34.9k
        goto fail;
848
34.9k
    }
849
850
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
851
67.3k
    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
67.3k
    if (return_parse_end) {
858
0
        *return_parse_end = (const char *)buffer_at_offset(&buffer);
859
0
    }
860
861
67.3k
    return item;
862
863
34.9k
fail:
864
34.9k
    if (item != NULL) {
865
34.9k
        loader_cJSON_Delete(item);
866
34.9k
    }
867
868
34.9k
    if (value != NULL) {
869
34.9k
        error local_error;
870
34.9k
        local_error.json = (const unsigned char *)value;
871
34.9k
        local_error.position = 0;
872
873
34.9k
        if (buffer.offset < buffer.length) {
874
33.9k
            local_error.position = buffer.offset;
875
33.9k
        } else if (buffer.length > 0) {
876
1.07k
            local_error.position = buffer.length - 1;
877
1.07k
        }
878
879
34.9k
        if (return_parse_end != NULL) {
880
0
            *return_parse_end = (const char *)local_error.json + local_error.position;
881
0
        }
882
883
        // global_error = local_error;
884
34.9k
    }
885
886
34.9k
    return NULL;
887
67.3k
}
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
102k
                             bool *out_of_memory) {
897
102k
    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
898
102k
}
899
900
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
901
902
3.50M
static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
903
3.50M
    static const size_t default_buffer_size = 256;
904
3.50M
    printbuffer buffer[1];
905
3.50M
    unsigned char *printed = NULL;
906
907
3.50M
    memset(buffer, 0, sizeof(buffer));
908
909
    /* create buffer */
910
3.50M
    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
911
3.50M
    buffer->length = default_buffer_size;
912
3.50M
    buffer->format = format;
913
3.50M
    buffer->pAllocator = item->pAllocator;
914
3.50M
    if (buffer->buffer == NULL) {
915
0
        *out_of_memory = true;
916
0
        goto fail;
917
0
    }
918
919
    /* print the value */
920
3.50M
    if (!print_value(item, buffer, out_of_memory)) {
921
0
        goto fail;
922
0
    }
923
3.50M
    update_offset(buffer);
924
925
3.50M
    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
926
3.50M
                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
927
3.50M
    if (printed == NULL) {
928
0
        *out_of_memory = true;
929
0
        goto fail;
930
0
    }
931
3.50M
    buffer->buffer = NULL;
932
933
3.50M
    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
3.50M
}
948
949
/* Render a cJSON item/entity/structure to text. */
950
3.50M
TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
951
3.50M
    return (char *)print(item, true, out_of_memory);
952
3.50M
}
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
1.50M
loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
988
1.50M
    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
989
990
1.50M
    if ((length < 0) || (buffer == NULL)) {
991
0
        return false;
992
0
    }
993
994
1.50M
    p.buffer = (unsigned char *)buffer;
995
1.50M
    p.length = (size_t)length;
996
1.50M
    p.offset = 0;
997
1.50M
    p.noalloc = true;
998
1.50M
    p.format = format;
999
1.50M
    p.pAllocator = item->pAllocator;
1000
1.50M
    bool out_of_memory = false;
1001
1.50M
    return print_value(item, &p, &out_of_memory);
1002
1.50M
}
1003
1004
/* Parser core - when encountering text, process appropriately. */
1005
33.4M
static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1006
33.4M
    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
33.4M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
1013
21.7k
        item->type = cJSON_NULL;
1014
21.7k
        input_buffer->offset += 4;
1015
21.7k
        return true;
1016
21.7k
    }
1017
    /* false */
1018
33.3M
    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
1019
21.6k
        item->type = cJSON_False;
1020
21.6k
        input_buffer->offset += 5;
1021
21.6k
        return true;
1022
21.6k
    }
1023
    /* true */
1024
33.3M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
1025
295k
        item->type = cJSON_True;
1026
295k
        item->valueint = 1;
1027
295k
        input_buffer->offset += 4;
1028
295k
        return true;
1029
295k
    }
1030
    /* string */
1031
33.0M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
1032
10.8M
        return parse_string(item, input_buffer, out_of_memory);
1033
10.8M
    }
1034
    /* number */
1035
22.1M
    if (can_access_at_index(input_buffer, 0) &&
1036
22.1M
        ((buffer_at_offset(input_buffer)[0] == '-') ||
1037
21.8M
         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
1038
8.26M
        return parse_number(item, input_buffer);
1039
8.26M
    }
1040
    /* array */
1041
13.9M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
1042
1.80M
        return parse_array(item, input_buffer, out_of_memory);
1043
1.80M
    }
1044
    /* object */
1045
12.1M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
1046
12.1M
        return parse_object(item, input_buffer, out_of_memory);
1047
12.1M
    }
1048
1049
28.2k
    return false;
1050
12.1M
}
1051
1052
/* Render a value to text. */
1053
14.7M
static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1054
14.7M
    unsigned char *output = NULL;
1055
1056
14.7M
    if ((item == NULL) || (output_buffer == NULL)) {
1057
0
        return false;
1058
0
    }
1059
1060
14.7M
    switch ((item->type) & 0xFF) {
1061
7.63k
        case cJSON_NULL:
1062
7.63k
            output = ensure(output_buffer, 5, out_of_memory);
1063
7.63k
            if (output == NULL) {
1064
0
                return false;
1065
0
            }
1066
7.63k
            strcpy((char *)output, "null");
1067
7.63k
            return true;
1068
1069
6.01k
        case cJSON_False:
1070
6.01k
            output = ensure(output_buffer, 6, out_of_memory);
1071
6.01k
            if (output == NULL) {
1072
0
                return false;
1073
0
            }
1074
6.01k
            strcpy((char *)output, "false");
1075
6.01k
            return true;
1076
1077
54.7k
        case cJSON_True:
1078
54.7k
            output = ensure(output_buffer, 5, out_of_memory);
1079
54.7k
            if (output == NULL) {
1080
0
                return false;
1081
0
            }
1082
54.7k
            strcpy((char *)output, "true");
1083
54.7k
            return true;
1084
1085
2.11M
        case cJSON_Number:
1086
2.11M
            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
5.10M
        case cJSON_String:
1104
5.10M
            return print_string(item, output_buffer, out_of_memory);
1105
1106
565k
        case cJSON_Array:
1107
565k
            return print_array(item, output_buffer, out_of_memory);
1108
1109
6.90M
        case cJSON_Object:
1110
6.90M
            return print_object(item, output_buffer, out_of_memory);
1111
1112
0
        default:
1113
0
            return false;
1114
14.7M
    }
1115
14.7M
}
1116
1117
/* Build an array from input text. */
1118
1.80M
static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1119
1.80M
    cJSON *head = NULL; /* head of the linked list */
1120
1.80M
    cJSON *current_item = NULL;
1121
1122
1.80M
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1123
56
        return false; /* to deeply nested */
1124
56
    }
1125
1.80M
    input_buffer->depth++;
1126
1127
1.80M
    if (buffer_at_offset(input_buffer)[0] != '[') {
1128
        /* not an array */
1129
0
        goto fail;
1130
0
    }
1131
1132
1.80M
    input_buffer->offset++;
1133
1.80M
    buffer_skip_whitespace(input_buffer);
1134
1.80M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
1135
        /* empty array */
1136
114k
        goto success;
1137
114k
    }
1138
1139
    /* check if we skipped to the end of the buffer */
1140
1.68M
    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
1.68M
    input_buffer->offset--;
1147
    /* loop through the comma separated array elements */
1148
20.2M
    do {
1149
        /* allocate next item */
1150
20.2M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1151
20.2M
        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
20.2M
        if (head == NULL) {
1158
            /* start the linked list */
1159
1.68M
            current_item = head = new_item;
1160
18.5M
        } else {
1161
            /* add to the end and advance */
1162
18.5M
            current_item->next = new_item;
1163
18.5M
            new_item->prev = current_item;
1164
18.5M
            current_item = new_item;
1165
18.5M
        }
1166
1167
        /* parse next value */
1168
20.2M
        input_buffer->offset++;
1169
20.2M
        buffer_skip_whitespace(input_buffer);
1170
20.2M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1171
420k
            goto fail; /* failed to parse value */
1172
420k
        }
1173
19.8M
        buffer_skip_whitespace(input_buffer);
1174
19.8M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1175
1176
1.26M
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
1177
1.85k
        goto fail; /* expected end of array */
1178
1.85k
    }
1179
1180
1.38M
success:
1181
1.38M
    input_buffer->depth--;
1182
1183
1.38M
    if (head != NULL) {
1184
1.26M
        head->prev = current_item;
1185
1.26M
    }
1186
1187
1.38M
    item->type = cJSON_Array;
1188
1.38M
    item->child = head;
1189
1190
1.38M
    input_buffer->offset++;
1191
1192
1.38M
    return true;
1193
1194
422k
fail:
1195
422k
    if (head != NULL) {
1196
422k
        loader_cJSON_Delete(head);
1197
422k
    }
1198
1199
422k
    return false;
1200
1.26M
}
1201
1202
/* Render an array to text */
1203
565k
static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1204
565k
    unsigned char *output_pointer = NULL;
1205
565k
    size_t length = 0;
1206
565k
    cJSON *current_element = item->child;
1207
1208
565k
    if (output_buffer == NULL) {
1209
0
        return false;
1210
0
    }
1211
1212
    /* Compose the output array. */
1213
    /* opening square bracket */
1214
565k
    output_pointer = ensure(output_buffer, 1, out_of_memory);
1215
565k
    if (output_pointer == NULL) {
1216
0
        return false;
1217
0
    }
1218
1219
565k
    *output_pointer = '[';
1220
565k
    output_buffer->offset++;
1221
565k
    output_buffer->depth++;
1222
1223
7.77M
    while (current_element != NULL) {
1224
7.21M
        if (!print_value(current_element, output_buffer, out_of_memory)) {
1225
0
            return false;
1226
0
        }
1227
7.21M
        update_offset(output_buffer);
1228
7.21M
        if (current_element->next) {
1229
6.66M
            length = (size_t)(output_buffer->format ? 2 : 1);
1230
6.66M
            output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1231
6.66M
            if (output_pointer == NULL) {
1232
0
                return false;
1233
0
            }
1234
6.66M
            *output_pointer++ = ',';
1235
6.66M
            if (output_buffer->format) {
1236
6.66M
                *output_pointer++ = ' ';
1237
6.66M
            }
1238
6.66M
            *output_pointer = '\0';
1239
6.66M
            output_buffer->offset += length;
1240
6.66M
        }
1241
7.21M
        current_element = current_element->next;
1242
7.21M
    }
1243
1244
565k
    output_pointer = ensure(output_buffer, 2, out_of_memory);
1245
565k
    if (output_pointer == NULL) {
1246
0
        return false;
1247
0
    }
1248
565k
    *output_pointer++ = ']';
1249
565k
    *output_pointer = '\0';
1250
565k
    output_buffer->depth--;
1251
1252
565k
    return true;
1253
565k
}
1254
1255
/* Build an object from the text. */
1256
12.1M
static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1257
12.1M
    cJSON *head = NULL; /* linked list head */
1258
12.1M
    cJSON *current_item = NULL;
1259
1260
12.1M
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1261
38
        return false; /* to deeply nested */
1262
38
    }
1263
12.1M
    input_buffer->depth++;
1264
1265
12.1M
    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
12.1M
    input_buffer->offset++;
1270
12.1M
    buffer_skip_whitespace(input_buffer);
1271
12.1M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
1272
5.85M
        goto success; /* empty object */
1273
5.85M
    }
1274
1275
    /* check if we skipped to the end of the buffer */
1276
6.25M
    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
6.25M
    input_buffer->offset--;
1283
    /* loop through the comma separated array elements */
1284
13.0M
    do {
1285
        /* allocate next item */
1286
13.0M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1287
13.0M
        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
13.0M
        if (head == NULL) {
1294
            /* start the linked list */
1295
6.25M
            current_item = head = new_item;
1296
6.78M
        } else {
1297
            /* add to the end and advance */
1298
6.78M
            current_item->next = new_item;
1299
6.78M
            new_item->prev = current_item;
1300
6.78M
            current_item = new_item;
1301
6.78M
        }
1302
1303
13.0M
        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
13.0M
        input_buffer->offset++;
1309
13.0M
        buffer_skip_whitespace(input_buffer);
1310
13.0M
        if (!parse_string(current_item, input_buffer, out_of_memory)) {
1311
1.73k
            goto fail; /* failed to parse name */
1312
1.73k
        }
1313
13.0M
        buffer_skip_whitespace(input_buffer);
1314
1315
        /* swap valuestring and string, because we parsed the name */
1316
13.0M
        current_item->string = current_item->valuestring;
1317
13.0M
        current_item->valuestring = NULL;
1318
1319
13.0M
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
1320
372
            goto fail; /* invalid object */
1321
372
        }
1322
1323
        /* parse the value */
1324
13.0M
        input_buffer->offset++;
1325
13.0M
        buffer_skip_whitespace(input_buffer);
1326
13.0M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1327
42.9k
            goto fail; /* failed to parse value */
1328
42.9k
        }
1329
12.9M
        buffer_skip_whitespace(input_buffer);
1330
12.9M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1331
1332
6.20M
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
1333
332
        goto fail; /* expected end of object */
1334
332
    }
1335
1336
12.0M
success:
1337
12.0M
    input_buffer->depth--;
1338
1339
12.0M
    if (head != NULL) {
1340
6.20M
        head->prev = current_item;
1341
6.20M
    }
1342
1343
12.0M
    item->type = cJSON_Object;
1344
12.0M
    item->child = head;
1345
1346
12.0M
    input_buffer->offset++;
1347
12.0M
    return true;
1348
1349
45.3k
fail:
1350
45.3k
    if (head != NULL) {
1351
45.3k
        loader_cJSON_Delete(head);
1352
45.3k
    }
1353
1354
45.3k
    return false;
1355
6.20M
}
1356
1357
/* Render an object to text. */
1358
6.90M
static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1359
6.90M
    unsigned char *output_pointer = NULL;
1360
6.90M
    size_t length = 0;
1361
6.90M
    cJSON *current_item = item->child;
1362
1363
6.90M
    if (output_buffer == NULL) {
1364
0
        return false;
1365
0
    }
1366
1367
    /* Compose the output: */
1368
6.90M
    length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
1369
6.90M
    output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1370
6.90M
    if (output_pointer == NULL) {
1371
0
        return false;
1372
0
    }
1373
1374
6.90M
    *output_pointer++ = '{';
1375
6.90M
    output_buffer->depth++;
1376
6.90M
    if (output_buffer->format) {
1377
6.90M
        *output_pointer++ = '\n';
1378
6.90M
    }
1379
6.90M
    output_buffer->offset += length;
1380
1381
9.44M
    while (current_item) {
1382
2.53M
        if (output_buffer->format) {
1383
2.53M
            size_t i;
1384
2.53M
            output_pointer = ensure(output_buffer, output_buffer->depth, out_of_memory);
1385
2.53M
            if (output_pointer == NULL) {
1386
0
                return false;
1387
0
            }
1388
1.16G
            for (i = 0; i < output_buffer->depth; i++) {
1389
1.16G
                *output_pointer++ = '\t';
1390
1.16G
            }
1391
2.53M
            output_buffer->offset += output_buffer->depth;
1392
2.53M
        }
1393
1394
        /* print key */
1395
2.53M
        if (!print_string_ptr((unsigned char *)current_item->string, output_buffer, out_of_memory)) {
1396
0
            return false;
1397
0
        }
1398
2.53M
        update_offset(output_buffer);
1399
1400
2.53M
        length = (size_t)(output_buffer->format ? 2 : 1);
1401
2.53M
        output_pointer = ensure(output_buffer, length, out_of_memory);
1402
2.53M
        if (output_pointer == NULL) {
1403
0
            return false;
1404
0
        }
1405
2.53M
        *output_pointer++ = ':';
1406
2.53M
        if (output_buffer->format) {
1407
2.53M
            *output_pointer++ = '\t';
1408
2.53M
        }
1409
2.53M
        output_buffer->offset += length;
1410
1411
        /* print value */
1412
2.53M
        if (!print_value(current_item, output_buffer, out_of_memory)) {
1413
0
            return false;
1414
0
        }
1415
2.53M
        update_offset(output_buffer);
1416
1417
        /* print comma if not last */
1418
2.53M
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1419
2.53M
        output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1420
2.53M
        if (output_pointer == NULL) {
1421
0
            return false;
1422
0
        }
1423
2.53M
        if (current_item->next) {
1424
1.03M
            *output_pointer++ = ',';
1425
1.03M
        }
1426
1427
2.53M
        if (output_buffer->format) {
1428
2.53M
            *output_pointer++ = '\n';
1429
2.53M
        }
1430
2.53M
        *output_pointer = '\0';
1431
2.53M
        output_buffer->offset += length;
1432
1433
2.53M
        current_item = current_item->next;
1434
2.53M
    }
1435
1436
6.90M
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2, out_of_memory);
1437
6.90M
    if (output_pointer == NULL) {
1438
0
        return false;
1439
0
    }
1440
6.90M
    if (output_buffer->format) {
1441
6.90M
        size_t i;
1442
5.18G
        for (i = 0; i < (output_buffer->depth - 1); i++) {
1443
5.17G
            *output_pointer++ = '\t';
1444
5.17G
        }
1445
6.90M
    }
1446
6.90M
    *output_pointer++ = '}';
1447
6.90M
    *output_pointer = '\0';
1448
6.90M
    output_buffer->depth--;
1449
1450
6.90M
    return true;
1451
6.90M
}
1452
1453
/* Get Array size/item / object item. */
1454
57.6k
CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
1455
57.6k
    cJSON *child = NULL;
1456
57.6k
    size_t size = 0;
1457
1458
57.6k
    if (array == NULL) {
1459
0
        return 0;
1460
0
    }
1461
1462
57.6k
    child = array->child;
1463
1464
2.72M
    while (child != NULL) {
1465
2.66M
        size++;
1466
2.66M
        child = child->next;
1467
2.66M
    }
1468
1469
    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1470
1471
57.6k
    return (int)size;
1472
57.6k
}
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
7.79M
static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
1499
7.79M
    cJSON *current_element = NULL;
1500
1501
7.79M
    if ((object == NULL) || (name == NULL)) {
1502
0
        return NULL;
1503
0
    }
1504
1505
7.79M
    current_element = object->child;
1506
7.79M
    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
7.79M
    } else {
1511
25.0M
        while ((current_element != NULL) &&
1512
22.1M
               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
1513
17.2M
            current_element = current_element->next;
1514
17.2M
        }
1515
7.79M
    }
1516
1517
7.79M
    if ((current_element == NULL) || (current_element->string == NULL)) {
1518
2.81M
        return NULL;
1519
2.81M
    }
1520
1521
4.97M
    return current_element;
1522
7.79M
}
1523
1524
7.79M
CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
1525
7.79M
    return get_object_item(object, string, false);
1526
7.79M
}
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
34
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsTrue(const cJSON *const item) {
1637
34
    if (item == NULL) {
1638
34
        return false;
1639
34
    }
1640
1641
0
    return (item->type & 0xff) == cJSON_True;
1642
34
}
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
2.74M
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
1668
2.74M
    if (item == NULL) {
1669
1.19M
        return false;
1670
1.19M
    }
1671
1672
1.55M
    return (item->type & 0xFF) == cJSON_String;
1673
2.74M
}
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
}