Skip to content

Commit 005a8b4

Browse files
affan-archmichalvasko
authored andcommitted
parser json BUGFIX use-after-free of escaped member names
A member name containing escape sequences is decoded into a buffer owned by the JSON context, which is freed by the next lyjson_ctx_next(). lydjson_meta_attr_instance() and lydjson_envelope() kept using the name/prefix pointing into it after that call, so take ownership of the buffer the same way lydjson_subtree_r() does.
1 parent 3749543 commit 005a8b4

2 files changed

Lines changed: 25 additions & 0 deletions

File tree

‎src/parser_json.c‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ lydjson_meta_attr_instance(struct lyd_json_ctx *lydctx, struct lyd_node *node, c
754754
LY_ERR rc = LY_SUCCESS;
755755
enum LYJSON_PARSER_STATUS status;
756756
const char *name, *prefix;
757+
char *value = NULL;
757758
uint32_t name_len, prefix_len;
758759
struct lys_module *mod;
759760
const struct ly_ctx *ctx = lydctx->jsonctx->ctx;
@@ -773,6 +774,7 @@ lydjson_meta_attr_instance(struct lyd_json_ctx *lydctx, struct lyd_node *node, c
773774
}
774775

775776
lydjson_parse_name(lydctx->jsonctx->value, lydctx->jsonctx->value_len, &name, &name_len, &prefix, &prefix_len, &is_attr);
777+
lyjson_ctx_give_dynamic_value(lydctx->jsonctx, &value);
776778

777779
if (!name_len) {
778780
LOGVAL(ctx, prev_node, LYVE_SYNTAX_JSON, "Metadata in JSON found with an empty name, followed by \"%.10s\".", name);
@@ -851,6 +853,7 @@ lydjson_meta_attr_instance(struct lyd_json_ctx *lydctx, struct lyd_node *node, c
851853
}
852854

853855
cleanup:
856+
free(value);
854857
return rc;
855858
}
856859

@@ -2109,6 +2112,7 @@ lydjson_envelope(struct lyjson_ctx *jsonctx, const char *name, const char *modul
21092112
LY_ERR rc = LY_SUCCESS, r;
21102113
enum LYJSON_PARSER_STATUS status = lyjson_ctx_status(jsonctx);
21112114
const char *nam, *prefix;
2115+
char *value = NULL;
21122116
uint32_t nam_len, prefix_len;
21132117
ly_bool is_meta;
21142118

@@ -2127,6 +2131,7 @@ lydjson_envelope(struct lyjson_ctx *jsonctx, const char *name, const char *modul
21272131
/* process the name */
21282132
assert(status == LYJSON_OBJECT_NAME);
21292133
lydjson_parse_name(jsonctx->value, jsonctx->value_len, &nam, &nam_len, &prefix, &prefix_len, &is_meta);
2134+
lyjson_ctx_give_dynamic_value(jsonctx, &value);
21302135
if (is_meta) {
21312136
LOGVAL(jsonctx->ctx, NULL, LYVE_DATA, "Unexpected metadata.");
21322137
rc = LY_EVALID;
@@ -2151,6 +2156,7 @@ lydjson_envelope(struct lyjson_ctx *jsonctx, const char *name, const char *modul
21512156
LY_CHECK_GOTO(rc, cleanup);
21522157

21532158
cleanup:
2159+
free(value);
21542160
if (rc) {
21552161
lyd_free_tree(*envp);
21562162
*envp = NULL;

‎tests/utests/data/test_parser_json.c‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,12 @@ test_leaf(void **state)
220220
assert_int_equal(LY_EINVAL, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
221221
CHECK_LOG_CTX("Annotation definition for attribute \"a:hi\nt\" not found.", "/a:foo/@a:hi\nt", 1);
222222

223+
/* escaped metadata member name */
224+
data = "{\"a:foo\":\"xxx\",\"@a:foo\":{\"a:hin\\u0074\":1}}";
225+
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
226+
CHECK_LYD_META(tree->meta, 1, "hint", 0, 1, INT8, "1", 1);
227+
lyd_free_all(tree);
228+
223229
data = "{\"a:foo\": null}";
224230
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Invalid non-string-encoded string value \"\".", "/a:foo", 1);
225231
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
@@ -990,6 +996,19 @@ test_restconf_notification(void **state)
990996
lyd_free_all(tree);
991997
lyd_free_all(ntf);
992998

999+
/* escaped envelope member name */
1000+
data = "{\"ietf-restconf:notificatio\\u006e\":{\"eventTime\":\"2013-12-21T00:01:00Z\",\"a:n2\":{}}}";
1001+
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
1002+
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, LYD_PARSE_STRICT,
1003+
&tree, &ntf));
1004+
ly_in_free(in, 0);
1005+
1006+
data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\"}}";
1007+
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_SIBLINGS, data);
1008+
1009+
lyd_free_all(tree);
1010+
lyd_free_all(ntf);
1011+
9931012
/* wrong order */
9941013
data = "{\"ietf-restconf:notification\":{\"a:n2\":{},\"eventTime\":\"2013-12-21T00:01:00Z\"}}";
9951014
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));

0 commit comments

Comments
 (0)