Coverage Report

Created: 2025-11-09 06:56

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
77.6M
#define true ((cJSON_bool)1)
70
71
#ifdef false
72
#undef false
73
#endif
74
10.8M
#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.22M
CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
101
2.22M
    if (!loader_cJSON_IsString(item)) {
102
1.89M
        return NULL;
103
1.89M
    }
104
105
328k
    return item->valuestring;
106
2.22M
}
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
16.1M
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
123
16.1M
    if ((string1 == NULL) || (string2 == NULL)) {
124
939
        return 1;
125
939
    }
126
127
16.1M
    if (string1 == string2) {
128
0
        return 0;
129
0
    }
130
131
37.1M
    for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) {
132
24.2M
        if (*string1 == '\0') {
133
3.23M
            return 0;
134
3.23M
        }
135
24.2M
    }
136
137
12.9M
    return tolower(*string1) - tolower(*string2);
138
16.1M
}
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
37.9M
static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
145
37.9M
    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
146
37.9M
    if (NULL != node) {
147
37.9M
        node->pAllocator = pAllocator;
148
37.9M
    }
149
37.9M
    return node;
150
37.9M
}
151
152
/* Delete a cJSON structure. */
153
12.3M
TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
154
12.3M
    cJSON *next = NULL;
155
50.3M
    while (item != NULL) {
156
37.9M
        next = item->next;
157
37.9M
        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
158
11.7M
            loader_cJSON_Delete(item->child);
159
11.7M
        }
160
37.9M
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
161
12.1M
            loader_free(item->pAllocator, item->valuestring);
162
12.1M
            item->valuestring = NULL;
163
12.1M
        }
164
37.9M
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
165
15.6M
            loader_free(item->pAllocator, item->string);
166
15.6M
            item->string = NULL;
167
15.6M
        }
168
37.9M
        loader_free(item->pAllocator, item);
169
37.9M
        item = next;
170
37.9M
    }
171
12.3M
}
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
227M
#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
884M
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
195
233M
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
196
/* get a pointer to the buffer at the position */
197
705M
#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.59M
static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
201
9.59M
    double number = 0;
202
9.59M
    unsigned char *after_end = NULL;
203
9.59M
    unsigned char number_c_string[64];
204
9.59M
    unsigned char decimal_point = get_decimal_point();
205
9.59M
    size_t i = 0;
206
207
9.59M
    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
33.5M
    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
215
33.5M
        switch (buffer_at_offset(input_buffer)[i]) {
216
2.55M
            case '0':
217
7.48M
            case '1':
218
9.20M
            case '2':
219
11.1M
            case '3':
220
13.2M
            case '4':
221
13.8M
            case '5':
222
17.1M
            case '6':
223
19.3M
            case '7':
224
20.8M
            case '8':
225
22.9M
            case '9':
226
22.9M
            case '+':
227
23.1M
            case '-':
228
23.7M
            case 'e':
229
23.8M
            case 'E':
230
23.8M
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
231
23.8M
                break;
232
233
141k
            case '.':
234
141k
                number_c_string[i] = decimal_point;
235
141k
                break;
236
237
9.59M
            default:
238
9.59M
                goto loop_end;
239
33.5M
        }
240
33.5M
    }
241
9.59M
loop_end:
242
9.59M
    number_c_string[i] = '\0';
243
244
9.59M
    number = strtod((const char *)number_c_string, (char **)&after_end);
245
9.59M
    if (number_c_string == after_end) {
246
284
        return false; /* parse_error */
247
284
    }
248
249
9.59M
    item->valuedouble = number;
250
251
    /* use saturation in case of overflow */
252
9.59M
    if (number >= INT_MAX) {
253
353k
        item->valueint = INT_MAX;
254
9.24M
    } else if (number <= (double)INT_MIN) {
255
201k
        item->valueint = INT_MIN;
256
9.04M
    } else {
257
9.04M
        item->valueint = (int)number;
258
9.04M
    }
259
260
9.59M
    item->type = cJSON_Number;
261
262
9.59M
    input_buffer->offset += (size_t)(after_end - number_c_string);
263
9.59M
    return true;
264
9.59M
}
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.7M
static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
278
45.7M
    unsigned char *newbuffer = NULL;
279
45.7M
    size_t newsize = 0;
280
281
45.7M
    if ((p == NULL) || (p->buffer == NULL)) {
282
0
        return NULL;
283
0
    }
284
285
45.7M
    if ((p->length > 0) && (p->offset >= p->length)) {
286
        /* make sure that offset is valid */
287
0
        return NULL;
288
0
    }
289
290
45.7M
    if (needed > INT_MAX) {
291
        /* sizes bigger than INT_MAX are currently not supported */
292
0
        return NULL;
293
0
    }
294
295
45.7M
    needed += p->offset + 1;
296
45.7M
    if (needed <= p->length) {
297
45.7M
        return p->buffer + p->offset;
298
45.7M
    }
299
300
23.8k
    if (p->noalloc) {
301
2.56k
        return NULL;
302
2.56k
    }
