From 869a03432a03189e31338827ad5dd56aa900a7a5 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Fri, 17 Mar 2023 09:15:50 +0100 Subject: [PATCH] webservices/json: update the JSON parser to version 1.1.0 json_parse_ex() now requires the length of the JSON string to parse. The following changes are integrated: * 672dd79c402b5f88c469c92b64e8e382db4cab2e (int64 on Windows), * ecb7c847198dc1cd392e0beecb5ef63a37d3fa6c (proper include guards), * c8edcab8cd6c53d39264a59dacbcabe65b2b2c98 (null deref), * 894bab1c0a2dd6cca72629df7426afc1be102dfe (fallthrough warning) The (unused) json_relaxed_commas flag is gone. We may also use it as a contrib. --- modules/misc/webservices/json.c | 405 +++++++++++++----- modules/misc/webservices/json.h | 73 +++- modules/misc/webservices/json_helper.h | 2 +- .../stream_out/chromecast/chromecast_ctrl.cpp | 8 +- 4 files changed, 354 insertions(+), 134 deletions(-) diff --git a/modules/misc/webservices/json.c b/modules/misc/webservices/json.c index ae7044601d..e5dc476f16 100644 --- a/modules/misc/webservices/json.c +++ b/modules/misc/webservices/json.c @@ -1,6 +1,6 @@ -/* vim: set et ts=3 sw=3 ft=c: +/* vim: set et ts=3 sw=3 sts=3 ft=c: * - * Copyright (C) 2012 James McLaughlin et al. All rights reserved. + * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. * https://github.com/udp/json-parser * * Redistribution and use in source and binary forms, with or without @@ -35,50 +35,58 @@ #endif #endif -#ifdef __cplusplus - const struct _json_value json_value_none; /* zero-d by ctor */ -#else - const struct _json_value json_value_none = { 0, 0, { 0 }, { 0 } }; -#endif +const struct _json_value json_value_none; -#include #include #include #include #include -typedef unsigned short json_uchar; +typedef unsigned int json_uchar; static unsigned char hex_value (json_char c) { - if (c >= 'A' && c <= 'F') - return (c - 'A') + 10; - - if (c >= 'a' && c <= 'f') - return (c - 'a') + 10; - - if (c >= '0' && c <= '9') + if (isdigit(c)) return c - '0'; - return 0xFF; + switch (c) { + case 'a': case 'A': return 0x0A; + case 'b': case 'B': return 0x0B; + case 'c': case 'C': return 0x0C; + case 'd': case 'D': return 0x0D; + case 'e': case 'E': return 0x0E; + case 'f': case 'F': return 0x0F; + default: return 0xFF; + } } typedef struct { - json_settings settings; - int first_pass; - unsigned long used_memory; unsigned int uint_max; unsigned long ulong_max; + json_settings settings; + int first_pass; + + const json_char * ptr; + unsigned int cur_line, cur_col; + } json_state; -static void * json_alloc (json_state * state, unsigned long size, int zero) +static void * default_alloc (size_t size, int zero, void * user_data) { - void * mem; + return zero ? calloc (1, size) : malloc (size); +} +static void default_free (void * ptr, void * user_data) +{ + free (ptr); +} + +static void * json_alloc (json_state * state, unsigned long size, int zero) +{ if ((state->ulong_max - state->used_memory) < size) return 0; @@ -88,14 +96,12 @@ static void * json_alloc (json_state * state, unsigned long size, int zero) return 0; } - if (! (mem = zero ? calloc (size, 1) : malloc (size))) - return 0; - - return mem; + return state->settings.mem_alloc (size, zero, state->settings.user_data); } -static int new_value - (json_state * state, json_value ** top, json_value ** root, json_value ** alloc, json_type type) +static int new_value (json_state * state, + json_value ** top, json_value ** root, json_value ** alloc, + json_type type) { json_value * value; int values_size; @@ -154,10 +160,11 @@ static int new_value return 1; } - value = (json_value *) json_alloc (state, sizeof (json_value), 1); - - if (!value) + if (! (value = (json_value *) json_alloc + (state, sizeof (json_value) + state->settings.value_extra, 1))) + { return 0; + } if (!*root) *root = value; @@ -165,6 +172,11 @@ static int new_value value->type = type; value->parent = *top; + #ifdef JSON_TRACK_SOURCE + value->line = state->cur_line; + value->col = state->cur_col; + #endif + if (*alloc) (*alloc)->_reserved.next_alloc = value; @@ -173,38 +185,67 @@ static int new_value return 1; } -#define e_off \ - ((int) (i - cur_line_begin)) - #define whitespace \ - case '\n': ++ cur_line; cur_line_begin = i; \ - /* fall through */ \ + case '\n': ++ state.cur_line; state.cur_col = 0; \ case ' ': case '\t': case '\r' #define string_add(b) \ do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0); -static const long - flag_next = 1, flag_reproc = 2, flag_need_comma = 4, flag_seek_value = 8, - flag_escaped = 16, flag_string = 32, flag_need_colon = 64, flag_done = 128, - flag_num_negative = 256, flag_num_zero = 512, flag_num_e = 1024, - flag_num_e_got_sign = 2048, flag_num_e_negative = 4096; +#define line_and_col \ + state.cur_line, state.cur_col -json_value * json_parse_ex (json_settings * settings, const json_char * json, char * error_buf) +static const long + flag_next = 1 << 0, + flag_reproc = 1 << 1, + flag_need_comma = 1 << 2, + flag_seek_value = 1 << 3, + flag_escaped = 1 << 4, + flag_string = 1 << 5, + flag_need_colon = 1 << 6, + flag_done = 1 << 7, + flag_num_negative = 1 << 8, + flag_num_zero = 1 << 9, + flag_num_e = 1 << 10, + flag_num_e_got_sign = 1 << 11, + flag_num_e_negative = 1 << 12, + flag_line_comment = 1 << 13, + flag_block_comment = 1 << 14; + +json_value * json_parse_ex (json_settings * settings, + const json_char * json, + size_t length, + char * error_buf) { - json_char error [128]; - unsigned int cur_line; - const json_char * cur_line_begin, * i; + json_char error [json_error_max]; + const json_char * end; json_value * top, * root, * alloc = 0; - json_state state; + json_state state = { 0 }; long flags; - long num_digits = 0, num_fraction = 0, num_e = 0; + long num_digits = 0, num_e = 0; + json_int_t num_fraction = 0; + + /* Skip UTF-8 BOM + */ + if (length >= 3 && ((unsigned char) json [0]) == 0xEF + && ((unsigned char) json [1]) == 0xBB + && ((unsigned char) json [2]) == 0xBF) + { + json += 3; + length -= 3; + } error[0] = '\0'; + end = (json + length); - memset (&state, 0, sizeof (json_state)); memcpy (&state.settings, settings, sizeof (json_settings)); + if (!state.settings.mem_alloc) + state.settings.mem_alloc = default_alloc; + + 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)); @@ -215,39 +256,22 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch { json_uchar uchar; unsigned char uc_b1, uc_b2, uc_b3, uc_b4; - json_char * string = NULL; + json_char * string = 0; unsigned int string_length = 0; top = root = 0; flags = flag_seek_value; - cur_line = 1; - cur_line_begin = json; + state.cur_line = 1; - for (i = json ;; ++ i) + for (state.ptr = json ;; ++ state.ptr) { - json_char b = *i; - - if (flags & flag_done) - { - if (!b) - break; - - switch (b) - { - whitespace: - continue; - - default: - sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b); - goto e_failed; - }; - } + json_char b = (state.ptr == end ? 0 : *state.ptr); if (flags & flag_string) { if (!b) - { sprintf (error, "Unexpected EOF in string (at %d:%d)", cur_line, e_off); + { sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col); goto e_failed; } @@ -267,19 +291,41 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch case 't': string_add ('\t'); break; case 'u': - if ((uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF - || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF) + if (end - state.ptr < 4 || + (uc_b1 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b2 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b3 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b4 = hex_value (*++ state.ptr)) == 0xFF) { - sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off); + sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col); goto e_failed; } - uc_b1 = uc_b1 * 16 + uc_b2; - uc_b2 = uc_b3 * 16 + uc_b4; + uc_b1 = (uc_b1 << 4) | uc_b2; + uc_b2 = (uc_b3 << 4) | uc_b4; + uchar = (uc_b1 << 8) | uc_b2; - uchar = ((json_char) uc_b1) * 256 + uc_b2; + if ((uchar & 0xF800) == 0xD800) { + json_uchar uchar2; - if (sizeof (json_char) >= sizeof (json_uchar) || (uc_b1 == 0 && uc_b2 <= 0x7F)) + if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' || + (uc_b1 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b2 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b3 = hex_value (*++ state.ptr)) == 0xFF || + (uc_b4 = hex_value (*++ state.ptr)) == 0xFF) + { + sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col); + goto e_failed; + } + + uc_b1 = (uc_b1 << 4) | uc_b2; + uc_b2 = (uc_b3 << 4) | uc_b4; + uchar2 = (uc_b1 << 8) | uc_b2; + + uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF); + } + + if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F)) { string_add ((json_char) uchar); break; @@ -290,19 +336,32 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch if (state.first_pass) string_length += 2; else - { string [string_length ++] = 0xC0 | ((uc_b2 & 0xC0) >> 6) | ((uc_b1 & 0x7) << 2); - string [string_length ++] = 0x80 | (uc_b2 & 0x3F); + { string [string_length ++] = 0xC0 | (uchar >> 6); + string [string_length ++] = 0x80 | (uchar & 0x3F); + } + + break; + } + + if (uchar <= 0xFFFF) { + if (state.first_pass) + string_length += 3; + else + { string [string_length ++] = 0xE0 | (uchar >> 12); + string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F); + string [string_length ++] = 0x80 | (uchar & 0x3F); } break; } if (state.first_pass) - string_length += 3; + string_length += 4; else - { string [string_length ++] = 0xE0 | ((uc_b1 & 0xF0) >> 4); - string [string_length ++] = 0x80 | ((uc_b1 & 0xF) << 2) | ((uc_b2 & 0xC0) >> 6); - string [string_length ++] = 0x80 | (uc_b2 & 0x3F); + { string [string_length ++] = 0xF0 | (uchar >> 18); + string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F); + string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F); + string [string_length ++] = 0x80 | (uchar & 0x3F); } break; @@ -346,6 +405,9 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch top->u.object.values [top->u.object.length].name = (json_char *) top->_reserved.object_mem; + top->u.object.values [top->u.object.length].name_length + = string_length; + (*(json_char **) &top->_reserved.object_mem) += string_length + 1; } @@ -363,6 +425,85 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch } } + if (state.settings.settings & json_enable_comments) + { + if (flags & (flag_line_comment | flag_block_comment)) + { + if (flags & flag_line_comment) + { + if (b == '\r' || b == '\n' || !b) + { + flags &= ~ flag_line_comment; + -- state.ptr; /* so null can be reproc'd */ + } + + continue; + } + + if (flags & flag_block_comment) + { + if (!b) + { sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col); + goto e_failed; + } + + if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/') + { + flags &= ~ flag_block_comment; + ++ state.ptr; /* skip closing sequence */ + } + + continue; + } + } + else if (b == '/') + { + if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object) + { sprintf (error, "%d:%d: Comment not allowed here", line_and_col); + goto e_failed; + } + + if (++ state.ptr == end) + { sprintf (error, "%d:%d: EOF unexpected", line_and_col); + goto e_failed; + } + + switch (b = *state.ptr) + { + case '/': + flags |= flag_line_comment; + continue; + + case '*': + flags |= flag_block_comment; + continue; + + default: + sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b); + goto e_failed; + }; + } + } + + if (flags & flag_done) + { + if (!b) + break; + + switch (b) + { + whitespace: + continue; + + default: + + sprintf (error, "%d:%d: Trailing garbage: `%c`", + state.cur_line, state.cur_col, b); + + goto e_failed; + }; + } + if (flags & flag_seek_value) { switch (b) @@ -374,8 +515,8 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch if (top && top->type == json_array) flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next; - else if (!(state.settings.settings & json_relaxed_commas)) - { sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off); + else + { sprintf (error, "%d:%d: Unexpected ]", line_and_col); goto e_failed; } @@ -390,7 +531,10 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch continue; } else - { sprintf (error, "%d:%d: Expected , before %c", cur_line, e_off, b); + { + sprintf (error, "%d:%d: Expected , before %c", + state.cur_line, state.cur_col, b); + goto e_failed; } } @@ -402,7 +546,10 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch continue; } else - { sprintf (error, "%d:%d: Expected : before %c", cur_line, e_off, b); + { + sprintf (error, "%d:%d: Expected : before %c", + state.cur_line, state.cur_col, b); + goto e_failed; } } @@ -440,8 +587,11 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch case 't': - if (*(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e') + if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' || + *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e') + { goto e_unknown_value; + } if (!new_value (&state, &top, &root, &alloc, json_boolean)) goto e_alloc_failure; @@ -453,8 +603,12 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch case 'f': - if (*(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e') + if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' || + *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' || + *(++ state.ptr) != 'e') + { goto e_unknown_value; + } if (!new_value (&state, &top, &root, &alloc, json_boolean)) goto e_alloc_failure; @@ -464,8 +618,11 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch case 'n': - if (*(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l') + if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' || + *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l') + { goto e_unknown_value; + } if (!new_value (&state, &top, &root, &alloc, json_null)) goto e_alloc_failure; @@ -485,7 +642,13 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch while (isdigit (b) || b == '+' || b == '-' || b == 'e' || b == 'E' || b == '.') { - b = *++ i; + if ( (++ state.ptr) == end) + { + b = 0; + break; + } + + b = *state.ptr; } flags |= flag_next | flag_reproc; @@ -510,7 +673,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch continue; } else - { sprintf (error, "%d:%d: Unexpected %c when seeking value", cur_line, e_off, b); + { sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b); goto e_failed; } }; @@ -529,9 +692,8 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch case '"': - if (flags & flag_need_comma && !(state.settings.settings & json_relaxed_commas)) - { - sprintf (error, "%d:%d: Expected , before \"", cur_line, e_off); + if (flags & flag_need_comma) + { sprintf (error, "%d:%d: Expected , before \"", line_and_col); goto e_failed; } @@ -555,10 +717,8 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch break; } - /* fall through */ default: - - sprintf (error, "%d:%d: Unexpected `%c` in object", cur_line, e_off, b); + sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b); goto e_failed; }; @@ -576,7 +736,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch if (! (flags & flag_num_e)) { if (flags & flag_num_zero) - { sprintf (error, "%d:%d: Unexpected `0` before `%c`", cur_line, e_off, b); + { sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b); goto e_failed; } @@ -613,7 +773,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch else if (b == '.' && top->type == json_integer) { if (!num_digits) - { sprintf (error, "%d:%d: Expected digit before `.`", cur_line, e_off); + { sprintf (error, "%d:%d: Expected digit before `.`", line_and_col); goto e_failed; } @@ -629,11 +789,11 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch if (top->type == json_double) { if (!num_digits) - { sprintf (error, "%d:%d: Expected digit after `.`", cur_line, e_off); + { sprintf (error, "%d:%d: Expected digit after `.`", line_and_col); goto e_failed; } - top->u.dbl += ((double) num_fraction) / (pow ( (double) 10.0, (double) num_digits)); + top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits)); } if (b == 'e' || b == 'E') @@ -655,11 +815,12 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch else { if (!num_digits) - { sprintf (error, "%d:%d: Expected digit after `e`", cur_line, e_off); + { sprintf (error, "%d:%d: Expected digit after `e`", line_and_col); goto e_failed; } - top->u.dbl *= pow (10, (double) (flags & flag_num_e_negative ? - num_e : num_e)); + top->u.dbl *= pow (10.0, (double) + (flags & flag_num_e_negative ? - num_e : num_e)); } if (flags & flag_num_negative) @@ -681,7 +842,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch if (flags & flag_reproc) { flags &= ~ flag_reproc; - -- i; + -- state.ptr; } if (flags & flag_next) @@ -740,7 +901,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch e_unknown_value: - sprintf (error, "%d:%d: Unknown value", cur_line, e_off); + sprintf (error, "%d:%d: Unknown value", line_and_col); goto e_failed; e_alloc_failure: @@ -750,7 +911,7 @@ e_alloc_failure: e_overflow: - sprintf (error, "%d:%d: Too long (caught overflow)", cur_line, e_off); + sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col); goto e_failed; e_failed: @@ -769,25 +930,23 @@ e_failed: while (alloc) { top = alloc->_reserved.next_alloc; - free (alloc); + state.settings.mem_free (alloc, state.settings.user_data); alloc = top; } if (!state.first_pass) - json_value_free (root); + json_value_free_ex (&state.settings, root); return 0; } -json_value * json_parse (const json_char * json) +json_value * json_parse (const json_char * json, size_t length) { - json_settings settings; - memset (&settings, 0, sizeof (json_settings)); - - return json_parse_ex (&settings, json, 0); + json_settings settings = { 0 }; + return json_parse_ex (&settings, json, length, 0); } -void json_value_free (json_value * value) +void json_value_free_ex (json_settings * settings, json_value * value) { json_value * cur_value; @@ -804,7 +963,7 @@ void json_value_free (json_value * value) if (!value->u.array.length) { - free (value->u.array.values); + settings->mem_free (value->u.array.values, settings->user_data); break; } @@ -815,7 +974,7 @@ void json_value_free (json_value * value) if (!value->u.object.length) { - free (value->u.object.values); + settings->mem_free (value->u.object.values, settings->user_data); break; } @@ -824,7 +983,7 @@ void json_value_free (json_value * value) case json_string: - free (value->u.string.ptr); + settings->mem_free (value->u.string.ptr, settings->user_data); break; default: @@ -833,6 +992,14 @@ void json_value_free (json_value * value) cur_value = value; value = value->parent; - free (cur_value); + settings->mem_free (cur_value, settings->user_data); } } + +void json_value_free (json_value * value) +{ + json_settings settings = { 0 }; + settings.mem_free = default_free; + json_value_free_ex (&settings, value); +} + diff --git a/modules/misc/webservices/json.h b/modules/misc/webservices/json.h index a4da78ade3..38d3abde5d 100644 --- a/modules/misc/webservices/json.h +++ b/modules/misc/webservices/json.h @@ -1,7 +1,6 @@ - -/* vim: set et ts=3 sw=3 ft=c: +/* vim: set et ts=3 sw=3 sts=3 ft=c: * - * Copyright (C) 2012 James McLaughlin et al. All rights reserved. + * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. * https://github.com/udp/json-parser * * Redistribution and use in source and binary forms, with or without @@ -36,10 +35,16 @@ #endif #ifndef json_int_t -#include -#define json_int_t int64_t + #ifndef _MSC_VER + #include + #define json_int_t int64_t + #else + #define json_int_t __int64 + #endif #endif +#include + #ifdef __cplusplus #include @@ -54,9 +59,19 @@ typedef struct unsigned long max_memory; int settings; + /* Custom allocator support (leave null to use malloc/free) + */ + + void * (* mem_alloc) (size_t, int zero, void * user_data); + void (* mem_free) (void *, void * user_data); + + void * user_data; /* will be passed to mem_alloc and mem_free */ + + size_t value_extra; /* how much extra space to allocate for values? */ + } json_settings; -#define json_relaxed_commas 1 +#define json_enable_comments 0x01 typedef enum { @@ -99,10 +114,21 @@ typedef struct _json_value struct { json_char * name; + unsigned int name_length; + struct _json_value * value; } * values; + #if defined(__cplusplus) && __cplusplus >= 201103L + decltype(values) begin () const + { return values; + } + decltype(values) end () const + { return values + length; + } + #endif + } object; struct @@ -110,6 +136,15 @@ typedef struct _json_value unsigned int length; struct _json_value ** values; + #if defined(__cplusplus) && __cplusplus >= 201103L + decltype(values) begin () const + { return values; + } + decltype(values) end () const + { return values + length; + } + #endif + } array; } u; @@ -121,6 +156,14 @@ typedef struct _json_value } _reserved; + #ifdef JSON_TRACK_SOURCE + + /* Location of the value in the source JSON + */ + unsigned int line, col; + + #endif + /* Some C++ operator sugar */ @@ -209,15 +252,25 @@ typedef struct _json_value } json_value; -json_value * json_parse - (const json_char * json); +json_value * json_parse (const json_char * json, + size_t length); -json_value * json_parse_ex - (json_settings * settings, const json_char * json, char * error); +#define json_error_max 128 +json_value * json_parse_ex (json_settings * settings, + const json_char * json, + size_t length, + char * error); void json_value_free (json_value *); +/* Not usually necessary, unless you used a custom mem_alloc and now want to + * use a custom mem_free. + */ +void json_value_free_ex (json_settings * settings, + json_value *); + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/modules/misc/webservices/json_helper.h b/modules/misc/webservices/json_helper.h index 05f2a92d64..00c2e885e0 100644 --- a/modules/misc/webservices/json_helper.h +++ b/modules/misc/webservices/json_helper.h @@ -59,7 +59,7 @@ json_value * json_parse_document(vlc_object_t *p_obj, const char *psz_buffer, si json_settings settings; char psz_error[128]; memset (&settings, 0, sizeof (json_settings)); - json_value *root = json_parse_ex(&settings, psz_buffer, psz_error); + json_value *root = json_parse_ex(&settings, psz_buffer, i_buffer, psz_error); if (root == NULL) { msg_Warn(p_obj, "Can't parse json data: %s", psz_error); diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp b/modules/stream_out/chromecast/chromecast_ctrl.cpp index 3a1a32552b..e085d4fe50 100644 --- a/modules/stream_out/chromecast/chromecast_ctrl.cpp +++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp @@ -673,7 +673,7 @@ void intf_sys_t::processAuthMessage( const castchannel::CastMessage& msg ) void intf_sys_t::processHeartBeatMessage( const castchannel::CastMessage& msg ) { - json_value *p_data = json_parse(msg.payload_utf8().c_str()); + json_value *p_data = json_parse(msg.payload_utf8().c_str(), msg.payload_utf8().length()); std::string type((*p_data)["type"]); if (type == "PING") @@ -696,7 +696,7 @@ void intf_sys_t::processHeartBeatMessage( const castchannel::CastMessage& msg ) bool intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg ) { - json_value *p_data = json_parse(msg.payload_utf8().c_str()); + json_value *p_data = json_parse(msg.payload_utf8().c_str(), msg.payload_utf8().length()); std::string type((*p_data)["type"]); bool ret = true; @@ -800,7 +800,7 @@ bool intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg ) void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg ) { - json_value *p_data = json_parse(msg.payload_utf8().c_str()); + json_value *p_data = json_parse(msg.payload_utf8().c_str(), msg.payload_utf8().length()); std::string type((*p_data)["type"]); int64_t requestId = (json_int_t) (*p_data)["requestId"]; @@ -947,7 +947,7 @@ void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg ) void intf_sys_t::processConnectionMessage( const castchannel::CastMessage& msg ) { - json_value *p_data = json_parse(msg.payload_utf8().c_str()); + json_value *p_data = json_parse(msg.payload_utf8().c_str(), msg.payload_utf8().length()); std::string type((*p_data)["type"]); json_value_free(p_data);