/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(©); |
1559 | 0 | if (!tg3json_value_copy(©, value)) return 0; |
1560 | 0 | if (!tg3json_object_set_take_n(object, key, key_len, ©)) { |
1561 | 0 | tg3json_value_free(©); |
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(©); |
1601 | 0 | if (!tg3json_value_copy(©, value)) return 0; |
1602 | 0 | if (!tg3json_array_append_take(array, ©)) { |
1603 | 0 | tg3json_value_free(©); |
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_ */ |