303
304
    /* calculate new buffer size */
305
21.3k
    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
21.3k
    } else {
313
21.3k
        newsize = needed * 2;
314
21.3k
    }
315
316
21.3k
    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
317
21.3k
    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
21.3k
    p->length = newsize;
327
21.3k
    p->buffer = newbuffer;
328
329
21.3k
    return newbuffer + p->offset;
330
21.3k
}
331
332
/* calculate the new length of the string in a printbuffer and update the offset */
333
17.8M
static void update_offset(printbuffer *const buffer) {
334
17.8M
    const unsigned char *buffer_pointer = NULL;
335
17.8M
    if ((buffer == NULL) || (buffer->buffer == NULL)) {
336
0
        return;
337
0
    }
338
17.8M
    buffer_pointer = buffer->buffer + buffer->offset;
339
340
17.8M
    buffer->offset += strlen((const char *)buffer_pointer);
341
17.8M
}
342
343
/* securely comparison of floating-point variables */
344
64.4k
static cJSON_bool compare_double(double a, double b) {
345
64.4k
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
346
64.4k
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
347
64.4k
}
348
349
/* Render the number nicely from the given item into a string. */
350
3.15M
static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
351
3.15M
    unsigned char *output_pointer = NULL;
352
3.15M
    double d = item->valuedouble;
353
3.15M
    int length = 0;
354
3.15M
    size_t i = 0;
355
3.15M
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
356
3.15M
    unsigned char decimal_point = get_decimal_point();
357
3.15M
    double test = 0.0;
358
359
3.15M
    if (output_buffer == NULL) {
360
0
        return false;
361
0
    }
362
363
    /* This checks for NaN and Infinity */
364
3.15M
    if (isnan(d) || isinf(d)) {
365
1.46k
        length = snprintf((char *)number_buffer, 26, "null");
366
3.15M
    } else if (d == (double)item->valueint) {
367
3.08M
        length = snprintf((char *)number_buffer, 26, "%d", item->valueint);
368
3.08M
    } else {
369
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
370
64.4k
        length = snprintf((char *)number_buffer, 26, "%1.15g", d);
371
372
        /* Check whether the original double can be recovered */
373
64.4k
        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.16k
            length = snprintf((char *)number_buffer, 26, "%1.17g", d);
376
7.16k
        }
377
64.4k
    }
378
379
    /* snprintf failed or buffer overrun occurred */
380
3.15M
    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.15M
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""), out_of_memory);
386
3.15M
    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
6.79M
    for (i = 0; i < ((size_t)length); i++) {
393
3.63M
        if (number_buffer[i] == decimal_point) {
394
10.7k
            output_pointer[i] = '.';
395
10.7k
            continue;
396
10.7k
        }
397
398
3.62M
        output_pointer[i] = number_buffer[i];
399
3.62M
    }
400
3.15M
    output_pointer[i] = '\0';
401
402
3.15M
    output_buffer->offset += (size_t)length;
403
404
3.15M
    return true;
405
3.15M
}
406
407
/* parse 4 digit hexadecimal number */
408
2.00M
static unsigned parse_hex4(const unsigned char *const input) {
409
2.00M
    unsigned int h = 0;
410
2.00M
    size_t i = 0;
411
412
7.91M
    for (i = 0; i < 4; i++) {
413
        /* parse digit */
414
6.72M
        if ((input[i] >= '0') && (input[i] <= '9')) {
415
3.70M
            h += (unsigned int)input[i] - '0';
416
3.70M
        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
417
676k
            h += (unsigned int)10 + input[i] - 'A';
418
2.33M
        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
419
1.51M
            h += (unsigned int)10 + input[i] - 'a';
420
1.51M
        } else /* invalid */
421
819k
        {
422
819k
            return 0;
423
819k
        }
424
425
5.90M
        if (i < 3) {
426
            /* shift left to make place for the next nibble */
427
4.71M
            h = h << 4;
428
4.71M
        }
429
5.90M
    }
430
431
1.18M
    return h;
432
2.00M
}
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
1.99M
                                           unsigned char **output_pointer) {
438
1.99M
    long unsigned int codepoint = 0;
439
1.99M
    unsigned int first_code = 0;
440
1.99M
    const unsigned char *first_sequence = input_pointer;
441
1.99M
    unsigned char utf8_length = 0;
442
1.99M
    unsigned char utf8_position = 0;
443
1.99M
    unsigned char sequence_length = 0;
444
1.99M
    unsigned char first_byte_mark = 0;
445
446
1.99M
    if ((input_end - first_sequence) < 6) {
447
        /* input ends unexpectedly */
448
155
        goto fail;
449
155
    }
450
451
    /* get the first utf16 sequence */
452
1.99M
    first_code = parse_hex4(first_sequence + 2);
453
454
    /* check that the code is valid */
455
1.99M
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
456
309
        goto fail;
457
309
    }
458
459
    /* UTF16 surrogate pair */
