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) {
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)
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++;
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);
{
test_json_parser_success(TRUE);
test_json_parser_success(FALSE);
+ test_json_parser_errors();
test_json_append_escaped();
test_json_append_escaped_data();
}