mirror of
https://github.com/DaveGamble/cJSON
synced 2025-04-25 20:57:55 +00:00
Merge e57af8df21
into 12c4bf1986
This commit is contained in:
commit
43a56d26f8
37
cJSON.c
37
cJSON.c
@ -796,24 +796,31 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
|
||||
unsigned char *output_pointer = NULL;
|
||||
unsigned char *output = NULL;
|
||||
|
||||
/* not a string */
|
||||
/* Not a string */
|
||||
if (buffer_at_offset(input_buffer)[0] != '\"')
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
{
|
||||
/* calculate approximate size of the output (overestimate) */
|
||||
/* Calculate approximate size of the output (overestimate) and validate control characters */
|
||||
size_t allocation_length = 0;
|
||||
size_t skipped_bytes = 0;
|
||||
while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
|
||||
{
|
||||
/* is escape sequence */
|
||||
/* Check for unescaped control characters (U+0000 to U+001F) */
|
||||
if (*input_end < 0x20) /* Control characters must be escaped */
|
||||
{
|
||||
input_buffer->offset = (size_t)(input_end - input_buffer->content);
|
||||
goto fail; /* Error: unescaped control character */
|
||||
}
|
||||
|
||||
/* Is escape sequence */
|
||||
if (input_end[0] == '\\')
|
||||
{
|
||||
if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
|
||||
{
|
||||
/* prevent buffer overflow when last input character is a backslash */
|
||||
/* Prevent buffer overflow when last input character is a backslash */
|
||||
goto fail;
|
||||
}
|
||||
skipped_bytes++;
|
||||
@ -823,27 +830,27 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
|
||||
}
|
||||
if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
|
||||
{
|
||||
goto fail; /* string ended unexpectedly */
|
||||
goto fail; /* String ended unexpectedly */
|
||||
}
|
||||
|
||||
/* This is at most how much we need for the output */
|
||||
allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
|
||||
allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
|
||||
output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
|
||||
if (output == NULL)
|
||||
{
|
||||
goto fail; /* allocation failure */
|
||||
goto fail; /* Allocation failure */
|
||||
}
|
||||
}
|
||||
|
||||
output_pointer = output;
|
||||
/* loop through the string literal */
|
||||
/* Loop through the string literal */
|
||||
while (input_pointer < input_end)
|
||||
{
|
||||
if (*input_pointer != '\\')
|
||||
{
|
||||
*output_pointer++ = *input_pointer++;
|
||||
}
|
||||
/* escape sequence */
|
||||
/* Escape sequence */
|
||||
else
|
||||
{
|
||||
unsigned char sequence_length = 2;
|
||||
@ -880,25 +887,25 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
|
||||
sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
|
||||
if (sequence_length == 0)
|
||||
{
|
||||
/* failed to convert UTF16-literal to UTF-8 */
|
||||
/* Failed to convert UTF16-literal to UTF-8 */
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
goto fail; /* Invalid escape sequence */
|
||||
}
|
||||
input_pointer += sequence_length;
|
||||
}
|
||||
}
|
||||
|
||||
/* zero terminate the output */
|
||||
/* Zero terminate the output */
|
||||
*output_pointer = '\0';
|
||||
|
||||
item->type = cJSON_String;
|
||||
item->valuestring = (char*)output;
|
||||
|
||||
input_buffer->offset = (size_t) (input_end - input_buffer->content);
|
||||
input_buffer->offset = (size_t)(input_end - input_buffer->content);
|
||||
input_buffer->offset++;
|
||||
|
||||
return true;
|
||||
@ -907,10 +914,9 @@ fail:
|
||||
if (output != NULL)
|
||||
{
|
||||
input_buffer->hooks.deallocate(output);
|
||||
output = NULL;
|
||||
}
|
||||
|
||||
if (input_pointer != NULL)
|
||||
if (input_pointer != NULL && (size_t)(input_pointer - input_buffer->content) < input_buffer->length)
|
||||
{
|
||||
input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
|
||||
}
|
||||
@ -918,6 +924,7 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Render the cstring provided to an escaped version that can be printed. */
|
||||
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
|
||||
{
|
||||
|
@ -33,7 +33,6 @@ static cJSON item[1];
|
||||
static void assert_is_string(cJSON *string_item)
|
||||
{
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(string_item, "Item is NULL.");
|
||||
|
||||
assert_not_in_list(string_item);
|
||||
assert_has_no_child(string_item);
|
||||
assert_has_type(string_item, cJSON_String);
|
||||
@ -68,8 +67,6 @@ static void assert_not_parse_string(const char * const string)
|
||||
assert_is_invalid(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void parse_string_should_parse_strings(void)
|
||||
{
|
||||
assert_parse_string("\"\"", "");
|
||||
@ -77,10 +74,8 @@ static void parse_string_should_parse_strings(void)
|
||||
"\" !\\\"#$%&'()*+,-./\\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_'abcdefghijklmnopqrstuvwxyz{|}~\"",
|
||||
" !\"#$%&'()*+,-.//0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~");
|
||||
assert_parse_string(
|
||||
"\"\\\"\\\\\\/\\b\\f\\n\\r\\t\\u20AC\\u732b\"",
|
||||
"\"\\/\b\f\n\r\t€猫");
|
||||
reset(item);
|
||||
assert_parse_string("\"\b\f\n\r\t\"", "\b\f\n\r\t");
|
||||
"\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"",
|
||||
"\"\\/\b\f\n\r\t");
|
||||
reset(item);
|
||||
}
|
||||
|
||||
@ -119,9 +114,22 @@ static void parse_string_should_parse_bug_94(void)
|
||||
reset(item);
|
||||
}
|
||||
|
||||
static void parse_string_should_not_parse_unescaped_control_chars(void)
|
||||
{
|
||||
/* Test unescaped control characters (U+0000 to U+001F) */
|
||||
assert_not_parse_string("\"\x0a\""); /* Newline */
|
||||
reset(item);
|
||||
assert_not_parse_string("\"\x00\""); /* Null character */
|
||||
reset(item);
|
||||
assert_not_parse_string("\"1\x0a2\""); /* Newline in middle, matches #766 test case */
|
||||
reset(item);
|
||||
assert_not_parse_string("\"\x1f\""); /* Unit separator (highest control char) */
|
||||
reset(item);
|
||||
}
|
||||
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item and error pointer */
|
||||
/* Initialize cJSON item and error pointer */
|
||||
memset(item, 0, sizeof(cJSON));
|
||||
|
||||
UNITY_BEGIN();
|
||||
@ -131,5 +139,6 @@ int CJSON_CDECL main(void)
|
||||
RUN_TEST(parse_string_should_not_parse_invalid_backslash);
|
||||
RUN_TEST(parse_string_should_parse_bug_94);
|
||||
RUN_TEST(parse_string_should_not_overflow_with_closing_backslash);
|
||||
RUN_TEST(parse_string_should_not_parse_unescaped_control_chars); /* New test */
|
||||
return UNITY_END();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user