460
1.99M
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
461
12.8k
        const unsigned char *second_sequence = first_sequence + 6;
462
12.8k
        unsigned int second_code = 0;
463
12.8k
        sequence_length = 12; /* \uXXXX\uXXXX */
464
465
12.8k
        if ((input_end - second_sequence) < 6) {
466
            /* input ends unexpectedly */
467
352
            goto fail;
468
352
        }
469
470
12.5k
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
471
            /* missing second half of the surrogate pair */
472
485
            goto fail;
473
485
        }
474
475
        /* get the second utf16 sequence */
476
12.0k
        second_code = parse_hex4(second_sequence + 2);
477
        /* check that the code is valid */
478
12.0k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
479
            /* invalid second half of the surrogate pair */
480
464
            goto fail;
481
464
        }
482
483
        /* calculate the unicode codepoint from the surrogate pair */
484
11.5k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
485
1.98M
    } else {
486
1.98M
        sequence_length = 6; /* \uXXXX */
487
1.98M
        codepoint = first_code;
488
1.98M
    }
489
490
    /* encode as UTF-8
491
     * takes at maximum 4 bytes to encode:
492
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
493
1.99M
    if (codepoint < 0x80) {
494
        /* normal ascii, encoding 0xxxxxxx */
495
826k
        utf8_length = 1;
496
1.16M
    } else if (codepoint < 0x800) {
497
        /* two bytes, encoding 110xxxxx 10xxxxxx */
498
273k
        utf8_length = 2;
499
273k
        first_byte_mark = 0xC0; /* 11000000 */
500
894k
    } else if (codepoint < 0x10000) {
501
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
502
883k
        utf8_length = 3;
503
883k
        first_byte_mark = 0xE0; /* 11100000 */
504
883k
    } else if (codepoint <= 0x10FFFF) {
505
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
506
11.5k
        utf8_length = 4;
507
11.5k
        first_byte_mark = 0xF0; /* 11110000 */
508
11.5k
    } else {
509
        /* invalid unicode codepoint */
510
0
        goto fail;
511
0
    }
512
513
    /* encode as utf8 */
514
4.07M
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
515
        /* 10xxxxxx */
516
2.07M
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
517
2.07M
        codepoint >>= 6;
518
2.07M
    }
519
    /* encode first byte */
520
1.99M
    if (utf8_length > 1) {
521
1.16M
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
522
1.16M
    } else {
523
826k
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
524
826k
    }
525
526
1.99M
    *output_pointer += utf8_length;
527
528
1.99M
    return sequence_length;
529
530
1.76k
fail:
531
1.76k
    return 0;
532
1.99M
}
533
534
/* Parse the input text into an unescaped cinput, and populate item. */
535
27.8M
static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
536
27.8M
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
537
27.8M
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
538
27.8M
    unsigned char *output_pointer = NULL;
539
27.8M
    unsigned char *output = NULL;
540
541
    /* not a string */
542
27.8M
    if (buffer_at_offset(input_buffer)[0] != '\"') {
543
1.34k
        goto fail;
544
1.34k
    }
545
546
27.8M
    {
547
        /* calculate approximate size of the output (overestimate) */
548
27.8M
        size_t allocation_length = 0;
549
27.8M
        size_t skipped_bytes = 0;
550
664M
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
551
            /* is escape sequence */
552
636M
            if (input_end[0] == '\\') {
553
3.92M
                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
3.92M
                skipped_bytes++;
558
3.92M
                input_end++;
559
3.92M
            }
560
636M
            input_end++;
561
636M
        }
562
27.8M
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
563
722
            goto fail; /* string ended unexpectedly */
564
722
        }
565
566
        /* This is at most how much we need for the output */
567
27.8M
        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
568
27.8M
        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
569
27.8M
                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
570
27.8M
        if (output == NULL) {
571
0
            *out_of_memory = true;
572
0
            goto fail; /* allocation failure */
573
0
        }
574
27.8M
    }
575
576
27.8M
    output_pointer = output;
577
    /* loop through the string literal */
578
591M
    while (input_pointer < input_end) {
579
563M
        if (*input_pointer != '\\') {
580
561M
            *output_pointer++ = *input_pointer++;
581
561M
        }
582
        /* escape sequence */
583
2.57M
        else {
584
2.57M
            unsigned char sequence_length = 2;
585
2.57M
            if ((input_end - input_pointer) < 1) {
586
0
                goto fail;
587
0
            }
588
589
2.57M
            switch (input_pointer[1]) {
590
50.5k
                case 'b':
591
50.5k
                    *output_pointer++ = '\b';
592
50.5k
                    break;
593
43.1k
                case 'f':
594
43.1k
                    *output_pointer++ = '\f';
595
43.1k
                    break;
596
12.1k
                case 'n':
597
12.1k
                    *output_pointer++ = '\n';
598
12.1k
                    break;
599
173k
                case 'r':
600
173k
                    *output_pointer++ = '\r';
601
173k
                    break;
602
31.4k
                case 't':
603
31.4k
                    *output_pointer++ = '\t';
604
31.4k
                    break;
605
8.58k
                case '\"':
606
254k
                case '\\':
607
263k
                case '/':
608
263k
                    *output_pointer++ = input_pointer[1];
609
263k
                    break;
610
611
                /* UTF-16 literal */
612
1.99M
                case 'u':
613
1.99M
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
614
1.99M
                    if (sequence_length == 0) {
615
                        /* failed to convert UTF16-literal to UTF-8 */
616
1.76k
                        goto fail;
617
1.76k
                    }
618
1.99M
                    break;
619
620
1.99M
                default:
621
337
                    goto fail;
622
2.57M
            }
623
2.56M
            input_pointer += sequence_length;
624
2.56M
        }
625
563M
    }
