# HG changeset patch # User Olaf Wintermann # Date 1729592176 -7200 # Node ID 9077724b75a0ec701c5465cef301bbe58279f009 # Parent bbf41b9c2658fde756e44f0ad73d5036735d42dd fix incomplete json object not resulting in syntax error diff -r bbf41b9c2658 -r 9077724b75a0 src/json.c --- a/src/json.c Sun Oct 20 12:30:30 2024 +0200 +++ b/src/json.c Tue Oct 22 12:16:16 2024 +0200 @@ -440,11 +440,6 @@ end_elm(p, CX_JSON_READER_ARRAY_END); break; } - case CX_JSON_TOKEN_END_OBJECT: { - p->value_ready = 0; - end_elm(p, CX_JSON_READER_OBJECT_END); - break; - } case CX_JSON_TOKEN_STRING: { p->reader_type = CX_JSON_READER_STRING; cxmutstr str = unescape_string(token.content, token.length); @@ -518,7 +513,7 @@ p->states[p->nstates] = 1; ret = json_read(p); } else if (state == 7) { - // expect ',' or '}]' + // expect ',' or '}' if (token.tokentype == CX_JSON_TOKEN_VALUE_SEPARATOR) { p->states[p->nstates] = JP_STATE_OBJ_NAME; ret = json_read(p); @@ -674,6 +669,7 @@ void cxJsonDestroy(CxJson *p) { free(p->states); free(p->readvalue_stack); + cxJsonValueFree(p->read_value); } void cxJsonFill(CxJson *p, const char *buf, size_t size) { @@ -699,6 +695,7 @@ if (p->readvalue_nelm > 0) { if (add_to_parent(p, p->readvalue_stack[p->readvalue_nelm - 1], v)) { + free(v); return -1; } } else { diff -r bbf41b9c2658 -r 9077724b75a0 tests/test_json.c --- a/tests/test_json.c Sun Oct 20 12:30:30 2024 +0200 +++ b/tests/test_json.c Tue Oct 22 12:16:16 2024 +0200 @@ -148,11 +148,48 @@ } } +CX_TEST(test_json_object_error) { + cxstring text0 = cx_str( + "{\n" + "\t\"message\":\"success\",\n" + "\t\"data\":{\n" + "\t\t\"obj\":{\n" + "\t\t\t\"array\": [1, 2, 3, ?syntaxerror? ]\n" + "\t\t\"}\n" + "\t},\n" + "\t\"timestamp\":1729348561,\n" + "}" + ); + cxstring text1 = cx_str("{ \"string\" }"); + cxstring text2 = cx_str("{ \"a\" : }"); + cxstring text3 = cx_str("{ \"a\" : \"b\" ]"); + cxstring text4 = cx_str("{ \"name\": \"value\" ]"); + + cxstring tests[] = { text0, text1, text2, text3, text4 }; + + CX_TEST_DO { + int result; + CxJson json; + CxJsonValue *obj = NULL; + + for(int i=0;i<5;i++) { + cxJsonInit(&json); + cxJsonFill(&json, tests[i].ptr, tests[i].length); + result = cxJsonNext(&json, &obj); + + CX_TEST_ASSERT(result == -1); + CX_TEST_ASSERT(obj == NULL); + cxJsonDestroy(&json); + } + } +} + CxTestSuite *cx_test_suite_json(void) { CxTestSuite *suite = cx_test_suite_new("json"); cx_test_register(suite, test_json_simple_object); cx_test_register(suite, test_json_object_incomplete_token); + cx_test_register(suite, test_json_object_error); return suite; }