Merge pull request #200 from rmallins/cJSON_ParseWithOpts_fix_ErrorPtr_behaviour

Fix error pointer behaviour of cJSON_ParseWithOpts()
This commit is contained in:
Max Bruckner 2017-09-08 12:05:19 +02:00 committed by GitHub
commit e4980b65b9
4 changed files with 38 additions and 10 deletions

View File

@ -1006,10 +1006,8 @@ fail:
{ {
*return_parse_end = (const char*)local_error.json + local_error.position; *return_parse_end = (const char*)local_error.json + local_error.position;
} }
else
{ global_error = local_error;
global_error = local_error;
}
} }
return NULL; return NULL;

View File

@ -139,7 +139,7 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */ /* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
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);
/* Render a cJSON entity to text for transfer/storage. */ /* Render a cJSON entity to text for transfer/storage. */

View File

@ -142,7 +142,7 @@ static void file_test6_should_not_be_parsed(void)
tree = cJSON_Parse(test6); tree = cJSON_Parse(test6);
TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse what is not JSON."); TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse what is not JSON.");
TEST_ASSERT_EQUAL_STRING_MESSAGE(test6, cJSON_GetErrorPtr(), "Error pointer is incorrect."); TEST_ASSERT_EQUAL_PTR_MESSAGE(test6, cJSON_GetErrorPtr(), "Error pointer is incorrect.");
if (test6 != NULL) if (test6 != NULL)
{ {
@ -179,6 +179,22 @@ static void file_test11_should_be_parsed_and_printed(void)
do_test("test11"); do_test("test11");
} }
static void test12_should_not_be_parsed(void)
{
const char *test12 = "{ \"name\": ";
cJSON *tree = NULL;
tree = cJSON_Parse(test12);
TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse incomplete JSON.");
TEST_ASSERT_EQUAL_PTR_MESSAGE(test12 + strlen(test12), cJSON_GetErrorPtr(), "Error pointer is incorrect.");
if (tree != NULL)
{
cJSON_Delete(tree);
}
}
int main(void) int main(void)
{ {
UNITY_BEGIN(); UNITY_BEGIN();
@ -193,5 +209,6 @@ int main(void)
RUN_TEST(file_test9_should_be_parsed_and_printed); RUN_TEST(file_test9_should_be_parsed_and_printed);
RUN_TEST(file_test10_should_be_parsed_and_printed); RUN_TEST(file_test10_should_be_parsed_and_printed);
RUN_TEST(file_test11_should_be_parsed_and_printed); RUN_TEST(file_test11_should_be_parsed_and_printed);
RUN_TEST(test12_should_not_be_parsed);
return UNITY_END(); return UNITY_END();
} }

View File

@ -40,11 +40,23 @@ static void parse_with_opts_should_handle_empty_strings(void)
{ {
const char empty_string[] = ""; const char empty_string[] = "";
const char *error_pointer = NULL; const char *error_pointer = NULL;
TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, NULL, false)); TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, NULL, false));
error_pointer = cJSON_GetErrorPtr(); TEST_ASSERT_EQUAL_PTR(empty_string, cJSON_GetErrorPtr());
TEST_ASSERT_EQUAL_INT(0, error_pointer - empty_string);
TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, &error_pointer, false)); TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, &error_pointer, false));
TEST_ASSERT_EQUAL_INT(0, error_pointer - empty_string); TEST_ASSERT_EQUAL_PTR(empty_string, error_pointer);
TEST_ASSERT_EQUAL_PTR(empty_string, cJSON_GetErrorPtr());
}
static void parse_with_opts_should_handle_incomplete_json(void)
{
const char json[] = "{ \"name\": ";
const char *parse_end = NULL;
TEST_ASSERT_NULL(cJSON_ParseWithOpts(json, &parse_end, false));
TEST_ASSERT_EQUAL_PTR(json + strlen(json), parse_end);
TEST_ASSERT_EQUAL_PTR(json + strlen(json), cJSON_GetErrorPtr());
} }
static void parse_with_opts_should_require_null_if_requested(void) static void parse_with_opts_should_require_null_if_requested(void)
@ -65,7 +77,7 @@ static void parse_with_opts_should_return_parse_end(void)
cJSON *item = cJSON_ParseWithOpts(json, &parse_end, false); cJSON *item = cJSON_ParseWithOpts(json, &parse_end, false);
TEST_ASSERT_NOT_NULL(item); TEST_ASSERT_NOT_NULL(item);
TEST_ASSERT_EQUAL_INT(2, parse_end - json); TEST_ASSERT_EQUAL_PTR(json + 2, parse_end);
cJSON_Delete(item); cJSON_Delete(item);
} }
@ -75,6 +87,7 @@ int main(void)
RUN_TEST(parse_with_opts_should_handle_null); RUN_TEST(parse_with_opts_should_handle_null);
RUN_TEST(parse_with_opts_should_handle_empty_strings); RUN_TEST(parse_with_opts_should_handle_empty_strings);
RUN_TEST(parse_with_opts_should_handle_incomplete_json);
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);