626
627
    /* zero terminate the output */
628
27.8M
    *output_pointer = '\0';
629
630
27.8M
    item->type = cJSON_String;
631
27.8M
    item->valuestring = (char *)output;
632
633
27.8M
    input_buffer->offset = (size_t)(input_end - input_buffer->content);
634
27.8M
    input_buffer->offset++;
635
636
27.8M
    return true;
637
638
4.16k
fail:
639
4.16k
    if (output != NULL) {
640
2.10k
        loader_free(input_buffer->pAllocator, output);
641
2.10k
        output = NULL;
642
2.10k
    }
643
644
4.16k
    if (input_pointer != NULL) {
645
4.16k
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
646
4.16k
    }
647
648
4.16k
    return false;
649
27.8M
}
650
651
/* Render the cstring provided to an escaped version that can be printed. */
652
10.5M
static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
653
10.5M
    const unsigned char *input_pointer = NULL;
654
10.5M
    unsigned char *output = NULL;
655
10.5M
    unsigned char *output_pointer = NULL;
656
10.5M
    size_t output_length = 0;
657
    /* numbers of additional characters needed for escaping */
658
10.5M
    size_t escape_characters = 0;
659
660
10.5M
    if (output_buffer == NULL) {
661
0
        return false;
662
0
    }
663
664
    /* empty string */
665
10.5M
    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
190M
    for (input_pointer = input; *input_pointer; input_pointer++) {
676
180M
        switch (*input_pointer) {
677
1.62k
            case '\"':
678
36.0k
            case '\\':
679
58.2k
            case '\b':
680
711k
            case '\f':
681
1.37M
            case '\n':
682
1.49M
            case '\r':
683
1.55M
            case '\t':
684
                /* one character escape sequence */
685
1.55M
                escape_characters++;
686
1.55M
                break;
687
178M
            default:
688
178M
                if (*input_pointer < 32) {
689
                    /* UTF-16 escape sequence uXXXX */
690
109M
                    escape_characters += 5;
691
109M
                }
692
178M
                break;
693
180M
        }
694
180M
    }
695
10.5M
    output_length = (size_t)(input_pointer - input) + escape_characters;
696
697
10.5M
    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
698
10.5M
    if (output == NULL) {
699
2.56k
        return false;
700
2.56k
    }
701
702
    /* no characters have to be escaped */
703
10.5M
    if (escape_characters == 0) {
704
10.1M
        memcpy(output, input, output_length);
705
10.1M
        output[output_length] = '\0';
706
707
10.1M
        return true;
708
10.1M
    }
709
710
394k
    output_pointer = output;
711
    /* copy the string */
712
136M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
713
136M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
714
            /* normal character, copy */
715
25.9M
            *output_pointer = *input_pointer;
716
110M
        } 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
110M
            switch (*input_pointer) {
723
34.4k
                case '\\':
724
34.4k
                    *output_pointer = '\\';
725
34.4k
                    break;
726
1.62k
                case '\"':
727
1.62k
                    *output_pointer = '\"';
728
1.62k
                    break;
729
22.0k
                case '\b':
730
22.0k
                    *output_pointer = '\b';
731
22.0k
                    break;
732
621k
                case '\f':
733
621k
                    *output_pointer = '\f';
734
621k
                    break;
735
579k
                case '\n':
736
579k
                    *output_pointer = '\n';
737
579k
                    break;
738
122k
                case '\r':
739
122k
                    *output_pointer = '\r';
740
122k
                    break;
741
52.2k
                case '\t':
742
52.2k
                    *output_pointer = '\t';
743
52.2k
                    break;
744
109M
                default:
745
                    /* escape and print as unicode codepoint */
746
109M
                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
747
109M
                    output_pointer += 4;
748
109M
                    break;
749
110M
            }
750
110M
        }
751
136M
    }
752
394k
    output[output_length] = '\0';
753
754
394k
    return true;
755
394k
}
756
757
/* Invoke print_string_ptr (which is useful) on an item. */
758
5.67M
static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
759
5.67M
    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
760
5.67M
}
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
122M
static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
772
122M
    if ((buffer == NULL) || (buffer->content == NULL)) {
773
0
        return NULL;
774
0
    }
