fix incomplete json object not resulting in syntax error

Tue, 22 Oct 2024 12:16:16 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 22 Oct 2024 12:16:16 +0200
changeset 941
9077724b75a0
parent 940
bbf41b9c2658
child 942
8a5bbdb7f87f

fix incomplete json object not resulting in syntax error

src/json.c file | annotate | diff | comparison | revisions
tests/test_json.c file | annotate | diff | comparison | revisions
--- 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 {
--- 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;
 }

mercurial