Coverage Report

Created: 2026-10-28 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tinygltf/tinygltf_json_c.h
Line
Count
Source
1
#ifndef TINYGLTF_JSON_C_H_
2
#define TINYGLTF_JSON_C_H_
3
4
/*
5
 * Floating-point conversion attribution:
6
 *
7
 * - JSON number parsing in this C11 port is based on fast_float.
8
 *   Upstream: https://github.com/fastfloat/fast_float
9
 *   Copyright (c) 2021 The fast_float authors.
10
 *   License: Apache License 2.0, MIT License, or Boost Software License 1.0.
11
 *
12
 * - JSON number serialization in this C11 port is based on Dragonbox-style
13
 *   shortest round-trippable binary floating-point to decimal conversion.
14
 *   Upstream: https://github.com/jk-jeon/dragonbox
15
 *   Copyright 2020-2024 Junekey Jeon.
16
 *   License: Apache License 2.0 with LLVM Exceptions, or Boost Software
17
 *   License 1.0.
18
 */
19
20
#include <stddef.h>
21
#include <stdint.h>
22
23
#ifdef __cplusplus
24
extern "C" {
25
#endif
26
27
typedef enum tg3json_type {
28
    TG3JSON_NULL = 0,
29
    TG3JSON_BOOL = 1,
30
    TG3JSON_INT = 2,
31
    TG3JSON_REAL = 3,
32
    TG3JSON_STRING = 4,
33
    TG3JSON_ARRAY = 5,
34
    TG3JSON_OBJECT = 6
35
} tg3json_type;
36
37
typedef struct tg3json_value tg3json_value;
38
39
typedef struct tg3json_string {
40
    char *ptr;
41
    size_t len;
42
} tg3json_string;
43
44
typedef struct tg3json_array {
45
    tg3json_value *items;
46
    size_t count;
47
} tg3json_array;
48
49
typedef struct tg3json_object_entry {
50
    char *key;
51
    size_t key_len;
52
    tg3json_value *value;
53
} tg3json_object_entry;
54
55
typedef struct tg3json_object {
56
    tg3json_object_entry *items;
57
    size_t count;
58
} tg3json_object;
59
60
struct tg3json_value {
61
    tg3json_type type;
62
    union {
63
        int boolean;
64
        int64_t integer;
65
        double real;
66
        tg3json_string string;
67
        tg3json_array array;
68
        tg3json_object object;
69
    } u;
70
};
71
72
int tg3json_parse_n(const char *data, size_t len, size_t depth_limit,
73
                    tg3json_value *out_value, const char **out_error_pos);
74
int tg3json_parse(const char *begin, const char *end, size_t depth_limit,
75
                  tg3json_value *out_value, const char **out_error_pos);
76
typedef struct tg3json_parse_options {
77
    size_t depth_limit;       /* 0 = default */
78
    size_t memory_budget;     /* 0 = unlimited */
79
    size_t max_single_alloc;  /* 0 = unlimited */
80
    size_t max_string_length; /* 0 = unlimited */
81
    int parse_float32;        /* 1 = round JSON reals to float */
82
} tg3json_parse_options;
83
int tg3json_parse_n_opts(const char *data, size_t len,
84
                         const tg3json_parse_options *options,
85
                         tg3json_value *out_value,
86
                         const char **out_error_pos);
87
void tg3json_value_free(tg3json_value *value);
88
void tg3json_value_init_null(tg3json_value *value);
89
void tg3json_value_init_bool(tg3json_value *value, int boolean_value);
90
void tg3json_value_init_int(tg3json_value *value, int64_t integer_value);
91
void tg3json_value_init_real(tg3json_value *value, double real_value);
92
int tg3json_value_init_string_n(tg3json_value *value, const char *str, size_t len);
93
int tg3json_value_init_string(tg3json_value *value, const char *str);
94
void tg3json_value_init_array(tg3json_value *value);
95
void tg3json_value_init_object(tg3json_value *value);
96
int tg3json_value_copy(tg3json_value *dst, const tg3json_value *src);
97
98
const tg3json_value *tg3json_object_get(const tg3json_value *object,
99
                                        const char *key);
100
const tg3json_value *tg3json_object_get_n(const tg3json_value *object,
101
                                          const char *key, size_t key_len);
102
tg3json_value *tg3json_object_get_mut(tg3json_value *object, const char *key);
103
tg3json_value *tg3json_object_get_mut_n(tg3json_value *object,
104
                                        const char *key, size_t key_len);
105
const tg3json_object_entry *tg3json_object_at(const tg3json_value *object,
106
                                              size_t index);
107
size_t tg3json_object_size(const tg3json_value *object);
108
int tg3json_object_set_take_n(tg3json_value *object, const char *key, size_t key_len,
109
                              tg3json_value *value);
110
int tg3json_object_set_take(tg3json_value *object, const char *key,
111
                            tg3json_value *value);
112
int tg3json_object_set_copy_n(tg3json_value *object, const char *key, size_t key_len,
113
                              const tg3json_value *value);
114
int tg3json_object_set_copy(tg3json_value *object, const char *key,
115
                            const tg3json_value *value);
116
const tg3json_value *tg3json_array_get(const tg3json_value *array, size_t index);
117
size_t tg3json_array_size(const tg3json_value *array);
118
int tg3json_array_append_take(tg3json_value *array, tg3json_value *value);
119
int tg3json_array_append_copy(tg3json_value *array, const tg3json_value *value);
120
char *tg3json_stringify(const tg3json_value *value, size_t *out_len);
121
char *tg3json_stringify_pretty(const tg3json_value *value, int indent, size_t *out_len);
122
123
#ifdef __cplusplus
124
} /* extern "C" */
125
#endif
126
127
#ifdef TINYGLTF_JSON_C_IMPLEMENTATION
128
129
#ifndef TINYGLTF_JSON_NO_STDLIB
130
  #include <stdlib.h>
131
  #include <string.h>
132
  #include <stdio.h>
133
  #include <float.h>
