]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Code cleanup to json-parser - assume less that the root is an object
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 1 Feb 2016 15:00:11 +0000 (17:00 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 1 Feb 2016 15:45:48 +0000 (17:45 +0200)
src/lib/json-parser.c
src/lib/test-json-parser.c

index cf0eeaa119fa1060ac1dd15c06784a1a4855af9f..45f888dfef222f347f101c004ae10771ac8fda9c 100644 (file)
@@ -335,21 +335,16 @@ static int json_parse_denest(struct json_parser *parser)
        json_parser_update_input_pos(parser);
 
        nested_states = array_get(&parser->nesting, &count);
-       if (count == 0) {
+       i_assert(count > 0);
+       if (count == 1) {
                /* closing root */
                parser->state = JSON_STATE_DONE;
                return 0;
        }
 
        /* closing a nested object */
-       if (count == 1) {
-               /* we're back to root */
-               parser->state = JSON_STATE_OBJECT_NEXT;
-       } else {
-               /* back to previous nested object */
-               parser->state = nested_states[count-2] == JSON_STATE_OBJECT_OPEN ?
-                       JSON_STATE_OBJECT_NEXT : JSON_STATE_ARRAY_NEXT;
-       }
+       parser->state = nested_states[count-2] == JSON_STATE_OBJECT_OPEN ?
+               JSON_STATE_OBJECT_NEXT : JSON_STATE_ARRAY_NEXT;
        array_delete(&parser->nesting, count-1, 1);
 
        if (parser->nested_skip_count > 0) {
@@ -377,6 +372,14 @@ json_parse_close_array(struct json_parser *parser, enum json_type *type_r)
        return 1;
 }
 
+static void json_parser_object_open(struct json_parser *parser)
+{
+       parser->data++;
+       parser->state = JSON_STATE_OBJECT_OPEN;
+       array_append(&parser->nesting, &parser->state, 1);
+       json_parser_update_input_pos(parser);
+}
+
 static int
 json_try_parse_next(struct json_parser *parser, enum json_type *type_r,
                    const char **value_r)
@@ -393,17 +396,12 @@ json_try_parse_next(struct json_parser *parser, enum json_type *type_r,
                        parser->error = "Object doesn't begin with '{'";
                        return -1;
                }
-               parser->data++;
-               parser->state = JSON_STATE_OBJECT_OPEN;
-               json_parser_update_input_pos(parser);
+               json_parser_object_open(parser);
                return 0;
        case JSON_STATE_OBJECT_VALUE:
        case JSON_STATE_ARRAY_VALUE:
                if (*parser->data == '{') {
-                       parser->data++;
-                       parser->state = JSON_STATE_OBJECT_OPEN;
-                       array_append(&parser->nesting, &parser->state, 1);
-                       json_parser_update_input_pos(parser);
+                       json_parser_object_open(parser);
 
                        if (parser->skipping) {
                                parser->nested_skip_count++;
index d2b78ec377aaa4200f568f4f85f67cc34b861e27..da24f0fcbb40cac476d6bb90109cdf6dfc762424 100644 (file)
@@ -163,6 +163,46 @@ static void test_json_parser_success(bool full_size)
        test_end();
 }
 
+static int test_json_parse_input(const char *test_input)
+{
+       struct json_parser *parser;
+       struct istream *input;
+       enum json_type type;
+       const char *value, *error;
+       int ret = 0;
+
+       input = test_istream_create_data(test_input, strlen(test_input));
+       parser = json_parser_init(input);
+       while (json_parse_next(parser, &type, &value) > 0)
+               ret++;
+       if (json_parser_deinit(&parser, &error) < 0)
+               ret = -1;
+       i_stream_unref(&input);
+       return ret;
+}
+
+static void test_json_parser_errors(void)
+{
+       static const char *test_inputs[] = {
+               "{",
+               "{:}",
+               "{\"foo\":}",
+               "{\"foo\" []}",
+               "{\"foo\": [1}",
+               "{\"foo\": [1,]}",
+               "{\"foo\": [1,]}",
+               "{\"foo\": 1,}",
+               "{\"foo\": 1.}}",
+               "{\"foo\": 1},{}"
+       };
+       unsigned int i;
+
+       test_begin("json parser error handling");
+       for (i = 0; i < N_ELEMENTS(test_inputs); i++)
+               test_assert_idx(test_json_parse_input(test_inputs[i]) < 0, i);
+       test_end();
+}
+
 static void test_json_append_escaped(void)
 {
        string_t *str = t_str_new(32);
@@ -189,6 +229,7 @@ void test_json_parser(void)
 {
        test_json_parser_success(TRUE);
        test_json_parser_success(FALSE);
+       test_json_parser_errors();
        test_json_append_escaped();
        test_json_append_escaped_data();
 }