Coverage Report

Created: 2025-11-11 06:38

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