diff --git a/mongoose.c b/mongoose.c index ca6ef32b..698af52f 100644 --- a/mongoose.c +++ b/mongoose.c @@ -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] == '.' || @@ -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 { diff --git a/src/json.c b/src/json.c index b97f8c49..112d41fc 100644 --- a/src/json.c +++ b/src/json.c @@ -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] == '.' || @@ -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 { diff --git a/test/unit_test.c b/test/unit_test.c index 91e32ed0..997d5f7c 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -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) {