775
776
122M
    if (cannot_access_at_index(buffer, 0)) {
777
0
        return buffer;
778
0
    }
779
780
183M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
781
60.6M
        buffer->offset++;
782
60.6M
    }
783
784
122M
    if (buffer->offset == buffer->length) {
785
17.0k
        buffer->offset--;
786
17.0k
    }
787
788
122M
    return buffer;
789
122M
}
790
791
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
792
74.0k
static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
793
74.0k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
794
0
        return NULL;
795
0
    }
796
797
74.0k
    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
798
1.01k
        buffer->offset += 3;
799
1.01k
    }
800
801
74.0k
    return buffer;
802
74.0k
}
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
74.0k
                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
824
74.0k
    parse_buffer buffer = {0, 0, 0, 0, 0};
825
74.0k
    cJSON *item = NULL;
826
827
    /* reset error position */
828
74.0k
    global_error.json = NULL;
829
74.0k
    global_error.position = 0;
830
831
74.0k
    if (value == NULL || 0 == buffer_length) {
832
0
        goto fail;
833
0
    }
834
835
74.0k
    buffer.content = (const unsigned char *)value;
836
74.0k
    buffer.length = buffer_length;
837
74.0k
    buffer.offset = 0;
838
74.0k
    buffer.pAllocator = pAllocator;
839
840
74.0k
    item = cJSON_New_Item(pAllocator);
841
74.0k
    if (item == NULL) /* memory fail */
842
0
    {
843
0
        *out_of_memory = true;
844
0
        goto fail;
845
0
    }
846
847
74.0k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
848
        /* parse failure. ep is set. */
849
24.3k
        goto fail;
850
24.3k
    }
851
852
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
853
49.6k
    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
49.6k
    if (return_parse_end) {
860
0
        *return_parse_end = (const char *)buffer_at_offset(&buffer);
861
0
    }
862
863
49.6k
    return item;
864
865
24.3k
fail:
866
24.3k
    if (item != NULL) {
867
24.3k
        loader_cJSON_Delete(item);
868
24.3k
    }
869
870
24.3k
    if (value != NULL) {
871
24.3k
        error local_error;
872
24.3k
        local_error.json = (const unsigned char *)value;
873
24.3k
        local_error.position = 0;
874
875
24.3k
        if (buffer.offset < buffer.length) {
876
23.2k
            local_error.position = buffer.offset;
877
23.2k
        } else if (buffer.length > 0) {
878
1.07k
            local_error.position = buffer.length - 1;
879
1.07k
        }
880
881
24.3k
        if (return_parse_end != NULL) {
882
0
            *return_parse_end = (const char *)local_error.json + local_error.position;
883
0
        }
884
885
24.3k
        global_error = local_error;
886
24.3k
    }
887
888
24.3k
    return NULL;
889
49.6k
}
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
74.0k
                             bool *out_of_memory) {
899
74.0k
    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
900
74.0k
}
901
902
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
903
904
2.55M
static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
905
2.55M
    static const size_t default_buffer_size = 256;
906
2.55M
    printbuffer buffer[1];
907
2.55M
    unsigned char *printed = NULL;
908
909
2.55M
    memset(buffer, 0, sizeof(buffer));
910
911
    /* create buffer */
912
2.55M
    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
913
2.55M
    buffer->length = default_buffer_size;
914
2.55M
    buffer->format = format;
915
2.55M
    buffer->pAllocator = item->pAllocator;
916
2.55M
    if (buffer->buffer == NULL) {
917
0
        *out_of_memory = true;
918
0
        goto fail;
919
0
    }
920
921
    /* print the value */
922
2.55M
    if (!print_value(item, buffer, out_of_memory)) {
923
0
        goto fail;
924
0
    }
925
2.55M
    update_offset(buffer);
926
927
2.55M
    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
928
2.55M
                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
929
2.55M
    if (printed == NULL) {
930
0
        *out_of_memory = true;
931
0
        goto fail;
932
0
    }
933
2.55M
    buffer->buffer = NULL;
934
935
2.55M
    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.55M
}
950
951
/* Render a cJSON item/entity/structure to text. */
952
2.55M
TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
953
2.55M
    return (char *)print(item, true, out_of_memory);
954
2.55M
}
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.09M
loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
990
2.09M
    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
991
992
2.09M
    if ((length < 0) || (buffer == NULL)) {
993
0
        return false;
994
0
    }
995
996
2.09M
    p.buffer = (unsigned char *)buffer;
997
2.09M
    p.length = (size_t)length;
998
2.09M
    p.offset = 0;
999
2.09M
    p.noalloc = true;
1000
2.09M
    p.format = format;
1001
2.09M
    p.pAllocator = item->pAllocator;
1002
2.09M
    bool out_of_memory = false;
1003
2.09M
    return print_value(item, &p, &out_of_memory);
1004
2.09M
}
1005
1006
/* Parser core - when encountering text, process appropriately. */
1007
37.9M
static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1008
37.9M
    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