134
#if defined(_MSC_VER) || (defined(LDBL_MANT_DIG) && LDBL_MANT_DIG <= 53)
135
#define TG3JSON_USE_STDLIB_FPCONV 1
136
#endif
137
#endif
138
#ifndef TG3JSON_USE_STDLIB_FPCONV
139
#define TG3JSON_USE_STDLIB_FPCONV 0
140
#endif
141
142
#ifdef TINYGLTF_JSON_NO_STDLIB
143
static void *tg3json__memcpy_fallback(void *dst, const void *src, size_t sz) {
144
    unsigned char *d = (unsigned char *)dst;
145
    const unsigned char *s = (const unsigned char *)src;
146
    while (sz--) *d++ = *s++;
147
    return dst;
148
}
149
150
static void *tg3json__memset_fallback(void *dst, int val, size_t sz) {
151
    unsigned char *d = (unsigned char *)dst;
152
    while (sz--) *d++ = (unsigned char)val;
153
    return dst;
154
}
155
156
static int tg3json__memcmp_fallback(const void *a, const void *b, size_t sz) {
157
    const unsigned char *pa = (const unsigned char *)a;
158
    const unsigned char *pb = (const unsigned char *)b;
159
    while (sz--) {
160
        if (*pa != *pb) return (int)*pa - (int)*pb;
161
        ++pa;
162
        ++pb;
163
    }
164
    return 0;
165
}
166
167
static size_t tg3json__strlen_fallback(const char *str) {
168
    const char *p = str;
169
    while (*p) ++p;
170
    return (size_t)(p - str);
171
}
172
173
#endif
174
175
#ifndef TINYGLTF_JSON_MALLOC
176
#ifdef TINYGLTF_JSON_NO_STDLIB
177
#define TINYGLTF_JSON_MALLOC(sz) NULL
178
#else
179
#define TINYGLTF_JSON_MALLOC(sz) malloc(sz)
180
#endif
181
#endif
182
#ifndef TINYGLTF_JSON_REALLOC
183
#ifdef TINYGLTF_JSON_NO_STDLIB
184
#define TINYGLTF_JSON_REALLOC(ptr, sz) NULL
185
#else
186
#define TINYGLTF_JSON_REALLOC(ptr, sz) realloc(ptr, sz)
187
#endif
188
#endif
189
#ifndef TINYGLTF_JSON_FREE
190
#ifdef TINYGLTF_JSON_NO_STDLIB
191
#define TINYGLTF_JSON_FREE(ptr) ((void)(ptr))
192
#else
193
#define TINYGLTF_JSON_FREE(ptr) free(ptr)
194
#endif
195
#endif
196
197
#ifndef TINYGLTF_JSON_MEMCPY
198
#ifdef TINYGLTF_JSON_NO_STDLIB
199
#define TINYGLTF_JSON_MEMCPY(dst, src, sz) tg3json__memcpy_fallback((dst), (src), (sz))
200
#else
201
2.00M
#define TINYGLTF_JSON_MEMCPY(dst, src, sz) memcpy(dst, src, sz)
202
#endif
203
#endif
204
#ifndef TINYGLTF_JSON_MEMSET
205
#ifdef TINYGLTF_JSON_NO_STDLIB
206
#define TINYGLTF_JSON_MEMSET(dst, val, sz) tg3json__memset_fallback((dst), (val), (sz))
207
#else
208
36.5M
#define TINYGLTF_JSON_MEMSET(dst, val, sz) memset(dst, val, sz)
209
#endif
210
#endif
211
#ifndef TINYGLTF_JSON_MEMCMP
212
#ifdef TINYGLTF_JSON_NO_STDLIB
213
#define TINYGLTF_JSON_MEMCMP(a, b, sz) tg3json__memcmp_fallback((a), (b), (sz))
214
#else
215
228k
#define TINYGLTF_JSON_MEMCMP(a, b, sz) memcmp(a, b, sz)
216
#endif
217
#endif
218
#ifndef TINYGLTF_JSON_STRLEN
219
#ifdef TINYGLTF_JSON_NO_STDLIB
220
#define TINYGLTF_JSON_STRLEN(str) tg3json__strlen_fallback((str))
221
#else
222
7.67M
#define TINYGLTF_JSON_STRLEN(str) strlen(str)
223
#endif
224
#endif
225
226
0
static size_t tg3json__itoa(int64_t value, char *buf) {
227
0
    char *p = buf;
228
0
    uint64_t val;
229
0
    char tmp[24];
230
0
    int i = 0;
231
0
    if (value < 0) {
232
0
        *p++ = '-';
233
0
        val = (value == -9223372036854775807LL - 1) ? 9223372036854775808ULL : (uint64_t)(-value);
234
0
    } else {
235
0
        val = (uint64_t)value;
236
0
    }
237
0
    if (val == 0) {
238
0
        *p++ = '0';
239
0
        *p = '\0';
240
0
        return (size_t)(p - buf);
241
0
    }
242
0
    while (val > 0) {
243
0
        tmp[i++] = (char)('0' + (val % 10));
244
0
        val /= 10;
245
0
    }
246
0
    while (i > 0) {
247
0
        *p++ = tmp[--i];
248
0
    }
249
0
    *p = '\0';
250
0
    return (size_t)(p - buf);
251
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__itoa(long, char*)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__itoa
252
253
#if !TG3JSON_USE_STDLIB_FPCONV
254
0
static size_t tg3json__utoa(uint64_t value, char *buf) {
255
0
    char tmp[32];
256
0
    size_t n = 0;
257
0
    size_t i = 0;
258
0
    if (value == 0) {
259
0
        buf[0] = '0';
260
0
        buf[1] = '\0';
261
0
        return 1;
262
0
    }
263
0
    while (value > 0) {
264
0
        tmp[n++] = (char)('0' + (value % 10u));
265
0
        value /= 10u;
266
0
    }
267
0
    while (n > 0) buf[i++] = tmp[--n];
268
0
    buf[i] = '\0';
269
0
    return i;
270
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__utoa(unsigned long, char*)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__utoa
271
#endif  /* !TG3JSON_USE_STDLIB_FPCONV */
272
273
538k
static uint64_t tg3json__double_bits(double v) {
274
538k
    uint64_t bits = 0;
275
538k
    TINYGLTF_JSON_MEMCPY(&bits, &v, sizeof(bits));
276
538k
    return bits;
277
538k
}
fuzz_gltf_v3.cc:tg3json__double_bits(double)
Line
Count
Source
273
81.6k
static uint64_t tg3json__double_bits(double v) {
274
81.6k
    uint64_t bits = 0;
275
81.6k
    TINYGLTF_JSON_MEMCPY(&bits, &v, sizeof(bits));
276
81.6k
    return bits;
277
81.6k
}
tiny_gltf_v3.c:tg3json__double_bits
Line
Count
Source
273
457k
static uint64_t tg3json__double_bits(double v) {
274
457k
    uint64_t bits = 0;
275
457k
    TINYGLTF_JSON_MEMCPY(&bits, &v, sizeof(bits));
276
457k
    return bits;
277
457k
}
278
279
0
static int tg3json__is_nan_bits(uint64_t bits) {
280
0
    return ((bits & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) &&
281
0
           ((bits & 0x000fffffffffffffULL) != 0);
282
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__is_nan_bits(unsigned long)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__is_nan_bits
283
284
538k
static int tg3json__is_inf_bits(uint64_t bits) {
285
538k
    return (bits & 0x7fffffffffffffffULL) == 0x7ff0000000000000ULL;
286
538k
}
fuzz_gltf_v3.cc:tg3json__is_inf_bits(unsigned long)
Line
Count
Source
284
81.6k
static int tg3json__is_inf_bits(uint64_t bits) {
285
81.6k
    return (bits & 0x7fffffffffffffffULL) == 0x7ff0000000000000ULL;
286
81.6k
}
tiny_gltf_v3.c:tg3json__is_inf_bits
Line
Count
Source
284
457k
static int tg3json__is_inf_bits(uint64_t bits) {
285
457k
    return (bits & 0x7fffffffffffffffULL) == 0x7ff0000000000000ULL;
286
457k
}
287
288
#if !TG3JSON_USE_STDLIB_FPCONV
289
1.40k
static double tg3json__double_from_bits(uint64_t bits) {
290
1.40k
    double v = 0.0;
291
1.40k
    TINYGLTF_JSON_MEMCPY(&v, &bits, sizeof(v));
292
1.40k
    return v;
293
1.40k
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__double_from_bits(unsigned long)
tiny_gltf_v3.c:tg3json__double_from_bits
Line
Count
Source
289
1.40k
static double tg3json__double_from_bits(uint64_t bits) {
290
1.40k
    double v = 0.0;
291
1.40k
    TINYGLTF_JSON_MEMCPY(&v, &bits, sizeof(v));
292
1.40k
    return v;
293
1.40k
}
294
295
570k
static long double tg3json__pow10_ld(int exp10) {
296
570k
    long double v = 1.0L;
297
570k
    if (exp10 < 0) {
298
182k
        exp10 = -exp10;
299
4.15M
        while (exp10 >= 16) {
300
3.97M
            v *= 1.0e-16L;
301
3.97M
            exp10 -= 16;
302
3.97M
        }
303
615k
        while (exp10-- > 0) v *= 0.1L;
304
387k
    } else {
305
587k
        while (exp10 >= 16) {
306
199k
            v *= 1.0e16L;
307
199k
            exp10 -= 16;
308
199k
        }
309
2.51M
        while (exp10-- > 0) v *= 10.0L;
310
387k
    }
311
570k
    return v;
312
570k
}
fuzz_gltf_v3.cc:tg3json__pow10_ld(int)
Line
Count
Source
295
112k
static long double tg3json__pow10_ld(int exp10) {
296
112k
    long double v = 1.0L;
297
112k
    if (exp10 < 0) {
298
51.2k
        exp10 = -exp10;
299
4.02M
        while (exp10 >= 16) {
300
3.97M
            v *= 1.0e-16L;
301
3.97M
            exp10 -= 16;
302
3.97M
        }
303
159k
        while (exp10-- > 0) v *= 0.1L;
304
61.4k
    } else {
305
157k
        while (exp10 >= 16) {
306
96.1k
            v *= 1.0e16L;
307
96.1k
            exp10 -= 16;
308
96.1k
        }
309
369k
        while (exp10-- > 0) v *= 10.0L;
310
61.4k
    }
311
112k
    return v;
312
112k
}
tiny_gltf_v3.c:tg3json__pow10_ld
Line
Count
Source
295
457k
static long double tg3json__pow10_ld(int exp10) {
296
457k
    long double v = 1.0L;
297
457k
    if (exp10 < 0) {
298
131k
        exp10 = -exp10;
299
131k
        while (exp10 >= 16) {
300
341
            v *= 1.0e-16L;
301
341
            exp10 -= 16;
302
341
        }
303
455k
        while (exp10-- > 0) v *= 0.1L;
304
326k
    } else {
305
429k
        while (exp10 >= 16) {
306
103k
            v *= 1.0e16L;
307
103k
            exp10 -= 16;
308
103k
        }
309
2.14M
        while (exp10-- > 0) v *= 10.0L;
310
326k
    }
311
457k
    return v;
312
457k
}
313
#endif
314
315
564k
static int tg3json__parse_f64_c(const char *start, const char *end, double *out) {
316
#if TG3JSON_USE_STDLIB_FPCONV
317
    size_t len = (size_t)(end - start);
318
    char stack_buf[128];
319
    char *buf = stack_buf;
320
    char *parse_end = NULL;
321
    double v;
322
    if (len + 1 > sizeof(stack_buf)) {
323
        buf = (char *)TINYGLTF_JSON_MALLOC(len + 1);
324
        if (!buf) return 0;
325
    }
326
    if (len > 0) TINYGLTF_JSON_MEMCPY(buf, start, len);
327
    buf[len] = '\0';
328
    v = strtod(buf, &parse_end);
329
    if (parse_end != buf + len || tg3json__is_inf_bits(tg3json__double_bits(v))) {
330
        if (buf != stack_buf) TINYGLTF_JSON_FREE(buf);
331
        return 0;
332
    }
333
    if (buf != stack_buf) TINYGLTF_JSON_FREE(buf);
334
    *out = v;
335
    return 1;
336
#else
337
564k
    const char *p = start;
338
564k
    int neg = 0;
339
564k
    int saw_digit = 0;
340
564k
    int nonzero_seen = 0;
341
564k
    int exp10 = 0;
342
564k
    uint64_t sig = 0;
343
564k
    int sig_digits = 0;
344
564k
    long double extra = 0.0L;
345
564k
    int extra_digits = 0;
346
564k
    int exp_sign = 1;
347
564k
    int exp_lit = 0;
348
564k
    long double v;
349
350
564k
    if (p < end && *p == '-') {
351
27.5k
        neg = 1;
352
27.5k
        ++p;
353
27.5k
    }
354
564k
    if (p >= end) return 0;
355
564k
    if (*p == '0') {
356
134k
        saw_digit = 1;
357
134k
        ++p;
358
430k
    } else if (*p >= '1' && *p <= '9') {
359
8.83M
        do {
360
8.83M
            int d = *p - '0';
361
8.83M
            saw_digit = 1;
362
8.83M
            nonzero_seen = 1;
363
8.83M
            if (sig_digits < 19) {
364
6.63M
                sig = sig * 10u + (uint64_t)d;
365
6.63M
                ++sig_digits;
366
6.63M
            } else if (extra_digits < 64) {
367
2.20M
                extra = extra * 10.0L + (long double)d;
368
2.20M
                ++extra_digits;
369
2.20M
            } else {
370
2.64k
                ++exp10;
371
2.64k
            }
372
8.83M
            ++p;
373
8.83M
        } while (p < end && *p >= '0' && *p <= '9');
374
430k
    } else {
375
0
        return 0;
376
0
    }
377
564k
    if (p < end && *p == '.') {
378
186k
        ++p;
379
186k
        if (p >= end || *p < '0' || *p > '9') return 0;
380
3.39M
        do {
381
3.39M
            int d = *p - '0';
382
3.39M
            saw_digit = 1;
383
3.39M
            if (d != 0 || nonzero_seen) {
384
3.35M
                nonzero_seen = nonzero_seen || (d != 0);
385
3.35M
                if (sig_digits < 19) {
386
573k
                    sig = sig * 10u + (uint64_t)d;
387
573k
                    ++sig_digits;
388
573k
                    --exp10;
389
2.78M
                } else if (extra_digits < 64) {
390
72.7k
                    extra = extra * 10.0L + (long double)d;
391
72.7k
                    ++extra_digits;
392
72.7k
                    --exp10;
393
2.71M
                } else {
394
2.71M
                    --exp10;
395
2.71M
                }
396
3.35M
            } else {
397
39.1k
                --exp10;
398
39.1k
            }
399
3.39M
            ++p;
400
3.39M
        } while (p < end && *p >= '0' && *p <= '9');
401
186k
    }
402
564k
    if (!saw_digit) return 0;
403
564k
    if (p < end && (*p == 'e' || *p == 'E')) {
404
85.2k
        ++p;
405
85.2k
        if (p < end && (*p == '+' || *p == '-')) {
406
39.3k
            exp_sign = (*p == '-') ? -1 : 1;
407
39.3k
            ++p;
408
39.3k
        }
409
85.2k
        if (p >= end || *p < '0' || *p > '9') return 0;
410
326k
        while (p < end && *p >= '0' && *p <= '9') {
411
240k
            if (exp_lit < 10000) exp_lit = exp_lit * 10 + (*p - '0');
412
240k
            ++p;
413
240k
        }
414
85.2k
        exp10 += exp_sign * exp_lit;
415
85.2k
    }
416
564k
    if (p != end) return 0;
417
564k
    if (!nonzero_seen || sig_digits == 0) {
418
12.2k
        *out = neg ? tg3json__double_from_bits(0x8000000000000000ULL) : 0.0;
419
12.2k
        return 1;
420
12.2k
    }
421
552k
    if (exp10 > 309) return 0;
422
552k
    if (exp10 < -4000) {
423
13.3k
        *out = neg ? tg3json__double_from_bits(0x8000000000000000ULL) : 0.0;
424
13.3k
        return 1;
425
13.3k
    }
426
538k
    v = (long double)sig;
427
538k
    if (extra_digits > 0) {
428
342k
        v = v * tg3json__pow10_ld(extra_digits) + extra;
429
342k
    }
430
538k
    if (exp10 != 0) v *= tg3json__pow10_ld(exp10);
431
538k
    if (neg) v = -v;
432
538k
    *out = (double)v;
433
538k
    if (tg3json__is_inf_bits(tg3json__double_bits(*out))) return 0;
434
538k
    return 1;
435
538k
#endif
436
538k
}
fuzz_gltf_v3.cc:tg3json__parse_f64_c(char const*, char const*, double*)
Line
Count
Source
315
98.5k
static int tg3json__parse_f64_c(const char *start, const char *end, double *out) {
316
#if TG3JSON_USE_STDLIB_FPCONV
317
    size_t len = (size_t)(end - start);
318
    char stack_buf[128];
319
    char *buf = stack_buf;
320
    char *parse_end = NULL;
321
    double v;
322
    if (len + 1 > sizeof(stack_buf)) {
323
        buf = (char *)TINYGLTF_JSON_MALLOC(len + 1);
324
        if (!buf) return 0;
325
    }
326
    if (len > 0) TINYGLTF_JSON_MEMCPY(buf, start, len);
327
    buf[len] = '\0';
328
    v = strtod(buf, &parse_end);
329
    if (parse_end != buf + len || tg3json__is_inf_bits(tg3json__double_bits(v))) {
330
        if (buf != stack_buf) TINYGLTF_JSON_FREE(buf);
331
        return 0;
332
    }
333
    if (buf != stack_buf) TINYGLTF_JSON_FREE(buf);
334
    *out = v;
335
    return 1;
336
#else
337
98.5k
    const char *p = start;
338
98.5k
    int neg = 0;
339
98.5k
    int saw_digit = 0;
340
98.5k
    int nonzero_seen = 0;
341
98.5k
    int exp10 = 0;
342
98.5k
    uint64_t sig = 0;
343
98.5k
    int sig_digits = 0;
344
98.5k
    long double extra = 0.0L;
345
98.5k
    int extra_digits = 0;
346
98.5k
    int exp_sign = 1;
347
98.5k
    int exp_lit = 0;
348
98.5k
    long double v;
349
350
98.5k
    if (p < end && *p == '-') {
351
1.97k
        neg = 1;
352
1.97k
        ++p;
353
1.97k
    }
354
98.5k
    if (p >= end) return 0;
355
98.5k
    if (*p == '0') {
356
3.91k
        saw_digit = 1;
357
3.91k
        ++p;
358
94.5k
    } else if (*p >= '1' && *p <= '9') {
359
937k
        do {
360
937k
            int d = *p - '0';
361
937k
            saw_digit = 1;
362
937k
            nonzero_seen = 1;
363
937k
            if (sig_digits < 19) {
364
791k
                sig = sig * 10u + (uint64_t)d;
365
791k
                ++sig_digits;
366
791k
            } else if (extra_digits < 64) {
367
146k
                extra = extra * 10.0L + (long double)d;
368
146k
                ++extra_digits;
369
146k
            } else {
370
20
                ++exp10;
371
20
            }
372
937k
            ++p;
373
937k
        } while (p < end && *p >= '0' && *p <= '9');
374
94.5k
    } else {
375
0
        return 0;
376
0
    }
377
98.5k
    if (p < end && *p == '.') {
378
46.5k
        ++p;
379
46.5k
        if (p >= end || *p < '0' || *p > '9') return 0;
380
2.37M
        do {
381
2.37M
            int d = *p - '0';
382
2.37M
            saw_digit = 1;
383
2.37M
            if (d != 0 || nonzero_seen) {
384
2.36M
                nonzero_seen = nonzero_seen || (d != 0);
385
2.36M
                if (sig_digits < 19) {
386
263k
                    sig = sig * 10u + (uint64_t)d;
387
263k
                    ++sig_digits;
388
263k
                    --exp10;
389
2.09M
                } else if (extra_digits < 64) {
390
69.4k
                    extra = extra * 10.0L + (long double)d;
391
69.4k
                    ++extra_digits;
392
69.4k
                    --exp10;
393
2.02M
                } else {
394
2.02M
                    --exp10;
395
2.02M
                }
396
2.36M
            } else {
397
14.0k
                --exp10;
398
14.0k
            }
399
2.37M
            ++p;
400
2.37M
        } while (p < end && *p >= '0' && *p <= '9');
401
46.5k
    }
402
98.5k
    if (!saw_digit) return 0;
403
98.5k
    if (p < end && (*p == 'e' || *p == 'E')) {
404
62.0k
        ++p;
405
62.0k
        if (p < end && (*p == '+' || *p == '-')) {
406
39.2k
            exp_sign = (*p == '-') ? -1 : 1;
407
39.2k
            ++p;
408
39.2k
        }
409
62.0k
        if (p >= end || *p < '0' || *p > '9') return 0;
410
263k
        while (p < end && *p >= '0' && *p <= '9') {
411
201k
            if (exp_lit < 10000) exp_lit = exp_lit * 10 + (*p - '0');
412
201k
            ++p;
413
201k
        }
414
62.0k
        exp10 += exp_sign * exp_lit;
415
62.0k
    }
416
98.5k
    if (p != end) return 0;
417
98.5k
    if (!nonzero_seen || sig_digits == 0) {
418
3.54k
        *out = neg ? tg3json__double_from_bits(0x8000000000000000ULL) : 0.0;
419
3.54k
        return 1;
420
3.54k
    }
421
94.9k
    if (exp10 > 309) return 0;
422
94.9k
    if (exp10 < -4000) {
423
13.3k
        *out = neg ? tg3json__double_from_bits(0x8000000000000000ULL) : 0.0;
424
13.3k
        return 1;
425
13.3k
    }
426
81.6k
    v = (long double)sig;
427
81.6k
    if (extra_digits > 0) {
428
38.5k
        v = v * tg3json__pow10_ld(extra_digits) + extra;
429
38.5k
    }
430
81.6k
    if (exp10 != 0) v *= tg3json__pow10_ld(exp10);
431
81.6k
    if (neg) v = -v;
432
81.6k
    *out = (double)v;
433
81.6k
    if (tg3json__is_inf_bits(tg3json__double_bits(*out))) return 0;
434
81.6k
    return 1;
435
81.6k
#endif
436
81.6k
}
tiny_gltf_v3.c:tg3json__parse_f64_c
Line
Count
Source
315
466k
static int tg3json__parse_f64_c(const char *start, const char *end, double *out) {
316
#if TG3JSON_USE_STDLIB_FPCONV
317
    size_t len = (size_t)(end - start);
318
    char stack_buf[128];
319
    char *buf = stack_buf;
320
    char *parse_end = NULL;
321
    double v;
322
    if (len + 1 > sizeof(stack_buf)) {
323
        buf = (char *)TINYGLTF_JSON_MALLOC(len + 1);
324
        if (!buf) return 0;
325
    }
326
    if (len > 0) TINYGLTF_JSON_MEMCPY(buf, start, len);
327
    buf[len] = '\0';
328
    v = strtod(buf, &parse_end);
329
    if (parse_end != buf + len || tg3json__is_inf_bits(tg3json__double_bits(v))) {
330
        if (buf != stack_buf) TINYGLTF_JSON_FREE(buf);
331
        return 0;
332
    }
333
    if (buf != stack_buf) TINYGLTF_JSON_FREE(buf);
334
    *out = v;
335
    return 1;
336
#else
337
466k
    const char *p = start;
338
466k
    int neg = 0;
339
466k
    int saw_digit = 0;
340
466k
    int nonzero_seen = 0;
341
466k
    int exp10 = 0;
342
466k
    uint64_t sig = 0;
343
466k
    int sig_digits = 0;
344
466k
    long double extra = 0.0L;
345
466k
    int extra_digits = 0;
346
466k
    int exp_sign = 1;
347
466k
    int exp_lit = 0;
348
466k
    long double v;
349
350
466k
    if (p < end && *p == '-') {
351
25.5k
        neg = 1;
352
25.5k
        ++p;
353
25.5k
    }
354
466k
    if (p >= end) return 0;
355
466k
    if (*p == '0') {
356
130k
        saw_digit = 1;
357
130k
        ++p;
358
335k
    } else if (*p >= '1' && *p <= '9') {
359
7.89M
        do {
360
7.89M
            int d = *p - '0';
361
7.89M
            saw_digit = 1;
362
7.89M
            nonzero_seen = 1;
363
7.89M
            if (sig_digits < 19) {
364
5.84M
                sig = sig * 10u + (uint64_t)d;
365
5.84M
                ++sig_digits;
366
5.84M
            } else if (extra_digits < 64) {
367
2.05M
                extra = extra * 10.0L + (long double)d;
368
2.05M
                ++extra_digits;
369
2.05M
            } else {
370
2.62k
                ++exp10;
371
2.62k
            }
372
7.89M
            ++p;
373
7.89M
        } while (p < end && *p >= '0' && *p <= '9');
374
335k
    } else {
375
0
        return 0;
376
0
    }
377
466k
    if (p < end && *p == '.') {
378
139k
        ++p;
379
139k
        if (p >= end || *p < '0' || *p > '9') return 0;
380
1.02M
        do {
381
1.02M
            int d = *p - '0';
382
1.02M
            saw_digit = 1;
383
1.02M
            if (d != 0 || nonzero_seen) {
384
998k
                nonzero_seen = nonzero_seen || (d != 0);
385
998k
                if (sig_digits < 19) {
386
310k
                    sig = sig * 10u + (uint64_t)d;
387
310k
                    ++sig_digits;
388
310k
                    --exp10;
389
687k
                } else if (extra_digits < 64) {
390
3.20k
                    extra = extra * 10.0L + (long double)d;
391
3.20k
                    ++extra_digits;
392
3.20k
                    --exp10;
393
684k
                } else {
394
684k
                    --exp10;
395
684k
                }
396
998k
            } else {
397
25.1k
                --exp10;
398
25.1k
            }
399
1.02M
            ++p;
400
1.02M
        } while (p < end && *p >= '0' && *p <= '9');
401
139k
    }
402
466k
    if (!saw_digit) return 0;
403
466k
    if (p < end && (*p == 'e' || *p == 'E')) {
404
23.1k
        ++p;
405
23.1k
        if (p < end && (*p == '+' || *p == '-')) {
406
153
            exp_sign = (*p == '-') ? -1 : 1;
407
153
            ++p;
408
153
        }
409
23.1k
        if (p >= end || *p < '0' || *p > '9') return 0;
410
62.6k
        while (p < end && *p >= '0' && *p <= '9') {
411
39.4k
            if (exp_lit < 10000) exp_lit = exp_lit * 10 + (*p - '0');
412
39.4k
            ++p;
413
39.4k
        }
414
23.1k
        exp10 += exp_sign * exp_lit;
415
23.1k
    }
416
466k
    if (p != end) return 0;
417
466k
    if (!nonzero_seen || sig_digits == 0) {
418
8.71k
        *out = neg ? tg3json__double_from_bits(0x8000000000000000ULL) : 0.0;
419
8.71k
        return 1;
420
8.71k
    }
421
457k
    if (exp10 > 309) return 0;
422
457k
    if (exp10 < -4000) {
423
30
        *out = neg ? tg3json__double_from_bits(0x8000000000000000ULL) : 0.0;
424
30
        return 1;
425
30
    }
426
457k
    v = (long double)sig;
427
457k
    if (extra_digits > 0) {
428
303k
        v = v * tg3json__pow10_ld(extra_digits) + extra;
429
303k
    }
430
457k
    if (exp10 != 0) v *= tg3json__pow10_ld(exp10);
431
457k
    if (neg) v = -v;
432
457k
    *out = (double)v;
433
457k
    if (tg3json__is_inf_bits(tg3json__double_bits(*out))) return 0;
434
457k
    return 1;
435
457k
#endif
436
457k
}
437
438
#if !TG3JSON_USE_STDLIB_FPCONV
439
0
static char *tg3json__write_exp(char *p, int exp10) {
440
0
    char tmp[16];
441
0
    size_t n;
442
0
    *p++ = 'e';
443
0
    if (exp10 < 0) {
444
0
        *p++ = '-';
445
0
        exp10 = -exp10;
446
0
    }
447
0
    n = tg3json__utoa((uint64_t)exp10, tmp);
448
0
    TINYGLTF_JSON_MEMCPY(p, tmp, n);
449
0
    return p + n;
450
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__write_exp(char*, int)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__write_exp
451
452
static char *tg3json__format_decimal_digits(char *out, const char *digits,
453
                                            int ndigits, int dec_exp,
454
0
                                            int negative) {
455
0
    char *p = out;
456
0
    int i;
457
0
    int output_exp = dec_exp + ndigits - 1;
458
0
    if (negative) *p++ = '-';
459
0
    if (output_exp < -4 || output_exp >= 16) {
460
0
        *p++ = digits[0];
461
0
        if (ndigits > 1) {
462
0
            *p++ = '.';
463
0
            for (i = 1; i < ndigits; ++i) *p++ = digits[i];
464
0
        }
465
0
        return tg3json__write_exp(p, output_exp);
466
0
    }
467
0
    if (dec_exp >= 0) {
468
0
        for (i = 0; i < ndigits; ++i) *p++ = digits[i];
469
0
        for (i = 0; i < dec_exp; ++i) *p++ = '0';
470
0
        return p;
471
0
    }
472
0
    if (dec_exp + ndigits > 0) {
473
0
        int int_digits = dec_exp + ndigits;
474
0
        for (i = 0; i < int_digits; ++i) *p++ = digits[i];
475
0
        *p++ = '.';
476
0
        for (; i < ndigits; ++i) *p++ = digits[i];
477
0
        return p;
478
0
    }
479
0
    *p++ = '0';
480
0
    *p++ = '.';
481
0
    for (i = 0; i < -(dec_exp + ndigits); ++i) *p++ = '0';
482
0
    for (i = 0; i < ndigits; ++i) *p++ = digits[i];
483
0
    return p;
484
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__format_decimal_digits(char*, char const*, int, int, int)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__format_decimal_digits
485
#endif  /* !TG3JSON_USE_STDLIB_FPCONV */
486
487
0
static int tg3json__same_f64(double a, double b) {
488
0
    return tg3json__double_bits(a) == tg3json__double_bits(b);
489
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__same_f64(double, double)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__same_f64
490
491
#if TG3JSON_USE_STDLIB_FPCONV
492
static void tg3json__normalize_exponent(char *s) {
493
    char *e = s;
494
    char *dst;
495
    int neg = 0;
496
    while (*e && *e != 'e' && *e != 'E') ++e;
497
    if (!*e) return;
498
    *e++ = 'e';
499
    dst = e;
500
    if (*e == '+' || *e == '-') {
501
        neg = (*e == '-');
502
        ++e;
503
    }
504
    while (*e == '0') ++e;
505
    if (neg) *dst++ = '-';
506
    if (!*e) {
507
        *dst++ = '0';
508
    } else {
509
        while (*e) *dst++ = *e++;
510
    }
511
    *dst = '\0';
512
}
513
514
static void tg3json__expand_short_plain_decimal(char *s) {
515
    char *p = s;
516
    char *e;
517
    char digits[32];
518
    char out[96];
519
    int negative = 0;
520
    int ndigits = 0;
521
    int int_digits = 0;
522
    int exp10 = 0;
523
    int new_point;
524
    int i;
525
    char *q = out;
526
527
    if (*p == '-') {
528
        negative = 1;
529
        ++p;
530
    }
531
    e = p;
532
    while (*e && *e != 'e') ++e;
533
    if (!*e) return;
534
    for (; p < e; ++p) {
535
        if (*p == '.') {
536
            int_digits = ndigits;
537
        } else {
538
            if (ndigits < (int)(sizeof(digits) - 1)) digits[ndigits++] = *p;
539
        }
540
    }
541
    if (int_digits == 0) int_digits = ndigits;
542
    ++e;
543
    if (*e == '-') {
544
        int sign = -1;
545
        ++e;
546
        while (*e >= '0' && *e <= '9') exp10 = exp10 * 10 + (*e++ - '0');
547
        exp10 *= sign;
548
    } else {
549
        while (*e >= '0' && *e <= '9') exp10 = exp10 * 10 + (*e++ - '0');
550
    }
551
    if (exp10 < -4 || exp10 >= 16) return;
552
553
    new_point = int_digits + exp10;
554
    if (negative) *q++ = '-';
555
    if (new_point <= 0) {
556
        *q++ = '0';
557
        *q++ = '.';
558
        for (i = 0; i < -new_point; ++i) *q++ = '0';
559
        for (i = 0; i < ndigits; ++i) *q++ = digits[i];
560
    } else if (new_point >= ndigits) {
561
        for (i = 0; i < ndigits; ++i) *q++ = digits[i];
562
        for (i = ndigits; i < new_point; ++i) *q++ = '0';
563
    } else {
564
        for (i = 0; i < new_point; ++i) *q++ = digits[i];
565
        *q++ = '.';
566
        for (; i < ndigits; ++i) *q++ = digits[i];
567
    }
568
    *q = '\0';
569
    if (q > out) {
570
        char *dot = out;
571
        while (*dot && *dot != '.') ++dot;
572
        if (*dot == '.') {
573
            char *end = q - 1;
574
            while (end > dot && *end == '0') *end-- = '\0';
575
            if (end == dot) *end = '\0';
576
        }
577
    }
578
    TINYGLTF_JSON_MEMCPY(s, out, (size_t)(TINYGLTF_JSON_STRLEN(out) + 1));
579
}
580
#endif
581
582
0
static char *tg3json__dtoa_c(double value, char *buf) {
583
0
    uint64_t bits = tg3json__double_bits(value);
584
0
    int negative = (int)(bits >> 63);
585
0
    uint64_t abits = bits & 0x7fffffffffffffffULL;
586
0
#if !TG3JSON_USE_STDLIB_FPCONV
587
0
    long double x;
588
0
    int dec_e = 0;
589
0
    char digits[24];
590
0
    int ndigits = 17;
591
0
    int i;
592
0
    char best[80];
593
0
    size_t best_len;
594
0
#endif
595
596
0
    if (tg3json__is_nan_bits(bits)) {
597
0
        TINYGLTF_JSON_MEMCPY(buf, "nan", 3);
598
0
        return buf + 3;
599
0
    }
600
0
    if (tg3json__is_inf_bits(bits)) {
601
0
        if (negative) {
602
0
            TINYGLTF_JSON_MEMCPY(buf, "-inf", 4);
603
0
            return buf + 4;
604
0
        }
605
0
        TINYGLTF_JSON_MEMCPY(buf, "inf", 3);
606
0
        return buf + 3;
607
0
    }
608
0
    if (abits == 0) {
609
0
        *buf++ = '0';
610
0
        return buf;
611
0
    }
612
0
    if (bits == 0x3ff0000000000000ULL) {
613
0
        *buf++ = '1';
614
0
        return buf;
615
0
    }
616
0
    if (bits == 0xbff0000000000000ULL) {
617
0
        *buf++ = '-';
618
0
        *buf++ = '1';
619
0
        return buf;
620
0
    }
621
622
#if TG3JSON_USE_STDLIB_FPCONV
623
    {
624
        int precision;
625
        char candidate[96];
626
        char shortest[96];
627
        shortest[0] = '\0';
628
        for (precision = 1; precision <= 17; ++precision) {
629
            char fmt[8];
630
            double parsed = 0.0;
631
            int n;
632
            n = snprintf(fmt, sizeof(fmt), "%%.%dg", precision);
633
            if (n <= 0 || n >= (int)sizeof(fmt)) continue;
634
            n = snprintf(candidate, sizeof(candidate), fmt, value);
635
            if (n <= 0 || n >= (int)sizeof(candidate)) continue;
636
            tg3json__normalize_exponent(candidate);
637
            tg3json__expand_short_plain_decimal(candidate);
638
            if (tg3json__parse_f64_c(candidate, candidate + TINYGLTF_JSON_STRLEN(candidate), &parsed) &&
639
                tg3json__same_f64(parsed, value)) {
640
                TINYGLTF_JSON_MEMCPY(shortest, candidate, TINYGLTF_JSON_STRLEN(candidate) + 1);
641
                break;
642
            }
643
        }
644
        if (!shortest[0]) {
645
            int n = snprintf(shortest, sizeof(shortest), "%.17g", value);
646
            if (n <= 0 || n >= (int)sizeof(shortest)) return buf;
647
            tg3json__normalize_exponent(shortest);
648
            tg3json__expand_short_plain_decimal(shortest);
649
        }
650
        TINYGLTF_JSON_MEMCPY(buf, shortest, TINYGLTF_JSON_STRLEN(shortest));
651
        return buf + TINYGLTF_JSON_STRLEN(shortest);
652
    }
653
#else
654
655
0
    x = negative ? -(long double)value : (long double)value;
656
0
    while (x >= 1.0e16L) {
657
0
        x *= 1.0e-16L;
658
0
        dec_e += 16;
659
0
    }
660
0
    while (x >= 10.0L) {
661
0
        x *= 0.1L;
662
0
        ++dec_e;
663
0
    }
664
0
    while (x < 1.0L) {
665
0
        x *= 10.0L;
666
0
        --dec_e;
667
0
    }
668
0
    for (i = 0; i < 18; ++i) {
669
0
        int d = (int)x;
670
0
        if (d < 0) d = 0;
671
0
        if (d > 9) d = 9;
672
0
        digits[i] = (char)('0' + d);
673
0
        x = (x - (long double)d) * 10.0L;
674
0
    }
675
0
    if (digits[17] >= '5') {
676
0
        int carry = 1;
677
0
        for (i = 16; i >= 0 && carry; --i) {
678
0
            if (digits[i] == '9') {
679
0
                digits[i] = '0';
680
0
            } else {
681
0
                digits[i]++;
682
0
                carry = 0;
683
0
            }
684
0
        }
685
0
        if (carry) {
686
0
            digits[0] = '1';
687
0
            for (i = 1; i < 17; ++i) digits[i] = '0';
688
0
            ++dec_e;
689
0
        }
690
0
    }
691
0
    while (ndigits > 1 && digits[ndigits - 1] == '0') --ndigits;
692
693
0
    {
694
0
        char *end = tg3json__format_decimal_digits(best, digits, ndigits,
695
0
                                                   dec_e - ndigits + 1,
696
0
                                                   negative);
697
0
        *end = '\0';
698
0
        best_len = (size_t)(end - best);
699
0
    }
700
0
    for (i = ndigits - 1; i >= 1; --i) {
701
0
        char candidate[80];
702
0
        char *end;
703
0
        double parsed = 0.0;
704
0
        end = tg3json__format_decimal_digits(candidate, digits, i,
705
0
                                             dec_e - i + 1, negative);
706
0
        *end = '\0';
707
0
        if (tg3json__parse_f64_c(candidate, end, &parsed) &&
708
0
            tg3json__same_f64(parsed, value)) {
709
0
            TINYGLTF_JSON_MEMCPY(best, candidate, (size_t)(end - candidate) + 1);
710
0
            best_len = (size_t)(end - candidate);
711
0
        } else {
712
0
            break;
713
0
        }
714
0
    }
715
0
    TINYGLTF_JSON_MEMCPY(buf, best, best_len);
716
0
    return buf + best_len;
717
0
#endif
718
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__dtoa_c(double, char*)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__dtoa_c
719
720
typedef struct tg3json__parser {
721
    const char *cur;
722
    const char *end;
723
    const char *error;
724
    size_t depth_limit;
725
    size_t memory_budget;
726
    size_t max_single_alloc;
727
    size_t max_string_length;
728
    size_t allocated;
729
    int parse_float32;
730
} tg3json__parser;
731
732
typedef struct tg3json__buffer {
733
    tg3json__parser *parser;
734
    char *data;
735
    size_t len;
736
    size_t cap;
737
} tg3json__buffer;
738
739
35.4M
static void tg3json__init_value(tg3json_value *value) {
740
35.4M
    if (!value) return;
741
35.4M
    TINYGLTF_JSON_MEMSET(value, 0, sizeof(*value));
742
35.4M
    value->type = TG3JSON_NULL;
743
35.4M
}
fuzz_gltf_v3.cc:tg3json__init_value(tg3json_value*)
Line
Count
Source
739
10.2M
static void tg3json__init_value(tg3json_value *value) {
740
10.2M
    if (!value) return;
741
10.2M
    TINYGLTF_JSON_MEMSET(value, 0, sizeof(*value));
742
10.2M
    value->type = TG3JSON_NULL;
743
10.2M
}
tiny_gltf_v3.c:tg3json__init_value
Line
Count
Source
739
25.1M
static void tg3json__init_value(tg3json_value *value) {
740
25.1M
    if (!value) return;
741
25.1M
    TINYGLTF_JSON_MEMSET(value, 0, sizeof(*value));
742
25.1M
    value->type = TG3JSON_NULL;
743
25.1M
}
744
745
0
static char *tg3json__strndup_local(const char *src, size_t len) {
746
0
    char *dst = (char *)TINYGLTF_JSON_MALLOC(len + 1);
747
0
    if (!dst) return NULL;
748
0
    if (len > 0) TINYGLTF_JSON_MEMCPY(dst, src, len);
749
0
    dst[len] = '\0';
750
0
    return dst;
751
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__strndup_local(char const*, unsigned long)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__strndup_local
752
753
1.12M
static void *tg3json__parser_alloc(tg3json__parser *parser, size_t size) {
754
1.12M
    void *ptr;
755
1.12M
    if (!parser) return TINYGLTF_JSON_MALLOC(size);
756
1.12M
    if (parser->max_single_alloc && size > parser->max_single_alloc) return NULL;
757
1.12M
    if (parser->memory_budget &&
758
1.12M
        (size > parser->memory_budget || parser->allocated > parser->memory_budget - size)) {
759
0
        return NULL;
760
0
    }
761
1.12M
    ptr = TINYGLTF_JSON_MALLOC(size);
762
1.12M
    if (!ptr) return NULL;
763
1.12M
    parser->allocated += size;
764
1.12M
    return ptr;
765
1.12M
}
fuzz_gltf_v3.cc:tg3json__parser_alloc(tg3json__parser*, unsigned long)
Line
Count
Source
753
38.5k
static void *tg3json__parser_alloc(tg3json__parser *parser, size_t size) {
754
38.5k
    void *ptr;
755
38.5k
    if (!parser) return TINYGLTF_JSON_MALLOC(size);
756
38.5k
    if (parser->max_single_alloc && size > parser->max_single_alloc) return NULL;
757
38.5k
    if (parser->memory_budget &&
758
38.5k
        (size > parser->memory_budget || parser->allocated > parser->memory_budget - size)) {
759
0
        return NULL;
760
0
    }
761
38.5k
    ptr = TINYGLTF_JSON_MALLOC(size);
762
38.5k
    if (!ptr) return NULL;
763
38.5k
    parser->allocated += size;
764
38.5k
    return ptr;
765
38.5k
}
tiny_gltf_v3.c:tg3json__parser_alloc
Line
Count
Source
753
1.08M
static void *tg3json__parser_alloc(tg3json__parser *parser, size_t size) {
754
1.08M
    void *ptr;
755
1.08M
    if (!parser) return TINYGLTF_JSON_MALLOC(size);
756
1.08M
    if (parser->max_single_alloc && size > parser->max_single_alloc) return NULL;
757
1.08M
    if (parser->memory_budget &&
758
1.08M
        (size > parser->memory_budget || parser->allocated > parser->memory_budget - size)) {
759
0
        return NULL;
760
0
    }
761
1.08M
    ptr = TINYGLTF_JSON_MALLOC(size);
762
1.08M
    if (!ptr) return NULL;
763
1.08M
    parser->allocated += size;
764
1.08M
    return ptr;
765
1.08M
}
766
767
static int tg3json__reserve_bytes(void **ptr, size_t elem_size,
768
0
                                  size_t needed, size_t *capacity) {
769
0
    void *new_ptr;
770
0
    size_t new_cap;
771
772
0
    if (needed <= *capacity) return 1;
773
0
    new_cap = (*capacity > 0) ? *capacity : 8;
774
0
    while (new_cap < needed) {
775
0
        if (new_cap > ((size_t)-1) / 2) {
776
0
            new_cap = needed;
777
0
            break;
778
0
        }
779
0
        new_cap *= 2;
780
0
    }
781
782
0
    if (elem_size != 0 && new_cap > ((size_t)-1) / elem_size) return 0;
783
0
    new_ptr = TINYGLTF_JSON_REALLOC(*ptr, elem_size * new_cap);
784
0
    if (!new_ptr) return 0;
785
0
    *ptr = new_ptr;
786
0
    *capacity = new_cap;
787
0
    return 1;
788
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__reserve_bytes(void**, unsigned long, unsigned long, unsigned long*)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__reserve_bytes
789
790
static int tg3json__reserve_bytes_parser(tg3json__parser *parser, void **ptr,
791
                                         size_t elem_size, size_t needed,
792
19.5M
                                         size_t *capacity) {
793
19.5M
    void *new_ptr;
794
19.5M
    size_t new_cap;
795
19.5M
    size_t old_bytes;
796
19.5M
    size_t new_bytes;
797
798
19.5M
    if (needed <= *capacity) return 1;
799
1.41M
    new_cap = (*capacity > 0) ? *capacity : 8;
800
2.29M
    while (new_cap < needed) {
801
881k
        if (new_cap > ((size_t)-1) / 2) {
802
0
            new_cap = needed;
803
0
            break;
804
0
        }
805
881k
        new_cap *= 2;
806
881k
    }
807
808
1.41M
    if (elem_size != 0 && new_cap > ((size_t)-1) / elem_size) return 0;
809
1.41M
    old_bytes = elem_size * (*capacity);
810
1.41M
    new_bytes = elem_size * new_cap;
811
1.41M
    if (parser) {
812
1.41M
        size_t delta = (new_bytes > old_bytes) ? (new_bytes - old_bytes) : 0;
813
1.41M
        if (parser->max_single_alloc && new_bytes > parser->max_single_alloc) return 0;
814
1.41M
        if (parser->memory_budget && delta > 0 &&
815
1.41M
            (delta > parser->memory_budget ||
816
1.41M
             parser->allocated > parser->memory_budget - delta)) {
817
0
            return 0;
818
0
        }
819
1.41M
    }
820
1.41M
    new_ptr = TINYGLTF_JSON_REALLOC(*ptr, new_bytes);
821
1.41M
    if (!new_ptr) return 0;
822
1.41M
    if (parser && new_bytes > old_bytes) parser->allocated += new_bytes - old_bytes;
823
1.41M
    *ptr = new_ptr;
824
1.41M
    *capacity = new_cap;
825
1.41M
    return 1;
826
1.41M
}
fuzz_gltf_v3.cc:tg3json__reserve_bytes_parser(tg3json__parser*, void**, unsigned long, unsigned long, unsigned long*)
Line
Count
Source
792
5.16M
                                         size_t *capacity) {
793
5.16M
    void *new_ptr;
794
5.16M
    size_t new_cap;
795
5.16M
    size_t old_bytes;
796
5.16M
    size_t new_bytes;
797
798
5.16M
    if (needed <= *capacity) return 1;
799
33.9k
    new_cap = (*capacity > 0) ? *capacity : 8;
800
69.2k
    while (new_cap < needed) {
801
35.2k
        if (new_cap > ((size_t)-1) / 2) {
802
0
            new_cap = needed;
803
0
            break;
804
0
        }
805
35.2k
        new_cap *= 2;
806
35.2k
    }
807
808
33.9k
    if (elem_size != 0 && new_cap > ((size_t)-1) / elem_size) return 0;
809
33.9k
    old_bytes = elem_size * (*capacity);
810
33.9k
    new_bytes = elem_size * new_cap;
811
33.9k
    if (parser) {
812
33.9k
        size_t delta = (new_bytes > old_bytes) ? (new_bytes - old_bytes) : 0;
813
33.9k
        if (parser->max_single_alloc && new_bytes > parser->max_single_alloc) return 0;
814
33.9k
        if (parser->memory_budget && delta > 0 &&
815
33.9k
            (delta > parser->memory_budget ||
816
33.9k
             parser->allocated > parser->memory_budget - delta)) {
817
0
            return 0;
818
0
        }
819
33.9k
    }
820
33.9k
    new_ptr = TINYGLTF_JSON_REALLOC(*ptr, new_bytes);
821
33.9k
    if (!new_ptr) return 0;
822
33.9k
    if (parser && new_bytes > old_bytes) parser->allocated += new_bytes - old_bytes;
823
33.9k
    *ptr = new_ptr;
824
33.9k
    *capacity = new_cap;
825
33.9k
    return 1;
826
33.9k
}
tiny_gltf_v3.c:tg3json__reserve_bytes_parser
Line
Count
Source
792
14.3M
                                         size_t *capacity) {
793
14.3M
    void *new_ptr;
794
14.3M
    size_t new_cap;
795
14.3M
    size_t old_bytes;
796
14.3M
    size_t new_bytes;
797
798
14.3M
    if (needed <= *capacity) return 1;
799
1.37M
    new_cap = (*capacity > 0) ? *capacity : 8;
800
2.22M
    while (new_cap < needed) {
801
846k
        if (new_cap > ((size_t)-1) / 2) {
802
0
            new_cap = needed;
803
0
            break;
804
0
        }
805
846k
        new_cap *= 2;
806
846k
    }
807
808
1.37M
    if (elem_size != 0 && new_cap > ((size_t)-1) / elem_size) return 0;
809
1.37M
    old_bytes = elem_size * (*capacity);
810
1.37M
    new_bytes = elem_size * new_cap;
811
1.37M
    if (parser) {
812
1.37M
        size_t delta = (new_bytes > old_bytes) ? (new_bytes - old_bytes) : 0;
813
1.37M
        if (parser->max_single_alloc && new_bytes > parser->max_single_alloc) return 0;
814
1.37M
        if (parser->memory_budget && delta > 0 &&
815
1.37M
            (delta > parser->memory_budget ||
816
1.37M
             parser->allocated > parser->memory_budget - delta)) {
817
0
            return 0;
818
0
        }
819
1.37M
    }
820
1.37M
    new_ptr = TINYGLTF_JSON_REALLOC(*ptr, new_bytes);
821
1.37M
    if (!new_ptr) return 0;
822
1.37M
    if (parser && new_bytes > old_bytes) parser->allocated += new_bytes - old_bytes;
823
1.37M
    *ptr = new_ptr;
824
1.37M
    *capacity = new_cap;
825
1.37M
    return 1;
826
1.37M
}
827
828
55.5M
static const char *tg3json__skip_ws(const char *p, const char *end) {
829
58.9M
    while (p < end) {
830
58.9M
        unsigned char c = (unsigned char)*p;
831
58.9M
        if (c != ' ' && c != '\n' && c != '\r' && c != '\t') break;
832
3.39M
        ++p;
833
3.39M
    }
834
55.5M
    return p;
835
55.5M
}
fuzz_gltf_v3.cc:tg3json__skip_ws(char const*, char const*)
Line
Count
Source
828
15.4M
static const char *tg3json__skip_ws(const char *p, const char *end) {
829
15.4M
    while (p < end) {
830
15.4M
        unsigned char c = (unsigned char)*p;
831
15.4M
        if (c != ' ' && c != '\n' && c != '\r' && c != '\t') break;
832
331
        ++p;
833
331
    }
834
15.4M
    return p;
835
15.4M
}
tiny_gltf_v3.c:tg3json__skip_ws
Line
Count
Source
828
40.0M
static const char *tg3json__skip_ws(const char *p, const char *end) {
829
43.4M
    while (p < end) {
830
43.4M
        unsigned char c = (unsigned char)*p;
831
43.4M
        if (c != ' ' && c != '\n' && c != '\r' && c != '\t') break;
832
3.39M
        ++p;
833
3.39M
    }
834
40.0M
    return p;
835
40.0M
}
836
837
106
static void tg3json__set_error(tg3json__parser *parser, const char *pos) {
838
106
    if (!parser->error) parser->error = pos;
839
106
}
fuzz_gltf_v3.cc:tg3json__set_error(tg3json__parser*, char const*)
Line
Count
Source
837
17
static void tg3json__set_error(tg3json__parser *parser, const char *pos) {
838
17
    if (!parser->error) parser->error = pos;
839
17
}
tiny_gltf_v3.c:tg3json__set_error
Line
Count
Source
837
89
static void tg3json__set_error(tg3json__parser *parser, const char *pos) {
838
89
    if (!parser->error) parser->error = pos;
839
89
}
840
841
1.62M
static int tg3json__buf_append(tg3json__buffer *buf, const char *src, size_t len) {
842
1.62M
    if (len == 0) return 1;
843
1.46M
    if (!tg3json__reserve_bytes_parser(buf->parser, (void **)&buf->data, 1,
844
1.46M
                                       buf->len + len + 1, &buf->cap)) {
845
0
        return 0;
846
0
    }
847
1.46M
    TINYGLTF_JSON_MEMCPY(buf->data + buf->len, src, len);
848
1.46M
    buf->len += len;
849
1.46M
    buf->data[buf->len] = '\0';
850
1.46M
    return 1;
851
1.46M
}
fuzz_gltf_v3.cc:tg3json__buf_append(tg3json__buffer*, char const*, unsigned long)
Line
Count
Source
841
38.6k
static int tg3json__buf_append(tg3json__buffer *buf, const char *src, size_t len) {
842
38.6k
    if (len == 0) return 1;
843
33.4k
    if (!tg3json__reserve_bytes_parser(buf->parser, (void **)&buf->data, 1,
844
33.4k
                                       buf->len + len + 1, &buf->cap)) {
845
0
        return 0;
846
0
    }
847
33.4k
    TINYGLTF_JSON_MEMCPY(buf->data + buf->len, src, len);
848
33.4k
    buf->len += len;
849
33.4k
    buf->data[buf->len] = '\0';
850
33.4k
    return 1;
851
33.4k
}
tiny_gltf_v3.c:tg3json__buf_append
Line
Count
Source
841
1.58M
static int tg3json__buf_append(tg3json__buffer *buf, const char *src, size_t len) {
842
1.58M
    if (len == 0) return 1;
843
1.43M
    if (!tg3json__reserve_bytes_parser(buf->parser, (void **)&buf->data, 1,
844
1.43M
                                       buf->len + len + 1, &buf->cap)) {
845
0
        return 0;
846
0
    }
847
1.43M
    TINYGLTF_JSON_MEMCPY(buf->data + buf->len, src, len);
848
1.43M
    buf->len += len;
849
1.43M
    buf->data[buf->len] = '\0';
850
1.43M
    return 1;
851
1.43M
}
852
853
356k
static int tg3json__buf_putc(tg3json__buffer *buf, char c) {
854
356k
    if (!tg3json__reserve_bytes_parser(buf->parser, (void **)&buf->data, 1,
855
356k
                                       buf->len + 2, &buf->cap)) {
856
0
        return 0;
857
0
    }
858
356k
    buf->data[buf->len++] = c;
859
356k
    buf->data[buf->len] = '\0';
860
356k
    return 1;
861
356k
}
fuzz_gltf_v3.cc:tg3json__buf_putc(tg3json__buffer*, char)
Line
Count
Source
853
19
static int tg3json__buf_putc(tg3json__buffer *buf, char c) {
854
19
    if (!tg3json__reserve_bytes_parser(buf->parser, (void **)&buf->data, 1,
855
19
                                       buf->len + 2, &buf->cap)) {
856
0
        return 0;
857
0
    }
858
19
    buf->data[buf->len++] = c;
859
19
    buf->data[buf->len] = '\0';
860
19
    return 1;
861
19
}
tiny_gltf_v3.c:tg3json__buf_putc
Line
Count
Source
853
356k
static int tg3json__buf_putc(tg3json__buffer *buf, char c) {
854
356k
    if (!tg3json__reserve_bytes_parser(buf->parser, (void **)&buf->data, 1,
855
356k
                                       buf->len + 2, &buf->cap)) {
856
0
        return 0;
857
0
    }
858
356k
    buf->data[buf->len++] = c;
859
356k
    buf->data[buf->len] = '\0';
860
356k
    return 1;
861
356k
}
862
863
110k
static int tg3json__hex4(const char *p, uint32_t *out) {
864
110k
    uint32_t value = 0;
865
110k
    size_t i;
866
402k
    for (i = 0; i < 4; ++i) {
867
351k
        unsigned char c = (unsigned char)p[i];
868
351k
        value <<= 4;
869
351k
        if (c >= '0' && c <= '9') value |= (uint32_t)(c - '0');
870
271k
        else if (c >= 'a' && c <= 'f') value |= (uint32_t)(10 + c - 'a');
871
213k
        else if (c >= 'A' && c <= 'F') value |= (uint32_t)(10 + c - 'A');
872
60.0k
        else return 0;
873
351k
    }
874
50.7k
    *out = value;
875
50.7k
    return 1;
876
110k
}
fuzz_gltf_v3.cc:tg3json__hex4(char const*, unsigned int*)
Line
Count
Source
863
156
static int tg3json__hex4(const char *p, uint32_t *out) {
864
156
    uint32_t value = 0;
865
156
    size_t i;
866
662
    for (i = 0; i < 4; ++i) {
867
538
        unsigned char c = (unsigned char)p[i];
868
538
        value <<= 4;
869
538
        if (c >= '0' && c <= '9') value |= (uint32_t)(c - '0');
870
520
        else if (c >= 'a' && c <= 'f') value |= (uint32_t)(10 + c - 'a');
871
33
        else if (c >= 'A' && c <= 'F') value |= (uint32_t)(10 + c - 'A');
872
32
        else return 0;
873
538
    }
874
124
    *out = value;
875
124
    return 1;
876
156
}
tiny_gltf_v3.c:tg3json__hex4
Line
Count
Source
863
110k
static int tg3json__hex4(const char *p, uint32_t *out) {
864
110k
    uint32_t value = 0;
865
110k
    size_t i;
866
402k
    for (i = 0; i < 4; ++i) {
867
351k
        unsigned char c = (unsigned char)p[i];
868
351k
        value <<= 4;
869
351k
        if (c >= '0' && c <= '9') value |= (uint32_t)(c - '0');
870
270k
        else if (c >= 'a' && c <= 'f') value |= (uint32_t)(10 + c - 'a');
871
213k
        else if (c >= 'A' && c <= 'F') value |= (uint32_t)(10 + c - 'A');
872
60.0k
        else return 0;
873
351k
    }
874
50.5k
    *out = value;
875
50.5k
    return 1;
876
110k
}
877
878
31.3k
static int tg3json__append_utf8(tg3json__buffer *buf, uint32_t cp) {
879
31.3k
    char tmp[4];
880
31.3k
    size_t len = 0;
881
31.3k
    if (cp <= 0x7Fu) {
882
3
        tmp[len++] = (char)cp;
883
31.3k
    } else if (cp <= 0x7FFu) {
884
44
        tmp[len++] = (char)(0xC0u | ((cp >> 6) & 0x1Fu));
885
44
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
886
31.3k
    } else if (cp <= 0xFFFFu) {
887
31.0k
        tmp[len++] = (char)(0xE0u | ((cp >> 12) & 0x0Fu));
888
31.0k
        tmp[len++] = (char)(0x80u | ((cp >> 6) & 0x3Fu));
889
31.0k
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
890
31.0k
    } else if (cp <= 0x10FFFFu) {
891
222
        tmp[len++] = (char)(0xF0u | ((cp >> 18) & 0x07u));
892
222
        tmp[len++] = (char)(0x80u | ((cp >> 12) & 0x3Fu));
893
222
        tmp[len++] = (char)(0x80u | ((cp >> 6) & 0x3Fu));
894
222
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
895
222
    } else {
896
0
        return 0;
897
0
    }
898
31.3k
    return tg3json__buf_append(buf, tmp, len);
899
31.3k
}
fuzz_gltf_v3.cc:tg3json__append_utf8(tg3json__buffer*, unsigned int)
Line
Count
Source
878
5
static int tg3json__append_utf8(tg3json__buffer *buf, uint32_t cp) {
879
5
    char tmp[4];
880
5
    size_t len = 0;
881
5
    if (cp <= 0x7Fu) {
882
0
        tmp[len++] = (char)cp;
883
5
    } else if (cp <= 0x7FFu) {
884
0
        tmp[len++] = (char)(0xC0u | ((cp >> 6) & 0x1Fu));
885
0
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
886
5
    } else if (cp <= 0xFFFFu) {
887
5
        tmp[len++] = (char)(0xE0u | ((cp >> 12) & 0x0Fu));
888
5
        tmp[len++] = (char)(0x80u | ((cp >> 6) & 0x3Fu));
889
5
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
890
5
    } else if (cp <= 0x10FFFFu) {
891
0
        tmp[len++] = (char)(0xF0u | ((cp >> 18) & 0x07u));
892
0
        tmp[len++] = (char)(0x80u | ((cp >> 12) & 0x3Fu));
893
0
        tmp[len++] = (char)(0x80u | ((cp >> 6) & 0x3Fu));
894
0
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
895
0
    } else {
896
0
        return 0;
897
0
    }
898
5
    return tg3json__buf_append(buf, tmp, len);
899
5
}
tiny_gltf_v3.c:tg3json__append_utf8
Line
Count
Source
878
31.3k
static int tg3json__append_utf8(tg3json__buffer *buf, uint32_t cp) {
879
31.3k
    char tmp[4];
880
31.3k
    size_t len = 0;
881
31.3k
    if (cp <= 0x7Fu) {
882
3
        tmp[len++] = (char)cp;
883
31.3k
    } else if (cp <= 0x7FFu) {
884
44
        tmp[len++] = (char)(0xC0u | ((cp >> 6) & 0x1Fu));
885
44
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
886
31.3k
    } else if (cp <= 0xFFFFu) {
887
31.0k
        tmp[len++] = (char)(0xE0u | ((cp >> 12) & 0x0Fu));
888
31.0k
        tmp[len++] = (char)(0x80u | ((cp >> 6) & 0x3Fu));
889
31.0k
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
890
31.0k
    } else if (cp <= 0x10FFFFu) {
891
222
        tmp[len++] = (char)(0xF0u | ((cp >> 18) & 0x07u));
892
222
        tmp[len++] = (char)(0x80u | ((cp >> 12) & 0x3Fu));
893
222
        tmp[len++] = (char)(0x80u | ((cp >> 6) & 0x3Fu));
894
222
        tmp[len++] = (char)(0x80u | (cp & 0x3Fu));
895
222
    } else {
896
0
        return 0;
897
0
    }
898
31.3k
    return tg3json__buf_append(buf, tmp, len);
899
31.3k
}
900
901
static int tg3json__parse_string_raw(tg3json__parser *parser,
902
1.14M
                                     char **out_str, size_t *out_len) {
903
1.14M
    tg3json__buffer buf;
904
1.14M
    const char *start;
905
1.14M
    TINYGLTF_JSON_MEMSET(&buf, 0, sizeof(buf));
906
1.14M
    buf.parser = parser;
907
908
1.14M
    if (parser->cur >= parser->end || *parser->cur != '"') {
909
3
        tg3json__set_error(parser, parser->cur);
910
3
        return 0;
911
3
    }
912
913
1.14M
    ++parser->cur;
914
1.14M
    start = parser->cur;
915
71.7M
    while (parser->cur < parser->end) {
916
71.7M
        unsigned char c = (unsigned char)*parser->cur;
917
71.7M
        if (c == '"') {
918
1.14M
            size_t final_len = buf.len + (size_t)(parser->cur - start);
919
1.14M
            if (parser->max_string_length && final_len > parser->max_string_length) goto oom;
920
1.14M
            if (!tg3json__buf_append(&buf, start, (size_t)(parser->cur - start))) goto oom;
921
1.14M
            ++parser->cur;
922
1.14M
            *out_str = buf.data;
923
1.14M
            *out_len = buf.len;
924
1.14M
            return 1;
925
1.14M
        }
926
70.5M
        if (c == '\\') {
927
454k
            uint32_t codepoint;
928
454k
            size_t pending_len = (size_t)(parser->cur - start);
929
454k
            if (parser->max_string_length && buf.len + pending_len > parser->max_string_length) goto oom;
930
454k
            if (!tg3json__buf_append(&buf, start, (size_t)(parser->cur - start))) goto oom;
931
454k
            ++parser->cur;
932
454k
            if (parser->cur >= parser->end) break;
933
454k
            switch (*parser->cur) {
934
7.07k
                case '"': if (!tg3json__buf_putc(&buf, '"')) goto oom; break;
935
22.4k
                case '\\': if (!tg3json__buf_putc(&buf, '\\')) goto oom; break;
936
22.4k
                case '/': if (!tg3json__buf_putc(&buf, '/')) goto oom; break;
937
97
                case 'b': if (!tg3json__buf_putc(&buf, '\b')) goto oom; break;
938
97
                case 'f': if (!tg3json__buf_putc(&buf, '\f')) goto oom; break;
939
16.4k
                case 'n': if (!tg3json__buf_putc(&buf, '\n')) goto oom; break;
940
305k
                case 'r': if (!tg3json__buf_putc(&buf, '\r')) goto oom; break;
941
305k
                case 't': if (!tg3json__buf_putc(&buf, '\t')) goto oom; break;
942
98.0k
                case 'u': {
943
98.0k
                    if ((size_t)(parser->end - parser->cur) < 5) break;
944
98.0k
                    if (!tg3json__hex4(parser->cur + 1, &codepoint)) break;
945
48.9k
                    parser->cur += 4;
946
48.9k
                    if (codepoint >= 0xD800u && codepoint <= 0xDBFFu) {
947
13.8k
                        uint32_t low;
948
13.8k
                        if ((size_t)(parser->end - parser->cur) < 7 || parser->cur[1] != '\\' || parser->cur[2] != 'u') break;
949
12.7k
                        if (!tg3json__hex4(parser->cur + 3, &low)) break;
950
1.76k
                        if (low < 0xDC00u || low > 0xDFFFu) break;
951
222
                        codepoint = 0x10000u + (((codepoint - 0xD800u) << 10) | (low - 0xDC00u));
952
222
                        parser->cur += 6;
953
35.0k
                    } else if (codepoint >= 0xDC00u && codepoint <= 0xDFFFu) {
954
3.90k
                        break;
955
3.90k
                    }
956
31.3k
                    if (!tg3json__append_utf8(&buf, codepoint)) goto oom;
957
31.3k
                    break;
958
31.3k
                }
959
31.3k
                default:
960
8
                    tg3json__set_error(parser, parser->cur);
961
8
                    TINYGLTF_JSON_FREE(buf.data);
962
8
                    return 0;
963
454k
            }
964
454k
            ++parser->cur;
965
454k
            start = parser->cur;
966
454k
            continue;
967
454k
        }
968
70.1M
        if (c < 0x20u) break;
969
70.1M
        ++parser->cur;
970
70.1M
    }
971
972
8
    tg3json__set_error(parser, parser->cur);
973
8
    TINYGLTF_JSON_FREE(buf.data);
974
8
    return 0;
975
976
0
oom:
977
0
    tg3json__set_error(parser, parser->cur);
978
0
    TINYGLTF_JSON_FREE(buf.data);
979
0
    return 0;
980
1.14M
}
fuzz_gltf_v3.cc:tg3json__parse_string_raw(tg3json__parser*, char**, unsigned long*)
Line
Count
Source
902
38.5k
                                     char **out_str, size_t *out_len) {
903
38.5k
    tg3json__buffer buf;
904
38.5k
    const char *start;
905
38.5k
    TINYGLTF_JSON_MEMSET(&buf, 0, sizeof(buf));
906
38.5k
    buf.parser = parser;
907
908
38.5k
    if (parser->cur >= parser->end || *parser->cur != '"') {
909
1
        tg3json__set_error(parser, parser->cur);
910
1
        return 0;
911
1
    }
912
913
38.5k
    ++parser->cur;
914
38.5k
    start = parser->cur;
915
1.56M
    while (parser->cur < parser->end) {
916
1.56M
        unsigned char c = (unsigned char)*parser->cur;
917
1.56M
        if (c == '"') {
918
38.5k
            size_t final_len = buf.len + (size_t)(parser->cur - start);
919
38.5k
            if (parser->max_string_length && final_len > parser->max_string_length) goto oom;
920
38.5k
            if (!tg3json__buf_append(&buf, start, (size_t)(parser->cur - start))) goto oom;
921
38.5k
            ++parser->cur;
922
38.5k
            *out_str = buf.data;
923
38.5k
            *out_len = buf.len;
924
38.5k
            return 1;
925
38.5k
        }
926
1.53M
        if (c == '\\') {
927
133
            uint32_t codepoint;
928
133
            size_t pending_len = (size_t)(parser->cur - start);
929
133
            if (parser->max_string_length && buf.len + pending_len > parser->max_string_length) goto oom;
930
133
            if (!tg3json__buf_append(&buf, start, (size_t)(parser->cur - start))) goto oom;
931
133
            ++parser->cur;
932
133
            if (parser->cur >= parser->end) break;
933
133
            switch (*parser->cur) {
934
0
                case '"': if (!tg3json__buf_putc(&buf, '"')) goto oom; break;
935
7
                case '\\': if (!tg3json__buf_putc(&buf, '\\')) goto oom; break;
936
7
                case '/': if (!tg3json__buf_putc(&buf, '/')) goto oom; break;
937
11
                case 'b': if (!tg3json__buf_putc(&buf, '\b')) goto oom; break;
938
11
                case 'f': if (!tg3json__buf_putc(&buf, '\f')) goto oom; break;
939
1
                case 'n': if (!tg3json__buf_putc(&buf, '\n')) goto oom; break;
940
1
                case 'r': if (!tg3json__buf_putc(&buf, '\r')) goto oom; break;
941
0
                case 't': if (!tg3json__buf_putc(&buf, '\t')) goto oom; break;
942
114
                case 'u': {
943
114
                    if ((size_t)(parser->end - parser->cur) < 5) break;
944
114
                    if (!tg3json__hex4(parser->cur + 1, &codepoint)) break;
945
83
                    parser->cur += 4;
946
83
                    if (codepoint >= 0xD800u && codepoint <= 0xDBFFu) {
947
78
                        uint32_t low;
948
78
                        if ((size_t)(parser->end - parser->cur) < 7 || parser->cur[1] != '\\' || parser->cur[2] != 'u') break;
949
42
                        if (!tg3json__hex4(parser->cur + 3, &low)) break;
950
41
                        if (low < 0xDC00u || low > 0xDFFFu) break;
951
0
                        codepoint = 0x10000u + (((codepoint - 0xD800u) << 10) | (low - 0xDC00u));
952
0
                        parser->cur += 6;
953
5
                    } else if (codepoint >= 0xDC00u && codepoint <= 0xDFFFu) {
954
0
                        break;
955
0
                    }
956
5
                    if (!tg3json__append_utf8(&buf, codepoint)) goto oom;
957
5
                    break;
958
5
                }
959
5
                default:
960
0
                    tg3json__set_error(parser, parser->cur);
961
0
                    TINYGLTF_JSON_FREE(buf.data);
962
0
                    return 0;
963
133
            }
964
133
            ++parser->cur;
965
133
            start = parser->cur;
966
133
            continue;
967
133
        }
968
1.53M
        if (c < 0x20u) break;
969
1.53M
        ++parser->cur;
970
1.53M
    }
971
972
1
    tg3json__set_error(parser, parser->cur);
973
1
    TINYGLTF_JSON_FREE(buf.data);
974
1
    return 0;
975
976
0
oom:
977
0
    tg3json__set_error(parser, parser->cur);
978
0
    TINYGLTF_JSON_FREE(buf.data);
979
0
    return 0;
980
38.5k
}
tiny_gltf_v3.c:tg3json__parse_string_raw
Line
Count
Source
902
1.10M
                                     char **out_str, size_t *out_len) {
903
1.10M
    tg3json__buffer buf;
904
1.10M
    const char *start;
905
1.10M
    TINYGLTF_JSON_MEMSET(&buf, 0, sizeof(buf));
906
1.10M
    buf.parser = parser;
907
908
1.10M
    if (parser->cur >= parser->end || *parser->cur != '"') {
909
2
        tg3json__set_error(parser, parser->cur);
910
2
        return 0;
911
2
    }
912
913
1.10M
    ++parser->cur;
914
1.10M
    start = parser->cur;
915
70.1M
    while (parser->cur < parser->end) {
916
70.1M
        unsigned char c = (unsigned char)*parser->cur;
917
70.1M
        if (c == '"') {
918
1.10M
            size_t final_len = buf.len + (size_t)(parser->cur - start);
919
1.10M
            if (parser->max_string_length && final_len > parser->max_string_length) goto oom;
920
1.10M
            if (!tg3json__buf_append(&buf, start, (size_t)(parser->cur - start))) goto oom;
921
1.10M
            ++parser->cur;
922
1.10M
            *out_str = buf.data;
923
1.10M
            *out_len = buf.len;
924
1.10M
            return 1;
925
1.10M
        }
926
69.0M
        if (c == '\\') {
927
454k
            uint32_t codepoint;
928
454k
            size_t pending_len = (size_t)(parser->cur - start);
929
454k
            if (parser->max_string_length && buf.len + pending_len > parser->max_string_length) goto oom;
930
454k
            if (!tg3json__buf_append(&buf, start, (size_t)(parser->cur - start))) goto oom;
931
454k
            ++parser->cur;
932
454k
            if (parser->cur >= parser->end) break;
933
454k
            switch (*parser->cur) {
934
7.07k
                case '"': if (!tg3json__buf_putc(&buf, '"')) goto oom; break;
935
22.4k
                case '\\': if (!tg3json__buf_putc(&buf, '\\')) goto oom; break;
936
22.4k
                case '/': if (!tg3json__buf_putc(&buf, '/')) goto oom; break;
937
86
                case 'b': if (!tg3json__buf_putc(&buf, '\b')) goto oom; break;
938
86
                case 'f': if (!tg3json__buf_putc(&buf, '\f')) goto oom; break;
939
16.4k
                case 'n': if (!tg3json__buf_putc(&buf, '\n')) goto oom; break;
940
305k
                case 'r': if (!tg3json__buf_putc(&buf, '\r')) goto oom; break;
941
305k
                case 't': if (!tg3json__buf_putc(&buf, '\t')) goto oom; break;
942
97.9k
                case 'u': {
943
97.9k
                    if ((size_t)(parser->end - parser->cur) < 5) break;
944
97.9k
                    if (!tg3json__hex4(parser->cur + 1, &codepoint)) break;
945
48.8k
                    parser->cur += 4;
946
48.8k
                    if (codepoint >= 0xD800u && codepoint <= 0xDBFFu) {
947
13.8k
                        uint32_t low;
948
13.8k
                        if ((size_t)(parser->end - parser->cur) < 7 || parser->cur[1] != '\\' || parser->cur[2] != 'u') break;
949
12.7k
                        if (!tg3json__hex4(parser->cur + 3, &low)) break;
950
1.72k
                        if (low < 0xDC00u || low > 0xDFFFu) break;
951
222
                        codepoint = 0x10000u + (((codepoint - 0xD800u) << 10) | (low - 0xDC00u));
952
222
                        parser->cur += 6;
953
35.0k
                    } else if (codepoint >= 0xDC00u && codepoint <= 0xDFFFu) {
954
3.90k
                        break;
955
3.90k
                    }
956
31.3k
                    if (!tg3json__append_utf8(&buf, codepoint)) goto oom;
957
31.3k
                    break;
958
31.3k
                }
959
31.3k
                default:
960
8
                    tg3json__set_error(parser, parser->cur);
961
8
                    TINYGLTF_JSON_FREE(buf.data);
962
8
                    return 0;
963
454k
            }
964
454k
            ++parser->cur;
965
454k
            start = parser->cur;
966
454k
            continue;
967
454k
        }
968
68.5M
        if (c < 0x20u) break;
969
68.5M
        ++parser->cur;
970
68.5M
    }
971
972
7
    tg3json__set_error(parser, parser->cur);
973
7
    TINYGLTF_JSON_FREE(buf.data);
974
7
    return 0;
975
976
0
oom:
977
0
    tg3json__set_error(parser, parser->cur);
978
0
    TINYGLTF_JSON_FREE(buf.data);
979
0
    return 0;
980
1.10M
}
981
982
static int tg3json__parse_value(tg3json__parser *parser, size_t depth,
983
                                tg3json_value *out_value);
984
985
static int tg3json__parse_int64_span(const char *start, const char *end,
986
17.2M
                                     int64_t *out) {
987
17.2M
    const char *p = start;
988
17.2M
    uint64_t value = 0;
989
17.2M
    uint64_t limit = (uint64_t)INT64_MAX;
990
17.2M
    int neg = 0;
991
17.2M
    if (p < end && *p == '-') {
992
184k
        neg = 1;
993
184k
        limit += 1u;
994
184k
        ++p;
995
184k
    }
996
17.2M
    if (p >= end) return 0;
997
54.8M
    while (p < end) {
998
37.9M
        unsigned digit = (unsigned)(*p - '0');
999
37.9M
        if (digit > 9u) return 0;
1000
37.9M
        if (value > (limit - digit) / 10u) return 0;
1001
37.6M
        value = value * 10u + (uint64_t)digit;
1002
37.6M
        ++p;
1003
37.6M
    }
1004
16.8M
    if (neg) {
1005
170k
        if (value == ((uint64_t)INT64_MAX + 1u)) {
1006
249
            *out = INT64_MIN;
1007
170k
        } else {
1008
170k
            *out = -(int64_t)value;
1009
170k
        }
1010
16.7M
    } else {
1011
16.7M
        *out = (int64_t)value;
1012
16.7M
    }
1013
16.8M
    return 1;
1014
17.2M
}
fuzz_gltf_v3.cc:tg3json__parse_int64_span(char const*, char const*, long*)
Line
Count
Source
986
5.03M
                                     int64_t *out) {
987
5.03M
    const char *p = start;
988
5.03M
    uint64_t value = 0;
989
5.03M
    uint64_t limit = (uint64_t)INT64_MAX;
990
5.03M
    int neg = 0;
991
5.03M
    if (p < end && *p == '-') {
992
39.9k
        neg = 1;
993
39.9k
        limit += 1u;
994
39.9k
        ++p;
995
39.9k
    }
996
5.03M
    if (p >= end) return 0;
997
16.9M
    while (p < end) {
998
11.9M
        unsigned digit = (unsigned)(*p - '0');
999
11.9M
        if (digit > 9u) return 0;
1000
11.9M
        if (value > (limit - digit) / 10u) return 0;
1001
11.9M
        value = value * 10u + (uint64_t)digit;
1002
11.9M
        ++p;
1003
11.9M
    }
1004
5.02M
    if (neg) {
1005
39.8k
        if (value == ((uint64_t)INT64_MAX + 1u)) {
1006
249
            *out = INT64_MIN;
1007
39.6k
        } else {
1008
39.6k
            *out = -(int64_t)value;
1009
39.6k
        }
1010
4.98M
    } else {
1011
4.98M
        *out = (int64_t)value;
1012
4.98M
    }
1013
5.02M
    return 1;
1014
5.03M
}
tiny_gltf_v3.c:tg3json__parse_int64_span
Line
Count
Source
986
12.1M
                                     int64_t *out) {
987
12.1M
    const char *p = start;
988
12.1M
    uint64_t value = 0;
989
12.1M
    uint64_t limit = (uint64_t)INT64_MAX;
990
12.1M
    int neg = 0;
991
12.1M
    if (p < end && *p == '-') {
992
144k
        neg = 1;
993
144k
        limit += 1u;
994
144k
        ++p;
995
144k
    }
996
12.1M
    if (p >= end) return 0;
997
37.8M
    while (p < end) {
998
26.0M
        unsigned digit = (unsigned)(*p - '0');
999
26.0M
        if (digit > 9u) return 0;
1000
26.0M
        if (value > (limit - digit) / 10u) return 0;
1001
25.7M
        value = value * 10u + (uint64_t)digit;
1002
25.7M
        ++p;
1003
25.7M
    }
1004
11.8M
    if (neg) {
1005
130k
        if (value == ((uint64_t)INT64_MAX + 1u)) {
1006
0
            *out = INT64_MIN;
1007
130k
        } else {
1008
130k
            *out = -(int64_t)value;
1009
130k
        }
1010
11.7M
    } else {
1011
11.7M
        *out = (int64_t)value;
1012
11.7M
    }
1013
11.8M
    return 1;
1014
12.1M
}
1015
1016
static int tg3json__parse_array(tg3json__parser *parser, size_t depth,
1017
9.67k
                                tg3json_value *out_value) {
1018
9.67k
    tg3json_value *items = NULL;
1019
9.67k
    size_t count = 0;
1020
9.67k
    size_t cap = 0;
1021
1022
9.67k
    ++parser->cur;
1023
9.67k
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1024
9.67k
    if (parser->cur < parser->end && *parser->cur == ']') {
1025
3.06k
        ++parser->cur;
1026
3.06k
        out_value->type = TG3JSON_ARRAY;
1027
3.06k
        out_value->u.array.items = NULL;
1028
3.06k
        out_value->u.array.count = 0;
1029
3.06k
        return 1;
1030
3.06k
    }
1031
1032
16.5M
    while (parser->cur < parser->end) {
1033
16.5M
        tg3json_value value;
1034
16.5M
        tg3json__init_value(&value);
1035
16.5M
        if (!tg3json__reserve_bytes_parser(parser, (void **)&items,
1036
16.5M
                                           sizeof(*items), count + 1, &cap)) goto oom;
1037
16.5M
        if (!tg3json__parse_value(parser, depth + 1, &value)) goto fail;
1038
16.5M
        items[count++] = value;
1039
16.5M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1040
16.5M
        if (parser->cur >= parser->end) break;
1041
16.5M
        if (*parser->cur == ',') {
1042
16.5M
            ++parser->cur;
1043
16.5M
            parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1044
16.5M
            continue;
1045
16.5M
        }
1046
6.59k
        if (*parser->cur == ']') {
1047
6.58k
            ++parser->cur;
1048
6.58k
            out_value->type = TG3JSON_ARRAY;
1049
6.58k
            out_value->u.array.items = items;
1050
6.58k
            out_value->u.array.count = count;
1051
6.58k
            return 1;
1052
6.58k
        }
1053
2
        break;
1054
6.59k
    }
1055
1056
20
fail:
1057
363k
    while (count > 0) {
1058
363k
        --count;
1059
363k
        tg3json_value_free(&items[count]);
1060
363k
    }
1061
20
    TINYGLTF_JSON_FREE(items);
1062
20
    tg3json__set_error(parser, parser->cur);
1063
20
    return 0;
1064
1065
0
oom:
1066
0
    while (count > 0) {
1067
0
        --count;
1068
0
        tg3json_value_free(&items[count]);
1069
0
    }
1070
0
    TINYGLTF_JSON_FREE(items);
1071
0
    tg3json__set_error(parser, parser->cur);
1072
0
    return 0;
1073
6.60k
}
fuzz_gltf_v3.cc:tg3json__parse_array(tg3json__parser*, unsigned long, tg3json_value*)
Line
Count
Source
1017
52
                                tg3json_value *out_value) {
1018
52
    tg3json_value *items = NULL;
1019
52
    size_t count = 0;
1020
52
    size_t cap = 0;
1021
1022
52
    ++parser->cur;
1023
52
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1024
52
    if (parser->cur < parser->end && *parser->cur == ']') {
1025
0
        ++parser->cur;
1026
0
        out_value->type = TG3JSON_ARRAY;
1027
0
        out_value->u.array.items = NULL;
1028
0
        out_value->u.array.count = 0;
1029
0
        return 1;
1030
0
    }
1031
1032
5.09M
    while (parser->cur < parser->end) {
1033
5.09M
        tg3json_value value;
1034
5.09M
        tg3json__init_value(&value);
1035
5.09M
        if (!tg3json__reserve_bytes_parser(parser, (void **)&items,
1036
5.09M
                                           sizeof(*items), count + 1, &cap)) goto oom;
1037
5.09M
        if (!tg3json__parse_value(parser, depth + 1, &value)) goto fail;
1038
5.09M
        items[count++] = value;
1039
5.09M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1040
5.09M
        if (parser->cur >= parser->end) break;
1041
5.09M
        if (*parser->cur == ',') {
1042
5.09M
            ++parser->cur;
1043
5.09M
            parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1044
5.09M
            continue;
1045
5.09M
        }
1046
52
        if (*parser->cur == ']') {
1047
52
            ++parser->cur;
1048
52
            out_value->type = TG3JSON_ARRAY;
1049
52
            out_value->u.array.items = items;
1050
52
            out_value->u.array.count = count;
1051
52
            return 1;
1052
52
        }
1053
0
        break;
1054
52
    }
1055
1056
0
fail:
1057
0
    while (count > 0) {
1058
0
        --count;
1059
0
        tg3json_value_free(&items[count]);
1060
0
    }
1061
0
    TINYGLTF_JSON_FREE(items);
1062
0
    tg3json__set_error(parser, parser->cur);
1063
0
    return 0;
1064
1065
0
oom:
1066
0
    while (count > 0) {
1067
0
        --count;
1068
0
        tg3json_value_free(&items[count]);
1069
0
    }
1070
0
    TINYGLTF_JSON_FREE(items);
1071
0
    tg3json__set_error(parser, parser->cur);
1072
0
    return 0;
1073
52
}
tiny_gltf_v3.c:tg3json__parse_array
Line
Count
Source
1017
9.61k
                                tg3json_value *out_value) {
1018
9.61k
    tg3json_value *items = NULL;
1019
9.61k
    size_t count = 0;
1020
9.61k
    size_t cap = 0;
1021
1022
9.61k
    ++parser->cur;
1023
9.61k
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1024
9.61k
    if (parser->cur < parser->end && *parser->cur == ']') {
1025
3.06k
        ++parser->cur;
1026
3.06k
        out_value->type = TG3JSON_ARRAY;
1027
3.06k
        out_value->u.array.items = NULL;
1028
3.06k
        out_value->u.array.count = 0;
1029
3.06k
        return 1;
1030
3.06k
    }
1031
1032
11.4M
    while (parser->cur < parser->end) {
1033
11.4M
        tg3json_value value;
1034
11.4M
        tg3json__init_value(&value);
1035
11.4M
        if (!tg3json__reserve_bytes_parser(parser, (void **)&items,
1036
11.4M
                                           sizeof(*items), count + 1, &cap)) goto oom;
1037
11.4M
        if (!tg3json__parse_value(parser, depth + 1, &value)) goto fail;
1038
11.4M
        items[count++] = value;
1039
11.4M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1040
11.4M
        if (parser->cur >= parser->end) break;
1041
11.4M
        if (*parser->cur == ',') {
1042
11.4M
            ++parser->cur;
1043
11.4M
            parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1044
11.4M
            continue;
1045
11.4M
        }
1046
6.53k
        if (*parser->cur == ']') {
1047
6.53k
            ++parser->cur;
1048
6.53k
            out_value->type = TG3JSON_ARRAY;
1049
6.53k
            out_value->u.array.items = items;
1050
6.53k
            out_value->u.array.count = count;
1051
6.53k
            return 1;
1052
6.53k
        }
1053
2
        break;
1054
6.53k
    }
1055
1056
20
fail:
1057
363k
    while (count > 0) {
1058
363k
        --count;
1059
363k
        tg3json_value_free(&items[count]);
1060
363k
    }
1061
20
    TINYGLTF_JSON_FREE(items);
1062
20
    tg3json__set_error(parser, parser->cur);
1063
20
    return 0;
1064
1065
0
oom:
1066
0
    while (count > 0) {
1067
0
        --count;
1068
0
        tg3json_value_free(&items[count]);
1069
0
    }
1070
0
    TINYGLTF_JSON_FREE(items);
1071
0
    tg3json__set_error(parser, parser->cur);
1072
0
    return 0;
1073
6.55k
}
1074
1075
static int tg3json__parse_object(tg3json__parser *parser, size_t depth,
1076
235k
                                 tg3json_value *out_value) {
1077
235k
    tg3json_object_entry *items = NULL;
1078
235k
    size_t count = 0;
1079
235k
    size_t cap = 0;
1080
1081
235k
    ++parser->cur;
1082
235k
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1083
235k
    if (parser->cur < parser->end && *parser->cur == '}') {
1084
161k
        ++parser->cur;
1085
161k
        out_value->type = TG3JSON_OBJECT;
1086
161k
        out_value->u.object.items = NULL;
1087
161k
        out_value->u.object.count = 0;
1088
161k
        return 1;
1089
161k
    }
1090
1091
1.12M
    while (parser->cur < parser->end) {
1092
1.12M
        char *key = NULL;
1093
1.12M
        size_t key_len = 0;
1094
1.12M
        tg3json_value value;
1095
1.12M
        tg3json__init_value(&value);
1096
1.12M
        if (!tg3json__parse_string_raw(parser, &key, &key_len)) goto fail;
1097
1.12M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1098
1.12M
        if (parser->cur >= parser->end || *parser->cur != ':') {
1099
3
            TINYGLTF_JSON_FREE(key);
1100
3
            goto fail;
1101
3
        }
1102
1.12M
        ++parser->cur;
1103
1.12M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1104
1.12M
        if (!tg3json__parse_value(parser, depth + 1, &value)) {
1105
29
            TINYGLTF_JSON_FREE(key);
1106
29
            goto fail;
1107
29
        }
1108
1.12M
        if (!tg3json__reserve_bytes_parser(parser, (void **)&items,
1109
1.12M
                                           sizeof(*items), count + 1, &cap)) {
1110
0
            TINYGLTF_JSON_FREE(key);
1111
0
            tg3json_value_free(&value);
1112
0
            goto oom;
1113
0
        }
1114
1.12M
        items[count].key = key;
1115
1.12M
        items[count].key_len = key_len;
1116
1.12M
        items[count].value = (tg3json_value *)tg3json__parser_alloc(parser, sizeof(tg3json_value));
1117
1.12M
        if (!items[count].value) {
1118
0
            TINYGLTF_JSON_FREE(key);
1119
0
            tg3json_value_free(&value);
1120
0
            goto oom;
1121
0
        }
1122
1.12M
        *items[count].value = value;
1123
1.12M
        ++count;
1124
1.12M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1125
1.12M
        if (parser->cur >= parser->end) break;
1126
1.12M
        if (*parser->cur == ',') {
1127
1.05M
            ++parser->cur;
1128
1.05M
            parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1129
1.05M
            continue;
1130
1.05M
        }
1131
73.5k
        if (*parser->cur == '}') {
1132
73.5k
            ++parser->cur;
1133
73.5k
            out_value->type = TG3JSON_OBJECT;
1134
73.5k
            out_value->u.object.items = items;
1135
73.5k
            out_value->u.object.count = count;
1136
73.5k
            return 1;
1137
73.5k
        }
1138
8
        break;
1139
73.5k
    }
1140
1141
46
fail:
1142
286k
    while (count > 0) {
1143
286k
        --count;
1144
286k
        TINYGLTF_JSON_FREE(items[count].key);
1145
286k
        if (items[count].value) {
1146
286k
            tg3json_value_free(items[count].value);
1147
286k
            TINYGLTF_JSON_FREE(items[count].value);
1148
286k
        }
1149
286k
    }
1150
46
    TINYGLTF_JSON_FREE(items);
1151
46
    tg3json__set_error(parser, parser->cur);
1152
46
    return 0;
1153
1154
0
oom:
1155
0
    while (count > 0) {
1156
0
        --count;
1157
0
        TINYGLTF_JSON_FREE(items[count].key);
1158
0
        if (items[count].value) {
1159
0
            tg3json_value_free(items[count].value);
1160
0
            TINYGLTF_JSON_FREE(items[count].value);
1161
0
        }
1162
0
    }
1163
0
    TINYGLTF_JSON_FREE(items);
1164
0
    tg3json__set_error(parser, parser->cur);
1165
0
    return 0;
1166
73.5k
}
fuzz_gltf_v3.cc:tg3json__parse_object(tg3json__parser*, unsigned long, tg3json_value*)
Line
Count
Source
1076
13.1k
                                 tg3json_value *out_value) {
1077
13.1k
    tg3json_object_entry *items = NULL;
1078
13.1k
    size_t count = 0;
1079
13.1k
    size_t cap = 0;
1080
1081
13.1k
    ++parser->cur;
1082
13.1k
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1083
13.1k
    if (parser->cur < parser->end && *parser->cur == '}') {
1084
12.9k
        ++parser->cur;
1085
12.9k
        out_value->type = TG3JSON_OBJECT;
1086
12.9k
        out_value->u.object.items = NULL;
1087
12.9k
        out_value->u.object.count = 0;
1088
12.9k
        return 1;
1089
12.9k
    }
1090
1091
38.5k
    while (parser->cur < parser->end) {
1092
38.5k
        char *key = NULL;
1093
38.5k
        size_t key_len = 0;
1094
38.5k
        tg3json_value value;
1095
38.5k
        tg3json__init_value(&value);
1096
38.5k
        if (!tg3json__parse_string_raw(parser, &key, &key_len)) goto fail;
1097
38.5k
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1098
38.5k
        if (parser->cur >= parser->end || *parser->cur != ':') {
1099
0
            TINYGLTF_JSON_FREE(key);
1100
0
            goto fail;
1101
0
        }
1102
38.5k
        ++parser->cur;
1103
38.5k
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1104
38.5k
        if (!tg3json__parse_value(parser, depth + 1, &value)) {
1105
5
            TINYGLTF_JSON_FREE(key);
1106
5
            goto fail;
1107
5
        }
1108
38.5k
        if (!tg3json__reserve_bytes_parser(parser, (void **)&items,
1109
38.5k
                                           sizeof(*items), count + 1, &cap)) {
1110
0
            TINYGLTF_JSON_FREE(key);
1111
0
            tg3json_value_free(&value);
1112
0
            goto oom;
1113
0
        }
1114
38.5k
        items[count].key = key;
1115
38.5k
        items[count].key_len = key_len;
1116
38.5k
        items[count].value = (tg3json_value *)tg3json__parser_alloc(parser, sizeof(tg3json_value));
1117
38.5k
        if (!items[count].value) {
1118
0
            TINYGLTF_JSON_FREE(key);
1119
0
            tg3json_value_free(&value);
1120
0
            goto oom;
1121
0
        }
1122
38.5k
        *items[count].value = value;
1123
38.5k
        ++count;
1124
38.5k
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1125
38.5k
        if (parser->cur >= parser->end) break;
1126
38.5k
        if (*parser->cur == ',') {
1127
38.3k
            ++parser->cur;
1128
38.3k
            parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1129
38.3k
            continue;
1130
38.3k
        }
1131
149
        if (*parser->cur == '}') {
1132
146
            ++parser->cur;
1133
146
            out_value->type = TG3JSON_OBJECT;
1134
146
            out_value->u.object.items = items;
1135
146
            out_value->u.object.count = count;
1136
146
            return 1;
1137
146
        }
1138
3
        break;
1139
149
    }
1140
1141
9
fail:
1142
38.1k
    while (count > 0) {
1143
38.1k
        --count;
1144
38.1k
        TINYGLTF_JSON_FREE(items[count].key);
1145
38.1k
        if (items[count].value) {
1146
38.1k
            tg3json_value_free(items[count].value);
1147
38.1k
            TINYGLTF_JSON_FREE(items[count].value);
1148
38.1k
        }
1149
38.1k
    }
1150
9
    TINYGLTF_JSON_FREE(items);
1151
9
    tg3json__set_error(parser, parser->cur);
1152
9
    return 0;
1153
1154
0
oom:
1155
0
    while (count > 0) {
1156
0
        --count;
1157
0
        TINYGLTF_JSON_FREE(items[count].key);
1158
0
        if (items[count].value) {
1159
0
            tg3json_value_free(items[count].value);
1160
0
            TINYGLTF_JSON_FREE(items[count].value);
1161
0
        }
1162
0
    }
1163
0
    TINYGLTF_JSON_FREE(items);
1164
0
    tg3json__set_error(parser, parser->cur);
1165
0
    return 0;
1166
155
}
tiny_gltf_v3.c:tg3json__parse_object
Line
Count
Source
1076
222k
                                 tg3json_value *out_value) {
1077
222k
    tg3json_object_entry *items = NULL;
1078
222k
    size_t count = 0;
1079
222k
    size_t cap = 0;
1080
1081
222k
    ++parser->cur;
1082
222k
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1083
222k
    if (parser->cur < parser->end && *parser->cur == '}') {
1084
148k
        ++parser->cur;
1085
148k
        out_value->type = TG3JSON_OBJECT;
1086
148k
        out_value->u.object.items = NULL;
1087
148k
        out_value->u.object.count = 0;
1088
148k
        return 1;
1089
148k
    }
1090
1091
1.08M
    while (parser->cur < parser->end) {
1092
1.08M
        char *key = NULL;
1093
1.08M
        size_t key_len = 0;
1094
1.08M
        tg3json_value value;
1095
1.08M
        tg3json__init_value(&value);
1096
1.08M
        if (!tg3json__parse_string_raw(parser, &key, &key_len)) goto fail;
1097
1.08M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1098
1.08M
        if (parser->cur >= parser->end || *parser->cur != ':') {
1099
3
            TINYGLTF_JSON_FREE(key);
1100
3
            goto fail;
1101
3
        }
1102
1.08M
        ++parser->cur;
1103
1.08M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1104
1.08M
        if (!tg3json__parse_value(parser, depth + 1, &value)) {
1105
24
            TINYGLTF_JSON_FREE(key);
1106
24
            goto fail;
1107
24
        }
1108
1.08M
        if (!tg3json__reserve_bytes_parser(parser, (void **)&items,
1109
1.08M
                                           sizeof(*items), count + 1, &cap)) {
1110
0
            TINYGLTF_JSON_FREE(key);
1111
0
            tg3json_value_free(&value);
1112
0
            goto oom;
1113
0
        }
1114
1.08M
        items[count].key = key;
1115
1.08M
        items[count].key_len = key_len;
1116
1.08M
        items[count].value = (tg3json_value *)tg3json__parser_alloc(parser, sizeof(tg3json_value));
1117
1.08M
        if (!items[count].value) {
1118
0
            TINYGLTF_JSON_FREE(key);
1119
0
            tg3json_value_free(&value);
1120
0
            goto oom;
1121
0
        }
1122
1.08M
        *items[count].value = value;
1123
1.08M
        ++count;
1124
1.08M
        parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1125
1.08M
        if (parser->cur >= parser->end) break;
1126
1.08M
        if (*parser->cur == ',') {
1127
1.01M
            ++parser->cur;
1128
1.01M
            parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1129
1.01M
            continue;
1130
1.01M
        }
1131
73.3k
        if (*parser->cur == '}') {
1132
73.3k
            ++parser->cur;
1133
73.3k
            out_value->type = TG3JSON_OBJECT;
1134
73.3k
            out_value->u.object.items = items;
1135
73.3k
            out_value->u.object.count = count;
1136
73.3k
            return 1;
1137
73.3k
        }
1138
5
        break;
1139
73.3k
    }
1140
1141
37
fail:
1142
248k
    while (count > 0) {
1143
248k
        --count;
1144
248k
        TINYGLTF_JSON_FREE(items[count].key);
1145
248k
        if (items[count].value) {
1146
248k
            tg3json_value_free(items[count].value);
1147
248k
            TINYGLTF_JSON_FREE(items[count].value);
1148
248k
        }
1149
248k
    }
1150
37
    TINYGLTF_JSON_FREE(items);
1151
37
    tg3json__set_error(parser, parser->cur);
1152
37
    return 0;
1153
1154
0
oom:
1155
0
    while (count > 0) {
1156
0
        --count;
1157
0
        TINYGLTF_JSON_FREE(items[count].key);
1158
0
        if (items[count].value) {
1159
0
            tg3json_value_free(items[count].value);
1160
0
            TINYGLTF_JSON_FREE(items[count].value);
1161
0
        }
1162
0
    }
1163
0
    TINYGLTF_JSON_FREE(items);
1164
0
    tg3json__set_error(parser, parser->cur);
1165
0
    return 0;
1166
73.4k
}
1167
1168
17.4M
static int tg3json__parse_number(tg3json__parser *parser, tg3json_value *out_value) {
1169
17.4M
    const char *start = parser->cur;
1170
17.4M
    const char *p = parser->cur;
1171
17.4M
    int is_real = 0;
1172
1173
17.4M
    if (*p == '-') ++p;
1174
17.4M
    if (p >= parser->end) goto fail;
1175
17.4M
    if (*p == '0') {
1176
160k
        ++p;
1177
17.2M
    } else if (*p >= '1' && *p <= '9') {
1178
40.5M
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1179
17.2M
    } else {
1180
9
        goto fail;
1181
9
    }
1182
17.4M
    if (p < parser->end && *p == '.') {
1183
186k
        is_real = 1;
1184
186k
        ++p;
1185
186k
        if (p >= parser->end || *p < '0' || *p > '9') goto fail;
1186
3.39M
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1187
186k
    }
1188
17.4M
    if (p < parser->end && (*p == 'e' || *p == 'E')) {
1189
85.2k
        is_real = 1;
1190
85.2k
        ++p;
1191
85.2k
        if (p < parser->end && (*p == '+' || *p == '-')) ++p;
1192
85.2k
        if (p >= parser->end || *p < '0' || *p > '9') goto fail;
1193
240k
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1194
85.2k
    }
1195
1196
17.4M
    if (!is_real) {
1197
17.2M
        int64_t v;
1198
17.2M
        if (tg3json__parse_int64_span(start, p, &v)) {
1199
16.8M
            out_value->type = TG3JSON_INT;
1200
16.8M
            out_value->u.integer = v;
1201
16.8M
            parser->cur = p;
1202
16.8M
            return 1;
1203
16.8M
        }
1204
310k
        is_real = 1;
1205
310k
    }
1206
1207
564k
    {
1208
564k
        if (!tg3json__parse_f64_c(start, p, &out_value->u.real)) goto fail;
1209
564k
        if (parser->parse_float32) out_value->u.real = (double)(float)out_value->u.real;
1210
564k
        out_value->type = TG3JSON_REAL;
1211
564k
        parser->cur = p;
1212
564k
        return 1;
1213
564k
    }
1214
1215
9
fail:
1216
9
    tg3json__set_error(parser, parser->cur);
1217
9
    return 0;
1218
564k
}
fuzz_gltf_v3.cc:tg3json__parse_number(tg3json__parser*, tg3json_value*)
Line
Count
Source
1168
5.12M
static int tg3json__parse_number(tg3json__parser *parser, tg3json_value *out_value) {
1169
5.12M
    const char *start = parser->cur;
1170
5.12M
    const char *p = parser->cur;
1171
5.12M
    int is_real = 0;
1172
1173
5.12M
    if (*p == '-') ++p;
1174
5.12M
    if (p >= parser->end) goto fail;
1175
5.12M
    if (*p == '0') {
1176
15.2k
        ++p;
1177
5.10M
    } else if (*p >= '1' && *p <= '9') {
1178
12.7M
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1179
5.10M
    } else {
1180
2
        goto fail;
1181
2
    }
1182
5.12M
    if (p < parser->end && *p == '.') {
1183
46.5k
        is_real = 1;
1184
46.5k
        ++p;
1185
46.5k
        if (p >= parser->end || *p < '0' || *p > '9') goto fail;
1186
2.37M
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1187
46.5k
    }
1188
5.12M
    if (p < parser->end && (*p == 'e' || *p == 'E')) {
1189
62.0k
        is_real = 1;
1190
62.0k
        ++p;
1191
62.0k
        if (p < parser->end && (*p == '+' || *p == '-')) ++p;
1192
62.0k
        if (p >= parser->end || *p < '0' || *p > '9') goto fail;
1193
201k
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1194
62.0k
    }
1195
1196
5.12M
    if (!is_real) {
1197
5.03M
        int64_t v;
1198
5.03M
        if (tg3json__parse_int64_span(start, p, &v)) {
1199
5.02M
            out_value->type = TG3JSON_INT;
1200
5.02M
            out_value->u.integer = v;
1201
5.02M
            parser->cur = p;
1202
5.02M
            return 1;
1203
5.02M
        }
1204
7.56k
        is_real = 1;
1205
7.56k
    }
1206
1207
98.5k
    {
1208
98.5k
        if (!tg3json__parse_f64_c(start, p, &out_value->u.real)) goto fail;
1209
98.5k
        if (parser->parse_float32) out_value->u.real = (double)(float)out_value->u.real;
1210
98.5k
        out_value->type = TG3JSON_REAL;
1211
98.5k
        parser->cur = p;
1212
98.5k
        return 1;
1213
98.5k
    }
1214
1215
2
fail:
1216
2
    tg3json__set_error(parser, parser->cur);
1217
2
    return 0;
1218
98.5k
}
tiny_gltf_v3.c:tg3json__parse_number
Line
Count
Source
1168
12.3M
static int tg3json__parse_number(tg3json__parser *parser, tg3json_value *out_value) {
1169
12.3M
    const char *start = parser->cur;
1170
12.3M
    const char *p = parser->cur;
1171
12.3M
    int is_real = 0;
1172
1173
12.3M
    if (*p == '-') ++p;
1174
12.3M
    if (p >= parser->end) goto fail;
1175
12.3M
    if (*p == '0') {
1176
145k
        ++p;
1177
12.1M
    } else if (*p >= '1' && *p <= '9') {
1178
27.8M
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1179
12.1M
    } else {
1180
7
        goto fail;
1181
7
    }
1182
12.3M
    if (p < parser->end && *p == '.') {
1183
139k
        is_real = 1;
1184
139k
        ++p;
1185
139k
        if (p >= parser->end || *p < '0' || *p > '9') goto fail;
1186
1.02M
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1187
139k
    }
1188
12.3M
    if (p < parser->end && (*p == 'e' || *p == 'E')) {
1189
23.1k
        is_real = 1;
1190
23.1k
        ++p;
1191
23.1k
        if (p < parser->end && (*p == '+' || *p == '-')) ++p;
1192
23.1k
        if (p >= parser->end || *p < '0' || *p > '9') goto fail;
1193
39.4k
        do { ++p; } while (p < parser->end && *p >= '0' && *p <= '9');
1194
23.1k
    }
1195
1196
12.3M
    if (!is_real) {
1197
12.1M
        int64_t v;
1198
12.1M
        if (tg3json__parse_int64_span(start, p, &v)) {
1199
11.8M
            out_value->type = TG3JSON_INT;
1200
11.8M
            out_value->u.integer = v;
1201
11.8M
            parser->cur = p;
1202
11.8M
            return 1;
1203
11.8M
        }
1204
303k
        is_real = 1;
1205
303k
    }
1206
1207
466k
    {
1208
466k
        if (!tg3json__parse_f64_c(start, p, &out_value->u.real)) goto fail;
1209
466k
        if (parser->parse_float32) out_value->u.real = (double)(float)out_value->u.real;
1210
466k
        out_value->type = TG3JSON_REAL;
1211
466k
        parser->cur = p;
1212
466k
        return 1;
1213
466k
    }
1214
1215
7
fail:
1216
7
    tg3json__set_error(parser, parser->cur);
1217
7
    return 0;
1218
466k
}
1219
1220
static int tg3json__parse_value(tg3json__parser *parser, size_t depth,
1221
17.7M
                                tg3json_value *out_value) {
1222
17.7M
    if (parser->depth_limit && depth > parser->depth_limit) {
1223
0
        tg3json__set_error(parser, parser->cur);
1224
0
        return 0;
1225
0
    }
1226
1227
17.7M
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1228
17.7M
    if (parser->cur >= parser->end) {
1229
0
        tg3json__set_error(parser, parser->cur);
1230
0
        return 0;
1231
0
    }
1232
1233
17.7M
    switch (*parser->cur) {
1234
9.67k
        case '[':
1235
9.67k
            return tg3json__parse_array(parser, depth, out_value);
1236
235k
        case '{':
1237
235k
            return tg3json__parse_object(parser, depth, out_value);
1238
16.4k
        case '"': {
1239
16.4k
            char *str = NULL;
1240
16.4k
            size_t len = 0;
1241
16.4k
            if (!tg3json__parse_string_raw(parser, &str, &len)) return 0;
1242
16.4k
            out_value->type = TG3JSON_STRING;
1243
16.4k
            out_value->u.string.ptr = str;
1244
16.4k
            out_value->u.string.len = len;
1245
16.4k
            return 1;
1246
16.4k
        }
1247
138
        case 'n':
1248
138
            if ((size_t)(parser->end - parser->cur) >= 4 && TINYGLTF_JSON_MEMCMP(parser->cur, "null", 4) == 0) {
1249
132
                out_value->type = TG3JSON_NULL;
1250
132
                parser->cur += 4;
1251
132
                return 1;
1252
132
            }
1253
6
            break;
1254
1.00k
        case 't':
1255
1.00k
            if ((size_t)(parser->end - parser->cur) >= 4 && TINYGLTF_JSON_MEMCMP(parser->cur, "true", 4) == 0) {
1256
1.00k
                out_value->type = TG3JSON_BOOL;
1257
1.00k
                out_value->u.boolean = 1;
1258
1.00k
                parser->cur += 4;
1259
1.00k
                return 1;
1260
1.00k
            }
1261
2
            break;
1262
146
        case 'f':
1263
146
            if ((size_t)(parser->end - parser->cur) >= 5 && TINYGLTF_JSON_MEMCMP(parser->cur, "false", 5) == 0) {
1264
142
                out_value->type = TG3JSON_BOOL;
1265
142
                out_value->u.boolean = 0;
1266
142
                parser->cur += 5;
1267
142
                return 1;
1268
142
            }
1269
4
            break;
1270
17.4M
        default:
1271
17.4M
            return tg3json__parse_number(parser, out_value);
1272
17.7M
    }
1273
1274
12
    tg3json__set_error(parser, parser->cur);
1275
12
    return 0;
1276
17.7M
}
fuzz_gltf_v3.cc:tg3json__parse_value(tg3json__parser*, unsigned long, tg3json_value*)
Line
Count
Source
1221
5.13M
                                tg3json_value *out_value) {
1222
5.13M
    if (parser->depth_limit && depth > parser->depth_limit) {
1223
0
        tg3json__set_error(parser, parser->cur);
1224
0
        return 0;
1225
0
    }
1226
1227
5.13M
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1228
5.13M
    if (parser->cur >= parser->end) {
1229
0
        tg3json__set_error(parser, parser->cur);
1230
0
        return 0;
1231
0
    }
1232
1233
5.13M
    switch (*parser->cur) {
1234
52
        case '[':
1235
52
            return tg3json__parse_array(parser, depth, out_value);
1236
13.1k
        case '{':
1237
13.1k
            return tg3json__parse_object(parser, depth, out_value);
1238
33
        case '"': {
1239
33
            char *str = NULL;
1240
33
            size_t len = 0;
1241
33
            if (!tg3json__parse_string_raw(parser, &str, &len)) return 0;
1242
32
            out_value->type = TG3JSON_STRING;
1243
32
            out_value->u.string.ptr = str;
1244
32
            out_value->u.string.len = len;
1245
32
            return 1;
1246
33
        }
1247
1
        case 'n':
1248
1
            if ((size_t)(parser->end - parser->cur) >= 4 && TINYGLTF_JSON_MEMCMP(parser->cur, "null", 4) == 0) {
1249
0
                out_value->type = TG3JSON_NULL;
1250
0
                parser->cur += 4;
1251
0
                return 1;
1252
0
            }
1253
1
            break;
1254
2
        case 't':
1255
2
            if ((size_t)(parser->end - parser->cur) >= 4 && TINYGLTF_JSON_MEMCMP(parser->cur, "true", 4) == 0) {
1256
0
                out_value->type = TG3JSON_BOOL;
1257
0
                out_value->u.boolean = 1;
1258
0
                parser->cur += 4;
1259
0
                return 1;
1260
0
            }
1261
2
            break;
1262
5
        case 'f':
1263
5
            if ((size_t)(parser->end - parser->cur) >= 5 && TINYGLTF_JSON_MEMCMP(parser->cur, "false", 5) == 0) {
1264
4
                out_value->type = TG3JSON_BOOL;
1265
4
                out_value->u.boolean = 0;
1266
4
                parser->cur += 5;
1267
4
                return 1;
1268
4
            }
1269
1
            break;
1270
5.12M
        default:
1271
5.12M
            return tg3json__parse_number(parser, out_value);
1272
5.13M
    }
1273
1274
4
    tg3json__set_error(parser, parser->cur);
1275
4
    return 0;
1276
5.13M
}
tiny_gltf_v3.c:tg3json__parse_value
Line
Count
Source
1221
12.5M
                                tg3json_value *out_value) {
1222
12.5M
    if (parser->depth_limit && depth > parser->depth_limit) {
1223
0
        tg3json__set_error(parser, parser->cur);
1224
0
        return 0;
1225
0
    }
1226
1227
12.5M
    parser->cur = tg3json__skip_ws(parser->cur, parser->end);
1228
12.5M
    if (parser->cur >= parser->end) {
1229
0
        tg3json__set_error(parser, parser->cur);
1230
0
        return 0;
1231
0
    }
1232
1233
12.5M
    switch (*parser->cur) {
1234
9.61k
        case '[':
1235
9.61k
            return tg3json__parse_array(parser, depth, out_value);
1236
222k
        case '{':
1237
222k
            return tg3json__parse_object(parser, depth, out_value);
1238
16.4k
        case '"': {
1239
16.4k
            char *str = NULL;
1240
16.4k
            size_t len = 0;
1241
16.4k
            if (!tg3json__parse_string_raw(parser, &str, &len)) return 0;
1242
16.4k
            out_value->type = TG3JSON_STRING;
1243
16.4k
            out_value->u.string.ptr = str;
1244
16.4k
            out_value->u.string.len = len;
1245
16.4k
            return 1;
1246
16.4k
        }
1247
137
        case 'n':
1248
137
            if ((size_t)(parser->end - parser->cur) >= 4 && TINYGLTF_JSON_MEMCMP(parser->cur, "null", 4) == 0) {
1249
132
                out_value->type = TG3JSON_NULL;
1250
132
                parser->cur += 4;
1251
132
                return 1;
1252
132
            }
1253
5
            break;
1254
1.00k
        case 't':
1255
1.00k
            if ((size_t)(parser->end - parser->cur) >= 4 && TINYGLTF_JSON_MEMCMP(parser->cur, "true", 4) == 0) {
1256
1.00k
                out_value->type = TG3JSON_BOOL;
1257
1.00k
                out_value->u.boolean = 1;
1258
1.00k
                parser->cur += 4;
1259
1.00k
                return 1;
1260
1.00k
            }
1261
0
            break;
1262
141
        case 'f':
1263
141
            if ((size_t)(parser->end - parser->cur) >= 5 && TINYGLTF_JSON_MEMCMP(parser->cur, "false", 5) == 0) {
1264
138
                out_value->type = TG3JSON_BOOL;
1265
138
                out_value->u.boolean = 0;
1266
138
                parser->cur += 5;
1267
138
                return 1;
1268
138
            }
1269
3
            break;
1270
12.3M
        default:
1271
12.3M
            return tg3json__parse_number(parser, out_value);
1272
12.5M
    }
1273
1274
8
    tg3json__set_error(parser, parser->cur);
1275
8
    return 0;
1276
12.5M
}
1277
1278
int tg3json_parse_n_opts(const char *data, size_t len,
1279
                         const tg3json_parse_options *options,
1280
                         tg3json_value *out_value,
1281
405
                         const char **out_error_pos) {
1282
405
    tg3json__parser parser;
1283
405
    int ok;
1284
1285
405
    if (out_error_pos) *out_error_pos = NULL;
1286
405
    if (!out_value) return 0;
1287
405
    tg3json__init_value(out_value);
1288
405
    if (!data) return 0;
1289
1290
405
    parser.cur = data;
1291
405
    parser.end = data + len;
1292
405
    parser.error = NULL;
1293
405
    parser.depth_limit = options ? (options->depth_limit ? options->depth_limit : 256) : 256;
1294
405
    parser.memory_budget = options ? options->memory_budget : 0;
1295
405
    parser.max_single_alloc = options ? options->max_single_alloc : 0;
1296
405
    parser.max_string_length = options ? options->max_string_length : 0;
1297
405
    parser.allocated = 0;
1298
405
    parser.parse_float32 = options ? options->parse_float32 : 0;
1299
1300
405
    parser.cur = tg3json__skip_ws(parser.cur, parser.end);
1301
405
    if (parser.cur >= parser.end) {
1302
0
        if (out_error_pos) *out_error_pos = data;
1303
0
        return 0;
1304
0
    }
1305
1306
405
    ok = tg3json__parse_value(&parser, 0, out_value);
1307
405
    if (!ok) {
1308
55
        if (out_error_pos) *out_error_pos = parser.error ? parser.error : parser.cur;
1309
55
        tg3json_value_free(out_value);
1310
55
        return 0;
1311
55
    }
1312
1313
350
    parser.cur = tg3json__skip_ws(parser.cur, parser.end);
1314
350
    if (parser.cur != parser.end) {
1315
2
        if (out_error_pos) *out_error_pos = parser.cur;
1316
2
        tg3json_value_free(out_value);
1317
2
        return 0;
1318
2
    }
1319
1320
348
    return 1;
1321
350
}
1322
1323
int tg3json_parse_n(const char *data, size_t len, size_t depth_limit,
1324
0
                    tg3json_value *out_value, const char **out_error_pos) {
1325
0
    tg3json_parse_options options;
1326
0
    TINYGLTF_JSON_MEMSET(&options, 0, sizeof(options));
1327
0
    options.depth_limit = depth_limit;
1328
0
    return tg3json_parse_n_opts(data, len, &options, out_value, out_error_pos);
1329
0
}
1330
1331
int tg3json_parse(const char *begin, const char *end, size_t depth_limit,
1332
0
                  tg3json_value *out_value, const char **out_error_pos) {
1333
0
    if (!begin || !end || end < begin) {
1334
0
        if (out_error_pos) *out_error_pos = begin;
1335
0
        return 0;
1336
0
    }
1337
0
    return tg3json_parse_n(begin, (size_t)(end - begin), depth_limit,
1338
0
                           out_value, out_error_pos);
1339
0
}
1340
1341
17.7M
void tg3json_value_free(tg3json_value *value) {
1342
17.7M
    size_t i;
1343
17.7M
    if (!value) return;
1344
17.7M
    switch (value->type) {
1345
16.4k
        case TG3JSON_STRING:
1346
16.4k
            TINYGLTF_JSON_FREE(value->u.string.ptr);
1347
16.4k
            break;
1348
9.65k
        case TG3JSON_ARRAY:
1349
16.2M
            for (i = 0; i < value->u.array.count; ++i) {
1350
16.2M
                tg3json_value_free(&value->u.array.items[i]);
1351
16.2M
            }
1352
9.65k
            TINYGLTF_JSON_FREE(value->u.array.items);
1353
9.65k
            break;
1354
235k
        case TG3JSON_OBJECT:
1355
1.07M
            for (i = 0; i < value->u.object.count; ++i) {
1356
837k
                TINYGLTF_JSON_FREE(value->u.object.items[i].key);
1357
837k
                if (value->u.object.items[i].value) {
1358
837k
                    tg3json_value_free(value->u.object.items[i].value);
1359
837k
                    TINYGLTF_JSON_FREE(value->u.object.items[i].value);
1360
837k
                }
1361
837k
            }
1362
235k
            TINYGLTF_JSON_FREE(value->u.object.items);
1363
235k
            break;
1364
187
        case TG3JSON_NULL:
1365
1.33k
        case TG3JSON_BOOL:
1366
16.8M
        case TG3JSON_INT:
1367
17.4M
        case TG3JSON_REAL:
1368
            /* Scalar variants own no heap memory. */
1369
17.4M
            break;
1370
17.7M
    }
1371
17.7M
    tg3json__init_value(value);
1372
17.7M
}
1373
1374
0
void tg3json_value_init_null(tg3json_value *value) {
1375
0
    tg3json__init_value(value);
1376
0
}
1377
1378
0
void tg3json_value_init_bool(tg3json_value *value, int boolean_value) {
1379
0
    tg3json__init_value(value);
1380
0
    value->type = TG3JSON_BOOL;
1381
0
    value->u.boolean = boolean_value ? 1 : 0;
1382
0
}
1383
1384
0
void tg3json_value_init_int(tg3json_value *value, int64_t integer_value) {
1385
0
    tg3json__init_value(value);
1386
0
    value->type = TG3JSON_INT;
1387
0
    value->u.integer = integer_value;
1388
0
}
1389
1390
0
void tg3json_value_init_real(tg3json_value *value, double real_value) {
1391
0
    tg3json__init_value(value);
1392
0
    value->type = TG3JSON_REAL;
1393
0
    value->u.real = real_value;
1394
0
}
1395
1396
0
int tg3json_value_init_string_n(tg3json_value *value, const char *str, size_t len) {
1397
0
    tg3json__init_value(value);
1398
0
    value->type = TG3JSON_STRING;
1399
0
    value->u.string.ptr = tg3json__strndup_local(str ? str : "", str ? len : 0);
1400
0
    if (!value->u.string.ptr) {
1401
0
        tg3json__init_value(value);
1402
0
        return 0;
1403
0
    }
1404
0
    value->u.string.len = str ? len : 0;
1405
0
    return 1;
1406
0
}
1407
1408
0
int tg3json_value_init_string(tg3json_value *value, const char *str) {
1409
0
    return tg3json_value_init_string_n(value, str, str ? TINYGLTF_JSON_STRLEN(str) : 0);
1410
0
}
1411
1412
0
void tg3json_value_init_array(tg3json_value *value) {
1413
0
    tg3json__init_value(value);
1414
0
    value->type = TG3JSON_ARRAY;
1415
0
}
1416
1417
0
void tg3json_value_init_object(tg3json_value *value) {
1418
0
    tg3json__init_value(value);
1419
0
    value->type = TG3JSON_OBJECT;
1420
0
}
1421
1422
0
int tg3json_value_copy(tg3json_value *dst, const tg3json_value *src) {
1423
0
    size_t i;
1424
0
    tg3json__init_value(dst);
1425
0
    if (!src) return 1;
1426
0
    switch (src->type) {
1427
0
        case TG3JSON_NULL:
1428
0
            return 1;
1429
0
        case TG3JSON_BOOL:
1430
0
            tg3json_value_init_bool(dst, src->u.boolean);
1431
0
            return 1;
1432
0
        case TG3JSON_INT:
1433
0
            tg3json_value_init_int(dst, src->u.integer);
1434
0
            return 1;
1435
0
        case TG3JSON_REAL:
1436
0
            tg3json_value_init_real(dst, src->u.real);
1437
0
            return 1;
1438
0
        case TG3JSON_STRING:
1439
0
            return tg3json_value_init_string_n(dst, src->u.string.ptr, src->u.string.len);
1440
0
        case TG3JSON_ARRAY:
1441
0
            tg3json_value_init_array(dst);
1442
0
            for (i = 0; i < src->u.array.count; ++i) {
1443
0
                if (!tg3json_array_append_copy(dst, &src->u.array.items[i])) {
1444
0
                    tg3json_value_free(dst);
1445
0
                    return 0;
1446
0
                }
1447
0
            }
1448
0
            return 1;
1449
0
        case TG3JSON_OBJECT:
1450
0
            tg3json_value_init_object(dst);
1451
0
            for (i = 0; i < src->u.object.count; ++i) {
1452
0
                if (!tg3json_object_set_copy_n(dst, src->u.object.items[i].key,
1453
0
                                               src->u.object.items[i].key_len,
1454
0
                                               src->u.object.items[i].value)) {
1455
0
                    tg3json_value_free(dst);
1456
0
                    return 0;
1457
0
                }
1458
0
            }
1459
0
            return 1;
1460
0
    }
1461
0
    return 0; /* unreachable: all enum cases handled above. */
1462
0
}
1463
1464
const tg3json_value *tg3json_object_get_n(const tg3json_value *object,
1465
7.67M
                                          const char *key, size_t key_len) {
1466
7.67M
    size_t i;
1467
7.67M
    if (!object || object->type != TG3JSON_OBJECT) return NULL;
1468
4.51M
    for (i = 0; i < object->u.object.count; ++i) {
1469
2.83M
        const tg3json_object_entry *entry = &object->u.object.items[i];
1470
2.83M
        if (entry->key_len == key_len && TINYGLTF_JSON_MEMCMP(entry->key, key, key_len) == 0) {
1471
20.3k
            return entry->value;
1472
20.3k
        }
1473
2.83M
    }
1474
1.68M
    return NULL;
1475
1.70M
}
1476
1477
const tg3json_value *tg3json_object_get(const tg3json_value *object,
1478
7.67M
                                        const char *key) {
1479
7.67M
    if (!key) return NULL;
1480
7.67M
    return tg3json_object_get_n(object, key, TINYGLTF_JSON_STRLEN(key));
1481
7.67M
}
1482
1483
tg3json_value *tg3json_object_get_mut_n(tg3json_value *object,
1484
0
                                        const char *key, size_t key_len) {
1485
0
    size_t i;
1486
0
    if (!object || object->type != TG3JSON_OBJECT) return NULL;
1487
0
    for (i = 0; i < object->u.object.count; ++i) {
1488
0
        tg3json_object_entry *entry = &object->u.object.items[i];
1489
0
        if (entry->key_len == key_len && TINYGLTF_JSON_MEMCMP(entry->key, key, key_len) == 0) {
1490
0
            return entry->value;
1491
0
        }
1492
0
    }
1493
0
    return NULL;
1494
0
}
1495
1496
0
tg3json_value *tg3json_object_get_mut(tg3json_value *object, const char *key) {
1497
0
    if (!key) return NULL;
1498
0
    return tg3json_object_get_mut_n(object, key, TINYGLTF_JSON_STRLEN(key));
1499
0
}
1500
1501
const tg3json_object_entry *tg3json_object_at(const tg3json_value *object,
1502
390k
                                              size_t index) {
1503
390k
    if (!object || object->type != TG3JSON_OBJECT || index >= object->u.object.count) {
1504
0
        return NULL;
1505
0
    }
1506
390k
    return &object->u.object.items[index];
1507
390k
}
1508
1509
5.85k
size_t tg3json_object_size(const tg3json_value *object) {
1510
5.85k
    if (!object || object->type != TG3JSON_OBJECT) return 0;
1511
5.85k
    return object->u.object.count;
1512
5.85k
}
1513
1514
int tg3json_object_set_take_n(tg3json_value *object, const char *key, size_t key_len,
1515
0
                              tg3json_value *value) {
1516
0
    tg3json_value *existing;
1517
0
    tg3json_object_entry *entry;
1518
0
    size_t cap;
1519
0
    if (!object || object->type != TG3JSON_OBJECT || !value || !key) return 0;
1520
0
    existing = tg3json_object_get_mut_n(object, key, key_len);
1521
0
    if (existing) {
1522
0
        tg3json_value_free(existing);
1523
0
        *existing = *value;
1524
0
        tg3json__init_value(value);
1525
0
        return 1;
1526
0
    }
1527
0
    cap = object->u.object.count;
1528
0
    if (!tg3json__reserve_bytes((void **)&object->u.object.items, sizeof(*object->u.object.items),
1529
0
                                object->u.object.count + 1, &cap)) {
1530
0
        return 0;
1531
0
    }
1532
0
    entry = &object->u.object.items[object->u.object.count];
1533
0
    entry->key = tg3json__strndup_local(key, key_len);
1534
0
    if (!entry->key) return 0;
1535
0
    entry->key_len = key_len;
1536
0
    entry->value = (tg3json_value *)TINYGLTF_JSON_MALLOC(sizeof(tg3json_value));
1537
0
    if (!entry->value) {
1538
0
        TINYGLTF_JSON_FREE(entry->key);
1539
0
        entry->key = NULL;
1540
0
        entry->key_len = 0;
1541
0
        return 0;
1542
0
    }
1543
0
    *entry->value = *value;
1544
0
    tg3json__init_value(value);
1545
0
    object->u.object.count += 1;
1546
0
    return 1;
1547
0
}
1548
1549
int tg3json_object_set_take(tg3json_value *object, const char *key,
1550
0
                            tg3json_value *value) {
1551
0
    if (!key) return 0;
1552
0
    return tg3json_object_set_take_n(object, key, TINYGLTF_JSON_STRLEN(key), value);
1553
0
}
1554
1555
int tg3json_object_set_copy_n(tg3json_value *object, const char *key, size_t key_len,
1556
0
                              const tg3json_value *value) {
1557
0
    tg3json_value copy;
1558
0
    tg3json__init_value(&copy);
1559
0
    if (!tg3json_value_copy(&copy, value)) return 0;
1560
0
    if (!tg3json_object_set_take_n(object, key, key_len, &copy)) {
1561
0
        tg3json_value_free(&copy);
1562
0
        return 0;
1563
0
    }
1564
0
    return 1;
1565
0
}
1566
1567
int tg3json_object_set_copy(tg3json_value *object, const char *key,
1568
0
                            const tg3json_value *value) {
1569
0
    if (!key) return 0;
1570
0
    return tg3json_object_set_copy_n(object, key, TINYGLTF_JSON_STRLEN(key), value);
1571
0
}
1572
1573
11.7M
const tg3json_value *tg3json_array_get(const tg3json_value *array, size_t index) {
1574
11.7M
    if (!array || array->type != TG3JSON_ARRAY || index >= array->u.array.count) {
1575
0
        return NULL;
1576
0
    }
1577
11.7M
    return &array->u.array.items[index];
1578
11.7M
}
1579
1580
2.89k
size_t tg3json_array_size(const tg3json_value *array) {
1581
2.89k
    if (!array || array->type != TG3JSON_ARRAY) return 0;
1582
2.89k
    return array->u.array.count;
1583
2.89k
}
1584
1585
0
int tg3json_array_append_take(tg3json_value *array, tg3json_value *value) {
1586
0
    size_t cap;
1587
0
    if (!array || array->type != TG3JSON_ARRAY || !value) return 0;
1588
0
    cap = array->u.array.count;
1589
0
    if (!tg3json__reserve_bytes((void **)&array->u.array.items, sizeof(*array->u.array.items),
1590
0
                                array->u.array.count + 1, &cap)) {
1591
0
        return 0;
1592
0
    }
1593
0
    array->u.array.items[array->u.array.count++] = *value;
1594
0
    tg3json__init_value(value);
1595
0
    return 1;
1596
0
}
1597
1598
0
int tg3json_array_append_copy(tg3json_value *array, const tg3json_value *value) {
1599
0
    tg3json_value copy;
1600
0
    tg3json__init_value(&copy);
1601
0
    if (!tg3json_value_copy(&copy, value)) return 0;
1602
0
    if (!tg3json_array_append_take(array, &copy)) {
1603
0
        tg3json_value_free(&copy);
1604
0
        return 0;
1605
0
    }
1606
0
    return 1;
1607
0
}
1608
1609
0
static int tg3json__indent(tg3json__buffer *buf, int indent, int depth) {
1610
0
    int i;
1611
0
    if (indent <= 0) return 1;
1612
0
    if (!tg3json__buf_putc(buf, '\n')) return 0;
1613
0
    for (i = 0; i < indent * depth; ++i) {
1614
0
        if (!tg3json__buf_putc(buf, ' ')) return 0;
1615
0
    }
1616
0
    return 1;
1617
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__indent(tg3json__buffer*, int, int)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__indent
1618
1619
static int tg3json__stringify_value_ex(tg3json__buffer *buf, const tg3json_value *value,
1620
0
                                       int indent, int depth) {
1621
0
    size_t i;
1622
0
    char numbuf[64];
1623
0
    switch (value->type) {
1624
0
        case TG3JSON_NULL:
1625
0
            return tg3json__buf_append(buf, "null", 4);
1626
0
        case TG3JSON_BOOL:
1627
0
            return value->u.boolean ? tg3json__buf_append(buf, "true", 4)
1628
0
                                    : tg3json__buf_append(buf, "false", 5);
1629
0
        case TG3JSON_INT:
1630
0
            tg3json__itoa(value->u.integer, numbuf);
1631
0
            return tg3json__buf_append(buf, numbuf, TINYGLTF_JSON_STRLEN(numbuf));
1632
0
        case TG3JSON_REAL:
1633
0
            {
1634
0
                char *end = tg3json__dtoa_c(value->u.real, numbuf);
1635
0
                *end = '\0';
1636
0
                const char *b = numbuf;
1637
0
                if (*b == '-') ++b;
1638
0
                if (*b == 'n' || *b == 'N' || *b == 'i' || *b == 'I') {
1639
0
                    return tg3json__buf_append(buf, "null", 4);
1640
0
                }
1641
0
            }
1642
0
            return tg3json__buf_append(buf, numbuf, TINYGLTF_JSON_STRLEN(numbuf));
1643
0
        case TG3JSON_STRING:
1644
0
            if (!tg3json__buf_putc(buf, '"')) return 0;
1645
0
            for (i = 0; i < value->u.string.len; ++i) {
1646
0
                unsigned char c = (unsigned char)value->u.string.ptr[i];
1647
0
                switch (c) {
1648
0
                    case '"': if (!tg3json__buf_append(buf, "\\\"", 2)) return 0; break;
1649
0
                    case '\\': if (!tg3json__buf_append(buf, "\\\\", 2)) return 0; break;
1650
0
                    case '\b': if (!tg3json__buf_append(buf, "\\b", 2)) return 0; break;
1651
0
                    case '\f': if (!tg3json__buf_append(buf, "\\f", 2)) return 0; break;
1652
0
                    case '\n': if (!tg3json__buf_append(buf, "\\n", 2)) return 0; break;
1653
0
                    case '\r': if (!tg3json__buf_append(buf, "\\r", 2)) return 0; break;
1654
0
                    case '\t': if (!tg3json__buf_append(buf, "\\t", 2)) return 0; break;
1655
0
                    default:
1656
0
                        if (c < 0x20u) {
1657
0
                            numbuf[0] = '\\';
1658
0
                            numbuf[1] = 'u';
1659
0
                            numbuf[2] = '0';
1660
0
                            numbuf[3] = '0';
1661
0
                            numbuf[4] = "0123456789abcdef"[(c >> 4) & 0xf];
1662
0
                            numbuf[5] = "0123456789abcdef"[c & 0xf];
1663
0
                            numbuf[6] = '\0';
1664
0
                            if (!tg3json__buf_append(buf, numbuf, 6)) return 0;
1665
0
                        } else {
1666
0
                            if (!tg3json__buf_putc(buf, (char)c)) return 0;
1667
0
                        }
1668
0
                        break;
1669
0
                }
1670
0
            }
1671
0
            return tg3json__buf_putc(buf, '"');
1672
0
        case TG3JSON_ARRAY:
1673
0
            if (!tg3json__buf_putc(buf, '[')) return 0;
1674
0
            for (i = 0; i < value->u.array.count; ++i) {
1675
0
                if (i > 0 && !tg3json__buf_putc(buf, ',')) return 0;
1676
0
                if (indent > 0 && !tg3json__indent(buf, indent, depth + 1)) return 0;
1677
0
                if (!tg3json__stringify_value_ex(buf, &value->u.array.items[i], indent, depth + 1)) return 0;
1678
0
            }
1679
0
            if (indent > 0 && value->u.array.count > 0 && !tg3json__indent(buf, indent, depth)) return 0;
1680
0
            return tg3json__buf_putc(buf, ']');
1681
0
        case TG3JSON_OBJECT:
1682
0
            if (!tg3json__buf_putc(buf, '{')) return 0;
1683
0
            for (i = 0; i < value->u.object.count; ++i) {
1684
0
                tg3json_value key_value;
1685
0
                if (i > 0 && !tg3json__buf_putc(buf, ',')) return 0;
1686
0
                if (indent > 0 && !tg3json__indent(buf, indent, depth + 1)) return 0;
1687
0
                tg3json__init_value(&key_value);
1688
0
                key_value.type = TG3JSON_STRING;
1689
0
                key_value.u.string.ptr = value->u.object.items[i].key;
1690
0
                key_value.u.string.len = value->u.object.items[i].key_len;
1691
0
                if (!tg3json__stringify_value_ex(buf, &key_value, indent, depth + 1)) return 0;
1692
0
                if (!tg3json__buf_putc(buf, ':')) return 0;
1693
0
                if (indent > 0 && !tg3json__buf_putc(buf, ' ')) return 0;
1694
0
                if (!tg3json__stringify_value_ex(buf, value->u.object.items[i].value, indent, depth + 1)) return 0;
1695
0
            }
1696
0
            if (indent > 0 && value->u.object.count > 0 && !tg3json__indent(buf, indent, depth)) return 0;
1697
0
            return tg3json__buf_putc(buf, '}');
1698
0
    }
1699
0
    return 0; /* unreachable: all enum cases handled above. */
1700
0
}
Unexecuted instantiation: fuzz_gltf_v3.cc:tg3json__stringify_value_ex(tg3json__buffer*, tg3json_value const*, int, int)
Unexecuted instantiation: tiny_gltf_v3.c:tg3json__stringify_value_ex
1701
1702
0
char *tg3json_stringify(const tg3json_value *value, size_t *out_len) {
1703
0
    tg3json__buffer buf;
1704
0
    TINYGLTF_JSON_MEMSET(&buf, 0, sizeof(buf));
1705
0
    if (!value || !tg3json__stringify_value_ex(&buf, value, -1, 0)) {
1706
0
        TINYGLTF_JSON_FREE(buf.data);
1707
0
        if (out_len) *out_len = 0;
1708
0
        return NULL;
1709
0
    }
1710
0
    if (!buf.data) {
1711
0
        buf.data = (char *)TINYGLTF_JSON_MALLOC(1);
1712
0
        if (!buf.data) {
1713
0
            if (out_len) *out_len = 0;
1714
0
            return NULL;
1715
0
        }
1716
0
        buf.data[0] = '\0';
1717
0
    }
1718
0
    if (out_len) *out_len = buf.len;
1719
0
    return buf.data;
1720
0
}
1721
1722
0
char *tg3json_stringify_pretty(const tg3json_value *value, int indent, size_t *out_len) {
1723
0
    tg3json__buffer buf;
1724
0
    TINYGLTF_JSON_MEMSET(&buf, 0, sizeof(buf));
1725
0
    if (!value || !tg3json__stringify_value_ex(&buf, value, indent, 0)) {
1726
0
        TINYGLTF_JSON_FREE(buf.data);
1727
0
        if (out_len) *out_len = 0;
1728
0
        return NULL;
1729
0
    }
1730
0
    if (!buf.data) {
1731
0
        buf.data = (char *)TINYGLTF_JSON_MALLOC(1);
1732
0
        if (!buf.data) {
1733
0
            if (out_len) *out_len = 0;
1734
0
            return NULL;
1735
0
        }
1736
0
        buf.data[0] = '\0';
1737
0
    }
1738
0
    if (out_len) *out_len = buf.len;
1739
0
    return buf.data;
1740
0
}
1741
1742
#endif /* TINYGLTF_JSON_C_IMPLEMENTATION */
1743
#endif /* TINYGLTF_JSON_C_H_ */