Update JSON parser to latest version from https://github.com/udp/json-parser

This commit is contained in:
Dianne Skoll
2025-03-22 12:09:30 -04:00
parent caf5f81eb0
commit ed15b7deb5
2 changed files with 122 additions and 102 deletions
+100 -88
View File
@@ -1,7 +1,7 @@
/* vim: set et ts=3 sw=3 sts=3 ft=c:
*
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
* https://github.com/udp/json-parser
* Copyright (C) 2012-2021 the json-parser authors All rights reserved.
* https://github.com/json-parser/json-parser
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,36 +29,49 @@
#include "json.h"
#define UNUSED(x) ( (void) x )
#ifdef _MSC_VER
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 might give us uintptr_t and UINTPTR_MAX but they also might not be provided */
#include <stdint.h>
#endif
const struct _json_value json_value_none;
#ifndef JSON_INT_T_OVERRIDDEN
#if defined(_MSC_VER)
/* https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges */
#define JSON_INT_MAX 9223372036854775807LL
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 */
#define JSON_INT_MAX INT_FAST64_MAX
#else
/* C89 */
#include <limits.h>
#define JSON_INT_MAX LONG_MAX
#endif
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#ifndef JSON_INT_MAX
#define JSON_INT_MAX (json_int_t)(((unsigned json_int_t)(-1)) / (unsigned json_int_t)2);
#endif
typedef unsigned int json_uchar;
/* There has to be a better way to do this */
static const json_int_t JSON_INT_MAX = sizeof(json_int_t) == 1
? INT8_MAX
: (sizeof(json_int_t) == 2
? INT16_MAX
: (sizeof(json_int_t) == 4
? INT32_MAX
: INT64_MAX));
const struct _json_value json_value_none;
static unsigned char hex_value (json_char c)
{
if (isdigit(c))
if (isdigit((unsigned char)c))
return c - '0';
switch (c) {
@@ -79,10 +92,7 @@ static int would_overflow (json_int_t value, json_char b)
typedef struct
{
unsigned long used_memory;
unsigned int uint_max;
unsigned long ulong_max;
size_t used_memory;
json_settings settings;
int first_pass;
@@ -94,19 +104,19 @@ typedef struct
static void * default_alloc (size_t size, int zero, void * user_data)
{
UNUSED(user_data);
return zero ? calloc (1, size) : malloc (size);
(void)user_data; /* ignore unused-parameter warn */
return zero ? calloc (1, size) : malloc (size);
}
static void default_free (void * ptr, void * user_data)
{
UNUSED(user_data);
free (ptr);
(void)user_data; /* ignore unused-parameter warn */
free (ptr);
}
static void * json_alloc (json_state * state, unsigned long size, int zero)
static void * json_alloc (json_state * state, size_t size, int zero)
{
if ((state->ulong_max - state->used_memory) < size)
if ((ULONG_MAX - 8 - state->used_memory) < size)
return 0;
if (state->settings.max_memory
@@ -123,7 +133,7 @@ static int new_value (json_state * state,
json_type type)
{
json_value * value;
int values_size;
size_t values_size;
if (!state->first_pass)
{
@@ -157,14 +167,16 @@ static int new_value (json_state * state,
values_size = sizeof (*value->u.object.values) * value->u.object.length;
if (! (value->u.object.values = (json_object_entry *) json_alloc
(state, values_size + ((unsigned long) value->u.object.values), 0)) )
#ifdef UINTPTR_MAX
(state, values_size + ((uintptr_t) value->u.object.values), 0)) )
#else
(state, values_size + ((size_t) value->u.object.values), 0)) )
#endif
{
return 0;
}
char *s = (char *) value->u.object.values;
s += values_size;
value->_reserved.object_mem = s;
value->_reserved.object_mem = (void *) (((char *) value->u.object.values) + values_size);
value->u.object.length = 0;
break;
@@ -213,8 +225,8 @@ static int new_value (json_state * state,
}
#define whitespace \
case '\n': ++ state.cur_line; state.cur_col = 0; /* FALLTHRU */ \
case ' ': case '\t': case '\r'
case '\n': ++ state.cur_line; state.cur_col = 0; /* FALLTHRU */ \
case ' ': /* FALLTHRU */ case '\t': /* FALLTHRU */ case '\r'
#define string_add(b) \
do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
@@ -245,13 +257,13 @@ json_value * json_parse_ex (json_settings * settings,
size_t length,
char * error_buf)
{
json_char error [json_error_max];
char error [json_error_max];
const json_char * end;
json_value * top, * root, * alloc = 0;
json_state state = { 0 };
long flags;
double num_digits = 0, num_e = 0;
double num_fraction = 0;
long flags = 0;
int num_digits = 0;
double num_e = 0, num_fraction = 0;
/* Skip UTF-8 BOM
*/
@@ -274,12 +286,6 @@ json_value * json_parse_ex (json_settings * settings,
if (!state.settings.mem_free)
state.settings.mem_free = default_free;
memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
state.uint_max -= 8; /* limit of how much can be added before next check */
state.ulong_max -= 8;
for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
{
json_uchar uchar;
@@ -299,11 +305,11 @@ json_value * json_parse_ex (json_settings * settings,
if (flags & flag_string)
{
if (!b)
{ snprintf (error, sizeof(error), "Unexpected EOF in string (at %u:%u)", line_and_col);
{ sprintf (error, "%u:%u: Unexpected EOF in string", line_and_col);
goto e_failed;
}
if (string_length > state.uint_max)
if (string_length > UINT_MAX - 8)
goto e_overflow;
if (flags & flag_escaped)
@@ -325,7 +331,7 @@ json_value * json_parse_ex (json_settings * settings,
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
{
snprintf (error, sizeof(error), "Invalid character value `%c` (at %u:%u)", b, line_and_col);
sprintf (error, "%u:%u: Invalid character value `%c`", line_and_col, b);
goto e_failed;
}
@@ -342,7 +348,7 @@ json_value * json_parse_ex (json_settings * settings,
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
{
snprintf (error, sizeof(error), "Invalid character value `%c` (at %u:%u)", b, line_and_col);
sprintf (error, "%u:%u: Invalid character value `%c`", line_and_col, b);
goto e_failed;
}
@@ -426,11 +432,12 @@ json_value * json_parse_ex (json_settings * settings,
case json_object:
if (state.first_pass) {
char *s = (char *) top->u.object.values;
s += string_length+1;
top->u.object.values = (void *) s;
} else {
if (state.first_pass) {
json_char **chars = (json_char **) &top->u.object.values;
chars[0] += string_length + 1;
}
else
{
top->u.object.values [top->u.object.length].name
= (json_char *) top->_reserved.object_mem;
@@ -472,7 +479,7 @@ json_value * json_parse_ex (json_settings * settings,
if (flags & flag_block_comment)
{
if (!b)
{ snprintf (error, sizeof(error), "%u:%u: Unexpected EOF in block comment", line_and_col);
{ sprintf (error, "%u:%u: Unexpected EOF in block comment", line_and_col);
goto e_failed;
}
@@ -488,12 +495,12 @@ json_value * json_parse_ex (json_settings * settings,
else if (b == '/')
{
if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
{ snprintf (error, sizeof(error), "%u:%u: Comment not allowed here", line_and_col);
{ sprintf (error, "%u:%u: Comment not allowed here", line_and_col);
goto e_failed;
}
if (++ state.ptr == end)
{ snprintf (error, sizeof(error), "%u:%u: EOF unexpected", line_and_col);
{ sprintf (error, "%u:%u: EOF unexpected", line_and_col);
goto e_failed;
}
@@ -508,7 +515,7 @@ json_value * json_parse_ex (json_settings * settings,
continue;
default:
snprintf (error, sizeof(error), "%u:%u: Unexpected `%c` in comment opening sequence", line_and_col, b);
sprintf (error, "%u:%u: Unexpected `%c` in comment opening sequence", line_and_col, b);
goto e_failed;
};
}
@@ -526,8 +533,8 @@ json_value * json_parse_ex (json_settings * settings,
default:
snprintf (error, sizeof(error), "%u:%u: Trailing garbage: `%c`",
state.cur_line, state.cur_col, b);
sprintf (error, "%u:%u: Trailing garbage: `%c`",
line_and_col, b);
goto e_failed;
};
@@ -545,7 +552,7 @@ json_value * json_parse_ex (json_settings * settings,
if (top && top->type == json_array)
flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
else
{ snprintf (error, sizeof(error), "%u:%u: Unexpected ]", line_and_col);
{ sprintf (error, "%u:%u: Unexpected `]`", line_and_col);
goto e_failed;
}
@@ -561,8 +568,8 @@ json_value * json_parse_ex (json_settings * settings,
}
else
{
snprintf (error, sizeof(error), "%u:%u: Expected , before %c",
state.cur_line, state.cur_col, b);
sprintf (error, "%u:%u: Expected `,` before `%c`",
line_and_col, b);
goto e_failed;
}
@@ -576,8 +583,8 @@ json_value * json_parse_ex (json_settings * settings,
}
else
{
snprintf (error, sizeof(error), "%u:%u: Expected : before %c",
state.cur_line, state.cur_col, b);
sprintf (error, "%u:%u: Expected `:` before `%c`",
line_and_col, b);
goto e_failed;
}
@@ -616,7 +623,7 @@ json_value * json_parse_ex (json_settings * settings,
case 't':
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
if ((end - state.ptr) <= 3 || *(++ state.ptr) != 'r' ||
*(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
{
goto e_unknown_value;
@@ -632,7 +639,7 @@ json_value * json_parse_ex (json_settings * settings,
case 'f':
if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
if ((end - state.ptr) <= 4 || *(++ state.ptr) != 'a' ||
*(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
*(++ state.ptr) != 'e')
{
@@ -647,7 +654,7 @@ json_value * json_parse_ex (json_settings * settings,
case 'n':
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
if ((end - state.ptr) <= 3 || *(++ state.ptr) != 'u' ||
*(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
{
goto e_unknown_value;
@@ -661,14 +668,14 @@ json_value * json_parse_ex (json_settings * settings,
default:
if (isdigit (b) || b == '-')
if (isdigit ((unsigned char) b) || b == '-')
{
if (!new_value (&state, &top, &root, &alloc, json_integer))
goto e_alloc_failure;
if (!state.first_pass)
{
while (isdigit (b) || b == '+' || b == '-'
while (isdigit ((unsigned char) b) || b == '+' || b == '-'
|| b == 'e' || b == 'E' || b == '.')
{
if ( (++ state.ptr) == end)
@@ -702,7 +709,7 @@ json_value * json_parse_ex (json_settings * settings,
continue;
}
else
{ snprintf (error, sizeof(error), "%u:%u: Unexpected %c when seeking value", line_and_col, b);
{ sprintf (error, "%u:%u: Unexpected `%c` when seeking value", line_and_col, b);
goto e_failed;
}
};
@@ -722,7 +729,7 @@ json_value * json_parse_ex (json_settings * settings,
case '"':
if (flags & flag_need_comma)
{ snprintf (error, sizeof(error), "%u:%u: Expected , before \"", line_and_col);
{ sprintf (error, "%u:%u: Expected `,` before `\"`", line_and_col);
goto e_failed;
}
@@ -744,10 +751,10 @@ json_value * json_parse_ex (json_settings * settings,
{
flags &= ~ flag_need_comma;
break;
}
/* FALLTHROUGH */
} /* FALLTHRU */
default:
snprintf (error, sizeof(error), "%u:%u: Unexpected `%c` in object", line_and_col, b);
sprintf (error, "%u:%u: Unexpected `%c` in object", line_and_col, b);
goto e_failed;
};
@@ -756,7 +763,7 @@ json_value * json_parse_ex (json_settings * settings,
case json_integer:
case json_double:
if (isdigit (b))
if (isdigit ((unsigned char)b))
{
++ num_digits;
@@ -765,7 +772,7 @@ json_value * json_parse_ex (json_settings * settings,
if (! (flags & flag_num_e))
{
if (flags & flag_num_zero)
{ snprintf (error, sizeof(error), "%u:%u: Unexpected `0` before `%c`", line_and_col, b);
{ sprintf (error, "%u:%u: Unexpected `0` before `%c`", line_and_col, b);
goto e_failed;
}
@@ -780,10 +787,12 @@ json_value * json_parse_ex (json_settings * settings,
}
if (would_overflow(top->u.integer, b))
{ -- num_digits;
{
json_int_t integer = top->u.integer;
-- num_digits;
-- state.ptr;
top->type = json_double;
top->u.dbl = (double)top->u.integer;
top->u.dbl = (double)integer;
continue;
}
@@ -813,13 +822,15 @@ json_value * json_parse_ex (json_settings * settings,
}
else if (b == '.' && top->type == json_integer)
{
json_int_t integer = top->u.integer;
if (!num_digits)
{ snprintf (error, sizeof(error), "%u:%u: Expected digit before `.`", line_and_col);
{ sprintf (error, "%u:%u: Expected digit before `.`", line_and_col);
goto e_failed;
}
top->type = json_double;
top->u.dbl = (double) top->u.integer;
top->u.dbl = (double) integer;
flags |= flag_num_got_decimal;
num_digits = 0;
@@ -831,7 +842,7 @@ json_value * json_parse_ex (json_settings * settings,
if (top->type == json_double)
{
if (!num_digits)
{ snprintf (error, sizeof(error), "%u:%u: Expected digit after `.`", line_and_col);
{ sprintf (error, "%u:%u: Expected digit after `.`", line_and_col);
goto e_failed;
}
@@ -844,8 +855,9 @@ json_value * json_parse_ex (json_settings * settings,
if (top->type == json_integer)
{
json_int_t integer = top->u.integer;
top->type = json_double;
top->u.dbl = (double) top->u.integer;
top->u.dbl = (double) integer;
}
num_digits = 0;
@@ -857,11 +869,11 @@ json_value * json_parse_ex (json_settings * settings,
else
{
if (!num_digits)
{ snprintf (error, sizeof(error), "%u:%u: Expected digit after `e`", line_and_col);
{ sprintf (error, "%u:%u: Expected digit after `e`", line_and_col);
goto e_failed;
}
top->u.dbl *= pow (10.0, ((flags & flag_num_e_negative) ? - num_e : num_e));
top->u.dbl *= pow (10.0, (flags & flag_num_e_negative ? - num_e : num_e));
}
if (flags & flag_num_negative)
@@ -926,7 +938,7 @@ json_value * json_parse_ex (json_settings * settings,
};
}
if ( (++ top->parent->u.array.length) > state.uint_max)
if ( (++ top->parent->u.array.length) > UINT_MAX - 8)
goto e_overflow;
top = top->parent;
@@ -942,7 +954,7 @@ json_value * json_parse_ex (json_settings * settings,
e_unknown_value:
snprintf (error, sizeof(error), "%u:%u: Unknown value", line_and_col);
sprintf (error, "%u:%u: Unknown value", line_and_col);
goto e_failed;
e_alloc_failure:
@@ -952,7 +964,7 @@ e_alloc_failure:
e_overflow:
snprintf (error, sizeof(error), "%u:%u: Too long (caught overflow)", line_and_col);
sprintf (error, "%u:%u: Too long (caught overflow)", line_and_col);
goto e_failed;
e_failed: