cJSON_Parse{,WithOpts}: Skip UTF-8 (Byte Order Marks)

This commit is contained in:
Max Bruckner 2017-07-03 21:43:14 +02:00
parent b26e71f960
commit 5baa77f86c
3 changed files with 60 additions and 2 deletions

19
cJSON.c
View File

@ -958,6 +958,22 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
return buffer; return buffer;
} }
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
{
if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
{
return NULL;
}
if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
{
buffer->offset += 3;
}
return buffer;
}
/* Parse an object - create a new root, and populate. */ /* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
{ {
@ -984,7 +1000,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
goto fail; goto fail;
} }
if (!parse_value(item, buffer_skip_whitespace(&buffer))) if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
{ {
/* parse failure. ep is set. */ /* parse failure. ep is set. */
goto fail; goto fail;
@ -1222,7 +1238,6 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf
return parse_object(item, input_buffer); return parse_object(item, input_buffer);
} }
return false; return false;
} }

View File

@ -410,6 +410,30 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
cJSON_Delete(item); cJSON_Delete(item);
} }
static void skip_utf8_bom_should_skip_bom(void)
{
const unsigned char string[] = "\xEF\xBB\xBF{}";
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
buffer.content = string;
buffer.length = sizeof(string);
buffer.hooks = global_hooks;
TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer);
TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset);
}
static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
{
const unsigned char string[] = " \xEF\xBB\xBF{}";
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
buffer.content = string;
buffer.length = sizeof(string);
buffer.hooks = global_hooks;
buffer.offset = 1;
TEST_ASSERT_NULL(skip_utf8_bom(&buffer));
}
int main(void) int main(void)
{ {
UNITY_BEGIN(); UNITY_BEGIN();
@ -425,6 +449,8 @@ int main(void)
RUN_TEST(cjson_replace_item_via_pointer_should_replace_items); RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
RUN_TEST(cjson_replace_item_in_object_should_preserve_name); RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
RUN_TEST(cjson_functions_shouldnt_crash_with_null_pointers); RUN_TEST(cjson_functions_shouldnt_crash_with_null_pointers);
RUN_TEST(skip_utf8_bom_should_skip_bom);
RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
return UNITY_END(); return UNITY_END();
} }

View File

@ -69,6 +69,22 @@ static void parse_with_opts_should_return_parse_end(void)
cJSON_Delete(item); cJSON_Delete(item);
} }
static void parse_with_opts_should_parse_utf8_bom(void)
{
cJSON *with_bom = NULL;
cJSON *without_bom = NULL;
with_bom = cJSON_ParseWithOpts("\xEF\xBB\xBF{}", NULL, true);
TEST_ASSERT_NOT_NULL(with_bom);
without_bom = cJSON_ParseWithOpts("{}", NULL, true);
TEST_ASSERT_NOT_NULL(with_bom);
TEST_ASSERT_TRUE(cJSON_Compare(with_bom, without_bom, true));
cJSON_Delete(with_bom);
cJSON_Delete(without_bom);
}
int main(void) int main(void)
{ {
UNITY_BEGIN(); UNITY_BEGIN();
@ -77,6 +93,7 @@ int main(void)
RUN_TEST(parse_with_opts_should_handle_empty_strings); RUN_TEST(parse_with_opts_should_handle_empty_strings);
RUN_TEST(parse_with_opts_should_require_null_if_requested); RUN_TEST(parse_with_opts_should_require_null_if_requested);
RUN_TEST(parse_with_opts_should_return_parse_end); RUN_TEST(parse_with_opts_should_return_parse_end);
RUN_TEST(parse_with_opts_should_parse_utf8_bom);
return UNITY_END(); return UNITY_END();
} }