37.9M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
1015
12.6k
        item->type = cJSON_NULL;
1016
12.6k
        input_buffer->offset += 4;
1017
12.6k
        return true;
1018
12.6k
    }
1019
    /* false */
1020
37.9M
    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
1021
10.9k
        item->type = cJSON_False;
1022
10.9k
        input_buffer->offset += 5;
1023
10.9k
        return true;
1024
10.9k
    }
1025
    /* true */
1026
37.9M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
1027
248k
        item->type = cJSON_True;
1028
248k
        item->valueint = 1;
1029
248k
        input_buffer->offset += 4;
1030
248k
        return true;
1031
248k
    }
1032
    /* string */
1033
37.6M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
1034
12.1M
        return parse_string(item, input_buffer, out_of_memory);
1035
12.1M
    }
1036
    /* number */
1037
25.4M
    if (can_access_at_index(input_buffer, 0) &&
1038
25.4M
        ((buffer_at_offset(input_buffer)[0] == '-') ||
1039
25.2M
         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
1040
9.59M
        return parse_number(item, input_buffer);
1041
9.59M
    }
1042
    /* array */
1043
15.8M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
1044
1.89M
        return parse_array(item, input_buffer, out_of_memory);
1045
1.89M
    }
1046
    /* object */
1047
13.9M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
1048
13.9M
        return parse_object(item, input_buffer, out_of_memory);
1049
13.9M
    }
1050
1051
17.3k
    return false;
1052
13.9M
}
1053
1054
/* Render a value to text. */
1055
15.0M
static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1056
15.0M
    unsigned char *output = NULL;
1057
1058
15.0M
    if ((item == NULL) || (output_buffer == NULL)) {
1059
0
        return false;
1060
0
    }
1061
1062
15.0M
    switch ((item->type) & 0xFF) {
1063
3.65k
        case cJSON_NULL:
1064
3.65k
            output = ensure(output_buffer, 5, out_of_memory);
1065
3.65k
            if (output == NULL) {
1066
0
                return false;
1067
0
            }
1068
3.65k
            strcpy((char *)output, "null");
1069
3.65k
            return true;
1070
1071
4.04k
        case cJSON_False:
1072
4.04k
            output = ensure(output_buffer, 6, out_of_memory);
1073
4.04k
            if (output == NULL) {
1074
0
                return false;
1075
0
            }
1076
4.04k
            strcpy((char *)output, "false");
1077
4.04k
            return true;
1078
1079
63.9k
        case cJSON_True:
1080
63.9k
            output = ensure(output_buffer, 5, out_of_memory);
1081
63.9k
            if (output == NULL) {
1082
0
                return false;
1083
0
            }
1084
63.9k
            strcpy((char *)output, "true");
1085
63.9k
            return true;
1086
1087
3.15M
        case cJSON_Number:
1088
3.15M
            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.67M
        case cJSON_String:
1106
5.67M
            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.67M
        case cJSON_Object:
1112
5.67M
            return print_object(item, output_buffer, out_of_memory);
1113
1114
0
        default:
1115
0
            return false;
1116
15.0M
    }
1117
15.0M
}
1118
1119
/* Build an array from input text. */
1120
1.89M
static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1121
1.89M
    cJSON *head = NULL; /* head of the linked list */
1122
1.89M
    cJSON *current_item = NULL;
1123
1124
1.89M
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1125
80
        return false; /* to deeply nested */
1126
80
    }
1127
1.89M
    input_buffer->depth++;
1128
1129
1.89M
    if (buffer_at_offset(input_buffer)[0] != '[') {
1130
        /* not an array */
1131
0
        goto fail;
1132
0
    }
1133
1134
1.89M
    input_buffer->offset++;
1135
1.89M
    buffer_skip_whitespace(input_buffer);
1136
1.89M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
1137
        /* empty array */
1138
114k
        goto success;
1139
114k
    }
1140
1141
    /* check if we skipped to the end of the buffer */
1142
1.78M
    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.78M
    input_buffer->offset--;
1149
    /* loop through the comma separated array elements */
1150
22.2M
    do {
1151
        /* allocate next item */
1152
22.2M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1153
22.2M
        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
22.2M
        if (head == NULL) {
1160
            /* start the linked list */
1161
1.78M
            current_item = head = new_item;
1162
20.4M
        } else {
1163
            /* add to the end and advance */
1164
20.4M
            current_item->next = new_item;
1165
20.4M
            new_item->prev = current_item;
1166
20.4M
            current_item = new_item;
1167
20.4M
        }
1168
1169
        /* parse next value */
1170
22.2M
        input_buffer->offset++;
1171
22.2M
        buffer_skip_whitespace(input_buffer);
1172
22.2M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1173
489k
            goto fail; /* failed to parse value */
1174
489k
        }
1175
21.7M
        buffer_skip_whitespace(input_buffer);
1176
21.7M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1177
1178
1.29M
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
1179
1.82k
        goto fail; /* expected end of array */
1180
1.82k
    }
