dovecot-2.2: JSON parser fixes
dovecot at dovecot.org
dovecot at dovecot.org
Thu Nov 29 07:31:26 EET 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/9a31c44c1184
changeset: 15436:9a31c44c1184
user: Timo Sirainen <tss at iki.fi>
date: Thu Nov 29 07:30:23 2012 +0200
description:
JSON parser fixes
diffstat:
src/lib/json-parser.c | 89 +++++++++++++++++++++++++++------------------
src/lib/test-json-parser.c | 9 +++-
2 files changed, 59 insertions(+), 39 deletions(-)
diffs (238 lines):
diff -r 86572582647e -r 9a31c44c1184 src/lib/json-parser.c
--- a/src/lib/json-parser.c Thu Nov 29 06:26:29 2012 +0200
+++ b/src/lib/json-parser.c Thu Nov 29 07:30:23 2012 +0200
@@ -148,11 +148,11 @@
parser->data++;
str_truncate(parser->value, 0);
- for (; parser->data != parser->end; parser->data++) {
+ for (; parser->data != parser->end; parser->data++) {
if (*parser->data == '"') {
parser->data++;
*value_r = str_c(parser->value);
- return 0;
+ return 1;
}
if (*parser->data != '\\')
str_append_c(parser->value, *parser->data);
@@ -179,8 +179,12 @@
str_append_c(parser->value, '\t');
break;
case 'u':
- if (parser->end - parser->data < 4)
- return -1;
+ parser->data++;
+ if (parser->end - parser->data < 4) {
+ /* wait for more data */
+ parser->data = parser->end;
+ return 0;
+ }
uni_ucs4_to_utf8_c(hex2dec(parser->data, 4),
parser->value);
parser->data += 3;
@@ -190,64 +194,69 @@
}
}
}
- return -1;
+ return 0;
}
static int
json_parse_digits(struct json_parser *parser)
{
- if (parser->data == parser->end ||
- *parser->data < '0' || *parser->data > '9')
+ if (parser->data == parser->end)
+ return 0;
+ if (*parser->data < '0' || *parser->data > '9')
return -1;
while (parser->data != parser->end &&
*parser->data >= '0' && *parser->data <= '9')
str_append_c(parser->value, *parser->data++);
- return 0;
+ return 1;
}
static int json_parse_int(struct json_parser *parser)
{
+ int ret;
+
if (*parser->data == '-') {
str_append_c(parser->value, *parser->data++);
if (parser->data == parser->end)
- return -1;
+ return 0;
}
if (*parser->data == '0')
str_append_c(parser->value, *parser->data++);
else {
- if (json_parse_digits(parser) < 0)
- return -1;
+ if ((ret = json_parse_digits(parser)) <= 0)
+ return ret;
}
- return 0;
+ return 1;
}
static int json_parse_number(struct json_parser *parser, const char **value_r)
{
+ int ret;
+
str_truncate(parser->value, 0);
- if (json_parse_int(parser) < 0)
- return -1;
+ if ((ret = json_parse_int(parser)) <= 0)
+ return ret;
if (parser->data != parser->end && *parser->data == '.') {
/* frac */
str_append_c(parser->value, *parser->data++);
- if (json_parse_digits(parser) < 0)
- return -1;
+ if ((ret = json_parse_digits(parser)) <= 0)
+ return ret;
}
if (parser->data != parser->end &&
(*parser->data == 'e' || *parser->data == 'E')) {
/* exp */
str_append_c(parser->value, *parser->data++);
if (parser->data == parser->end)
- return -1;
+ return 0;
if (*parser->data == '+' || *parser->data == '-')
str_append_c(parser->value, *parser->data++);
- if (json_parse_digits(parser) < 0)
- return -1;
+ if ((ret = json_parse_digits(parser)) <= 0)
+ return ret;
}
if (parser->data == parser->end && !parser->input->eof)
- return -1;
+ return 0;
*value_r = str_c(parser->value);
- return 0;
+ return 1;
}
static int json_parse_atom(struct json_parser *parser, const char *atom)
@@ -256,16 +265,17 @@
avail = parser->end - parser->data;
if (avail < len) {
- if (memcmp(parser->data, atom, avail) == 0) {
- /* everything matches so far, but we need more data */
- parser->data += avail;
- }
- return -1;
+ if (memcmp(parser->data, atom, avail) != 0)
+ return -1;
+
+ /* everything matches so far, but we need more data */
+ parser->data += avail;
+ return 0;
}
if (memcmp(parser->data, atom, len) != 0)
return -1;
parser->data += len;
- return 0;
+ return 1;
}
static int
@@ -290,6 +300,8 @@
json_try_parse_next(struct json_parser *parser, enum json_type *type_r,
const char **value_r)
{
+ int ret;
+
if (!json_parse_whitespace(parser))
return -1;
@@ -304,11 +316,7 @@
json_parser_update_input_pos(parser);
return json_try_parse_next(parser, type_r, value_r);
case JSON_STATE_OBJECT_VALUE:
- if (json_parse_string(parser, value_r) == 0)
- *type_r = JSON_TYPE_STRING;
- else if (json_parse_number(parser, value_r) == 0)
- *type_r = JSON_TYPE_NUMBER;
- else if (*parser->data == '[') {
+ if (*parser->data == '[') {
parser->error = "Arrays not supported";
return -1;
} else if (*parser->data == '{') {
@@ -318,19 +326,28 @@
json_parser_update_input_pos(parser);
*type_r = JSON_TYPE_OBJECT;
return 0;
- } else if (json_parse_atom(parser, "true") == 0) {
+ }
+ if ((ret = json_parse_string(parser, value_r)) >= 0) {
+ *type_r = JSON_TYPE_STRING;
+ } else if ((ret = json_parse_number(parser, value_r)) >= 0) {
+ *type_r = JSON_TYPE_NUMBER;
+ } else if ((ret = json_parse_atom(parser, "true")) >= 0) {
*type_r = JSON_TYPE_TRUE;
*value_r = "true";
- } else if (json_parse_atom(parser, "false") == 0) {
+ } else if ((ret = json_parse_atom(parser, "false")) >= 0) {
*type_r = JSON_TYPE_FALSE;
*value_r = "false";
- } else if (json_parse_atom(parser, "null") == 0) {
+ } else if ((ret = json_parse_atom(parser, "null")) >= 0) {
*type_r = JSON_TYPE_NULL;
*value_r = NULL;
} else {
parser->error = "Invalid data as value";
return -1;
}
+ if (ret == 0) {
+ i_assert(parser->data == parser->end);
+ return -1;
+ }
parser->state = parser->state == JSON_STATE_ROOT ?
JSON_STATE_DONE :
JSON_STATE_OBJECT_VALUE_NEXT;
@@ -341,7 +358,7 @@
parser->state = JSON_STATE_OBJECT_KEY;
/* fall through */
case JSON_STATE_OBJECT_KEY:
- if (json_parse_string(parser, value_r) < 0) {
+ if (json_parse_string(parser, value_r) <= 0) {
parser->error = "Expected string as object key";
return -1;
}
diff -r 86572582647e -r 9a31c44c1184 src/lib/test-json-parser.c
--- a/src/lib/test-json-parser.c Thu Nov 29 06:26:29 2012 +0200
+++ b/src/lib/test-json-parser.c Thu Nov 29 07:30:23 2012 +0200
@@ -20,7 +20,8 @@
" \"sub2\":-12.456,\n"
" \"sub3\":12.456e9,\n"
" \"sub4\":0.456e-789"
- "}"
+ "},"
+ "\"key9\": \"\\\\\\\"\\b\\f\\n\\r\\t\\u0001\uffff\""
"}\n";
static struct {
@@ -53,7 +54,9 @@
{ JSON_TYPE_NUMBER, "12.456e9" },
{ JSON_TYPE_OBJECT_KEY, "sub4" },
{ JSON_TYPE_NUMBER, "0.456e-789" },
- { JSON_TYPE_OBJECT_END, NULL }
+ { JSON_TYPE_OBJECT_END, NULL },
+ { JSON_TYPE_OBJECT_KEY, "key9" },
+ { JSON_TYPE_STRING, "\\\"\b\f\n\r\t\001\xef\xbf\xbf" }
};
static void test_json_parser_success(bool full_size)
@@ -93,6 +96,6 @@
void test_json_parser(void)
{
+ test_json_parser_success(FALSE);
test_json_parser_success(TRUE);
- test_json_parser_success(FALSE);
}
More information about the dovecot-cvs
mailing list