Wed, 10 Dec 2025 14:05:20 +0100
fix memory leak in the json parser and add more tests for cxJsonFromString - relates to #777
| src/json.c | file | annotate | diff | comparison | revisions | |
| tests/test_json.c | file | annotate | diff | comparison | revisions |
--- a/src/json.c Wed Dec 10 13:12:27 2025 +0100 +++ b/src/json.c Wed Dec 10 14:05:20 2025 +0100 @@ -557,6 +557,7 @@ } cxJsonValueFree(json->parsed); json->parsed = NULL; + token_destroy(&json->uncompleted); cx_strfree_a(json->allocator, &json->uncompleted_member_name); }
--- a/tests/test_json.c Wed Dec 10 13:12:27 2025 +0100 +++ b/tests/test_json.c Wed Dec 10 14:05:20 2025 +0100 @@ -199,6 +199,43 @@ } } +CX_TEST(test_json_from_string_errors) { + CX_TEST_DO { + CxJsonValue *obj = NULL; + CX_TEST_ASSERT(cxJsonFromString(NULL, "", &obj) == CX_JSON_NO_DATA); + CX_TEST_ASSERT(cxJsonFromString(NULL, cx_str(NULL), &obj) == CX_JSON_NO_DATA); + CX_TEST_ASSERT(cxJsonFromString(NULL, "\"incomplete", &obj) == CX_JSON_INCOMPLETE_DATA); + CX_TEST_ASSERT(cxJsonFromString(NULL, "{ \"incomplete\": ", &obj) == CX_JSON_INCOMPLETE_DATA); + CX_TEST_ASSERT(cxJsonFromString(NULL, "{\"number\": 47110815!}", &obj) == CX_JSON_FORMAT_ERROR_NUMBER); + CX_TEST_ASSERT(cxJsonFromString(NULL, "[ \"unexpected token\" : true ]", &obj) == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); + CX_TEST_ASSERT(cxJsonFromString(NULL, "} [", &obj) == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); + CX_TEST_ASSERT(obj && obj->type == CX_JSON_NOTHING); + } +} + +CX_TEST(test_json_from_string_multiple_values) { + CxJsonStatus status; + CxJsonValue *obj = NULL; + CX_TEST_DO { + status = cxJsonFromString(NULL, "{ \"obj1\": \"hello\" }\n\"value2\"\n", &obj); + + // TODO: what is the expected behavior here? Is this an error or do we ignore the second value? + CX_TEST_ASSERT(status == CX_JSON_NO_ERROR); + CX_TEST_ASSERT(cxJsonIsObject(obj)); + // CX_TEST_ASSERT(status == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); + + cxJsonValueFree(obj); + + // TODO: this really should be an error in theory + status = cxJsonFromString(NULL, "\"value\" \n ] syntax error [", &obj); + CX_TEST_ASSERT(status == CX_JSON_NO_ERROR); + CX_TEST_ASSERT(cxJsonIsString(obj)); + // CX_TEST_ASSERT(status == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); + + cxJsonValueFree(obj); + } +} + CX_TEST(test_json_escaped_strings) { cxstring text = cx_str( "{\n" @@ -449,6 +486,13 @@ // now there is everything read result = cxJsonNext(&json, &obj); CX_TEST_ASSERT(result == CX_JSON_NO_DATA); + + // Test 2: abort after incomplete token + cxJsonReset(&json); + + cxJsonFill(&json, "\"incomplete token"); + result = cxJsonNext(&json, &obj); + CX_TEST_ASSERT(result == CX_JSON_INCOMPLETE_DATA); cxJsonDestroy(&json); } @@ -1519,6 +1563,8 @@ cx_test_register(suite, test_json_simple_object); cx_test_register(suite, test_json_large_object); cx_test_register(suite, test_json_from_string); + cx_test_register(suite, test_json_from_string_errors); + cx_test_register(suite, test_json_from_string_multiple_values); cx_test_register(suite, test_json_escaped_strings); cx_test_register(suite, test_json_escaped_unicode_strings); cx_test_register(suite, test_json_escaped_unicode_malformed);