Skip to content

Commit

Permalink
cJSON_Parse{,WithOpts}: Skip UTF-8 (Byte Order Marks)
Browse files Browse the repository at this point in the history
  • Loading branch information
FSMaxB committed Jul 3, 2017
1 parent b26e71f commit 5baa77f
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
19 changes: 17 additions & 2 deletions cJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,22 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const 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. */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
{
Expand All @@ -984,7 +1000,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
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. */
goto fail;
Expand Down Expand Up @@ -1222,7 +1238,6 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf
return parse_object(item, input_buffer);
}


return false;
}

Expand Down
26 changes: 26 additions & 0 deletions tests/misc_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,30 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
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)
{
UNITY_BEGIN();
Expand All @@ -425,6 +449,8 @@ int main(void)
RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
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();
}
17 changes: 17 additions & 0 deletions tests/parse_with_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ static void parse_with_opts_should_return_parse_end(void)
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)
{
UNITY_BEGIN();
Expand All @@ -77,6 +93,7 @@ int main(void)
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_return_parse_end);
RUN_TEST(parse_with_opts_should_parse_utf8_bom);

return UNITY_END();
}

0 comments on commit 5baa77f

Please sign in to comment.