1181
1182
1.40M
success:
1183
1.40M
    input_buffer->depth--;
1184
1185
1.40M
    if (head != NULL) {
1186
1.28M
        head->prev = current_item;
1187
1.28M
    }
1188
1189
1.40M
    item->type = cJSON_Array;
1190
1.40M
    item->child = head;
1191
1192
1.40M
    input_buffer->offset++;
1193
1194
1.40M
    return true;
1195
1196
491k
fail:
1197
491k
    if (head != NULL) {
1198
491k
        loader_cJSON_Delete(head);
1199
491k
    }
1200
1201
491k
    return false;
1202
1.29M
}
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.09M
    while (current_element != NULL) {
1226
5.59M
        if (!print_value(current_element, output_buffer, out_of_memory)) {
1227
0
            return false;
1228
0
        }
1229
5.59M
        update_offset(output_buffer);
1230
5.59M
        if (current_element->next) {
1231
5.09M
            length = (size_t)(output_buffer->format ? 2 : 1);
1232
5.09M
            output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1233
5.09M
            if (output_pointer == NULL) {
1234
0
                return false;
1235
0
            }
1236
5.09M
            *output_pointer++ = ',';
1237
5.09M
            if (output_buffer->format) {
1238
5.09M
                *output_pointer++ = ' ';
1239
5.09M
            }
1240
5.09M
            *output_pointer = '\0';
1241
5.09M
            output_buffer->offset += length;
1242
5.09M
        }
1243
5.59M
        current_element = current_element->next;
1244
5.59M
    }
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.9M
static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1259
13.9M
    cJSON *head = NULL; /* linked list head */
1260
13.9M
    cJSON *current_item = NULL;
1261
1262
13.9M
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1263
73
        return false; /* to deeply nested */
1264
73
    }
1265
13.9M
    input_buffer->depth++;
1266
1267
13.9M
    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.9M
    input_buffer->offset++;
1272
13.9M
    buffer_skip_whitespace(input_buffer);
1273
13.9M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
1274
3.44M
        goto success; /* empty object */
1275
3.44M
    }
1276
1277
    /* check if we skipped to the end of the buffer */
1278
10.5M
    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.5M
    input_buffer->offset--;
1285
    /* loop through the comma separated array elements */
1286
15.6M
    do {
1287
        /* allocate next item */
1288
15.6M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1289
15.6M
        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.6M
        if (head == NULL) {
1296
            /* start the linked list */
1297
10.5M
            current_item = head = new_item;
1298
10.5M
        } else {
1299
            /* add to the end and advance */
1300
5.14M
            current_item->next = new_item;
1301
5.14M
            new_item->prev = current_item;
1302
5.14M
            current_item = new_item;
1303
5.14M
        }
1304
1305
15.6M
        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.6M
        input_buffer->offset++;
1311
15.6M
        buffer_skip_whitespace(input_buffer);
1312
15.6M
        if (!parse_string(current_item, input_buffer, out_of_memory)) {
1313
2.00k
            goto fail; /* failed to parse name */
1314
2.00k
        }
1315
15.6M
        buffer_skip_whitespace(input_buffer);
1316
1317
        /* swap valuestring and string, because we parsed the name */
1318
15.6M
        current_item->string = current_item->valuestring;
1319
15.6M
        current_item->valuestring = NULL;
1320
1321
15.6M
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
1322
316
            goto fail; /* invalid object */
1323
316
        }
1324
1325
        /* parse the value */
1326
15.6M
        input_buffer->offset++;
1327
15.6M
        buffer_skip_whitespace(input_buffer);
1328
15.6M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1329
35.4k
            goto fail; /* failed to parse value */
1330
35.4k
        }
1331
15.6M
        buffer_skip_whitespace(input_buffer);
1332
15.6M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1333
1334
10.4M
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
1335
282
        goto fail; /* expected end of object */
1336
282
    }
1337
1338
13.9M
success:
1339
13.9M
    input_buffer->depth--;
1340
1341
13.9M
    if (head != NULL) {
1342
10.4M
        head->prev = current_item;
1343
10.4M
    }
1344
1345
13.9M
    item->type = cJSON_Object;
1346
13.9M
    item->child = head;
1347
1348
13.9M
    input_buffer->offset++;
1349
13.9M
    return true;
1350
1351
38.0k
fail:
1352
38.0k
    if (head != NULL) {
1353
38.0k
        loader_cJSON_Delete(head);
1354
38.0k
    }
1355
1356
38.0k
    return false;
1357
10.4M
}
1358
1359
/* Render an object to text. */
1360
5.67M
static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1361
5.67M
    unsigned char *output_pointer = NULL;
1362
5.67M
    size_t length = 0;
1363
5.67M
    cJSON *current_item = item->child;
1364
1365
5.67M
    if (output_buffer == NULL) {
1366
0
        return false;
1367
0
    }
1368
1369
    /* Compose the output: */
1370
5.67M
    length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
1371
5.67M
    output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1372
