Skip to content

Commit

Permalink
Fix #2345 - json parsing of arrays of objects
Browse files Browse the repository at this point in the history
  • Loading branch information
cpq committed Aug 16, 2023
1 parent 66e022c commit 58886a9
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 10 deletions.
14 changes: 9 additions & 5 deletions mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -2596,11 +2596,11 @@ int mg_json_get(struct mg_str json, const char *path, int *toklen) {
if (i + 1 + n >= len) return MG_JSON_NOT_FOUND;
if (depth < ed) return MG_JSON_NOT_FOUND;
if (depth == ed && path[pos - 1] != '.') return MG_JSON_NOT_FOUND;
// printf("K %s [%.*s] [%.*s] %d %d %d\n", path, pos, path, n,
// &s[i + 1], n, depth, ed);
// NOTE(cpq): in the check sequence below is important.
// strncmp() must go first: it fails fast if the remaining length of
// the path is smaller than `n`.
// printf("K %s [%.*s] [%.*s] %d %d %d %d %d\n", path, pos, path, n,
// &s[i + 1], n, depth, ed, ci, ei);
// NOTE(cpq): in the check sequence below is important.
// strncmp() must go first: it fails fast if the remaining length of
// the path is smaller than `n`.
if (depth == ed && path[pos - 1] == '.' &&
strncmp(&s[i + 1], &path[pos], (size_t) n) == 0 &&
(path[pos + n] == '\0' || path[pos + n] == '.' ||
Expand Down Expand Up @@ -2632,6 +2632,10 @@ int mg_json_get(struct mg_str json, const char *path, int *toklen) {
} else if (c == ',') {
expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
} else if (c == ']' || c == '}') {
if (depth == ed && c == '}' && path[pos - 1] == '.')
return MG_JSON_NOT_FOUND;
if (depth == ed && c == ']' && path[pos - 1] == ',')
return MG_JSON_NOT_FOUND;
MG_EOO('O');
if (depth == ed && ei >= 0) ci++;
} else {
Expand Down
14 changes: 9 additions & 5 deletions src/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,11 @@ int mg_json_get(struct mg_str json, const char *path, int *toklen) {
if (i + 1 + n >= len) return MG_JSON_NOT_FOUND;
if (depth < ed) return MG_JSON_NOT_FOUND;
if (depth == ed && path[pos - 1] != '.') return MG_JSON_NOT_FOUND;
// printf("K %s [%.*s] [%.*s] %d %d %d\n", path, pos, path, n,
// &s[i + 1], n, depth, ed);
// NOTE(cpq): in the check sequence below is important.
// strncmp() must go first: it fails fast if the remaining length of
// the path is smaller than `n`.
// printf("K %s [%.*s] [%.*s] %d %d %d %d %d\n", path, pos, path, n,
// &s[i + 1], n, depth, ed, ci, ei);
// NOTE(cpq): in the check sequence below is important.
// strncmp() must go first: it fails fast if the remaining length of
// the path is smaller than `n`.
if (depth == ed && path[pos - 1] == '.' &&
strncmp(&s[i + 1], &path[pos], (size_t) n) == 0 &&
(path[pos + n] == '\0' || path[pos + n] == '.' ||
Expand Down Expand Up @@ -202,6 +202,10 @@ int mg_json_get(struct mg_str json, const char *path, int *toklen) {
} else if (c == ',') {
expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
} else if (c == ']' || c == '}') {
if (depth == ed && c == '}' && path[pos - 1] == '.')
return MG_JSON_NOT_FOUND;
if (depth == ed && c == ']' && path[pos - 1] == ',')
return MG_JSON_NOT_FOUND;
MG_EOO('O');
if (depth == ed && ei >= 0) ci++;
} else {
Expand Down
12 changes: 12 additions & 0 deletions test/unit_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2939,6 +2939,18 @@ static void test_json(void) {
ASSERT(mg_json_get_long(mg_str("[0, 42]"), "$[1]", 0) == 42);
ASSERT(mg_json_get_long(mg_str("[[], 42]"), "$[1]", 0) == 42);
ASSERT(mg_json_get_long(mg_str("[{}, 42]"), "$[1]", 0) == 42);

json = mg_str("[{\"a\":1},{\"a\":2}]");
ASSERT(mg_json_get_long(json, "$[0]", -1) == -1);
ASSERT(mg_json_get_long(json, "$[0].a", -1) == 1);
ASSERT(mg_json_get_long(json, "$[1].a", -1) == 2);
ASSERT(mg_json_get_long(json, "$[2].a", -1) == -1);

json = mg_str("[{\"a1\":1},{\"a\":2}]");
ASSERT(mg_json_get_long(json, "$[0]", -1) == -1);
ASSERT(mg_json_get_long(json, "$[0].a", -1) == -1);
ASSERT(mg_json_get_long(json, "$[1].a", -1) == 2);
ASSERT(mg_json_get_long(json, "$[2].a", -1) == -1);
}

static void resp_rpc(struct mg_rpc_req *r) {
Expand Down

0 comments on commit 58886a9

Please sign in to comment.