5.67M
    if (output_pointer == NULL) {
1373
0
        return false;
1374
0
    }
1375
1376
5.67M
    *output_pointer++ = '{';
1377
5.67M
    output_buffer->depth++;
1378
5.67M
    if (output_buffer->format) {
1379
5.67M
        *output_pointer++ = '\n';
1380
5.67M
    }
1381
5.67M
    output_buffer->offset += length;
1382
1383
10.5M
    while (current_item) {
1384
4.85M
        if (output_buffer->format) {
1385
4.85M
            size_t i;
1386
4.85M
            output_pointer = ensure(output_buffer, output_buffer->depth, out_of_memory);
1387
4.85M
            if (output_pointer == NULL) {
1388
0
                return false;
1389
0
            }
1390
2.98G
            for (i = 0; i < output_buffer->depth; i++) {
1391
2.97G
                *output_pointer++ = '\t';
1392
2.97G
            }
1393
4.85M
            output_buffer->offset += output_buffer->depth;
1394
4.85M
        }
1395
1396
        /* print key */
1397
4.85M
        if (!print_string_ptr((unsigned char *)current_item->string, output_buffer, out_of_memory)) {
1398
0
            return false;
1399
0
        }
1400
4.85M
        update_offset(output_buffer);
1401
1402
4.85M
        length = (size_t)(output_buffer->format ? 2 : 1);
1403
4.85M
        output_pointer = ensure(output_buffer, length, out_of_memory);
1404
4.85M
        if (output_pointer == NULL) {
1405
0
            return false;
1406
0
        }
1407
4.85M
        *output_pointer++ = ':';
1408
4.85M
        if (output_buffer->format) {
1409
4.85M
            *output_pointer++ = '\t';
1410
4.85M
        }
1411
4.85M
        output_buffer->offset += length;
1412
1413
        /* print value */
1414
4.85M
        if (!print_value(current_item, output_buffer, out_of_memory)) {
1415
0
            return false;
1416
0
        }
1417
4.85M
        update_offset(output_buffer);
1418
1419
        /* print comma if not last */
1420
4.85M
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1421
4.85M
        output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1422
4.85M
        if (output_pointer == NULL) {
1423
0
            return false;
1424
0
        }
1425
4.85M
        if (current_item->next) {
1426
2.31M
            *output_pointer++ = ',';
1427
2.31M
        }
1428
1429
4.85M
        if (output_buffer->format) {
1430
4.85M
            *output_pointer++ = '\n';
1431
4.85M
        }
1432
4.85M
        *output_pointer = '\0';
1433
4.85M
        output_buffer->offset += length;
1434
1435
4.85M
        current_item = current_item->next;
1436
4.85M
    }
1437
1438
5.67M
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2, out_of_memory);
1439
5.67M
    if (output_pointer == NULL) {
1440
0
        return false;
1441
0
    }
1442
5.67M
    if (output_buffer->format) {
1443
5.67M
        size_t i;
1444
3.86G
        for (i = 0; i < (output_buffer->depth - 1); i++) {
1445
3.86G
            *output_pointer++ = '\t';
1446
3.86G
        }
1447
5.67M
    }
1448
5.67M
    *output_pointer++ = '}';
1449
5.67M
    *output_pointer = '\0';
1450
5.67M
    output_buffer->depth--;
1451
1452
5.67M
    return true;
1453
5.67M
}
1454
1455
/* Get Array size/item / object item. */
1456
90.3k
CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
1457
90.3k
    cJSON *child = NULL;
1458
90.3k
    size_t size = 0;
1459
1460
90.3k
    if (array == NULL) {
1461
0
        return 0;
1462
0
    }
1463
1464
90.3k
    child = array->child;
1465
1466
3.24M
    while (child != NULL) {
1467
3.15M
        size++;
1468
3.15M
        child = child->next;
1469
3.15M
    }
1470
1471
    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1472
1473
90.3k
    return (int)size;
1474
90.3k
}
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.27M
static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
1501
6.27M
    cJSON *current_element = NULL;
1502
1503
6.27M
    if ((object == NULL) || (name == NULL)) {
1504
0
        return NULL;
1505
0
    }
1506
1507
6.27M
    current_element = object->child;
1508
6.27M
    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.27M
    } else {
1513
19.2M
        while ((current_element != NULL) &&
1514
16.1M
               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
1515
12.9M
            current_element = current_element->next;
1516
12.9M
        }
1517
6.27M
    }
1518
1519
6.27M
    if ((current_element == NULL) || (current_element->string == NULL)) {
1520
3.03M
        return NULL;
1521
3.03M
    }
1522
1523
3.23M
    return current_element;
1524
6.27M
}
1525
1526
6.27M
CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
1527
6.27M
    return get_object_item(object, string, false);
1528
6.27M
}
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.22M
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
1670
2.22M
    if (item == NULL) {
1671
1.89M
        return false;
1672
1.89M
    }
1673
1674
331k
    return (item->type & 0xFF) == cJSON_String;
1675
2.22M
}
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
}