From 10f211e9c3ffc3a01344f30f502c7f80280fc224 Mon Sep 17 00:00:00 2001 From: Stefan Gula Date: Sun, 28 Sep 2025 23:14:17 +0200 Subject: [PATCH] parsing BUGFIX invalid backward parent pointer This patch fixes the issue if extensions are used within subsequent refine or typedef statements --- src/parser_yang.c | 16 ++++++++ tests/utests/basic/test_plugins.c | 61 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/parser_yang.c b/src/parser_yang.c index 928533022..7238e0762 100644 --- a/src/parser_yang.c +++ b/src/parser_yang.c @@ -2722,9 +2722,17 @@ parse_refine(struct lysp_yang_ctx *ctx, struct lysp_refine **refines) size_t word_len; enum ly_stmt kw; struct lysp_refine *rf; + LY_ARRAY_COUNT_TYPE u, v; LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM); + /* revalidate the backward parent pointers from extensions. The realloc within LY_ARRAY_NEW_RET is making previous entries invalid */ + LY_ARRAY_FOR(*refines, u) { + LY_ARRAY_FOR((*refines)[u].exts, v) { + (*refines)[u].exts[v].parent = &(*refines)[u]; + } + } + /* get value */ LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len)); CHECK_NONEMPTY(ctx, word_len, "refine"); @@ -2792,9 +2800,17 @@ parse_typedef(struct lysp_yang_ctx *ctx, struct lysp_node *parent, struct lysp_t size_t word_len; enum ly_stmt kw; struct lysp_tpdf *tpdf; + LY_ARRAY_COUNT_TYPE u, v; LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM); + /* revalidate the backward parent pointers from extensions. The realloc within LY_ARRAY_NEW_RET is making previous entries invalid */ + LY_ARRAY_FOR(*typedefs, u) { + LY_ARRAY_FOR((*typedefs)[u].exts, v) { + (*typedefs)[u].exts[v].parent = &(*typedefs)[u]; + } + } + /* get value */ LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len)); INSERT_WORD_GOTO(ctx, buf, tpdf->name, word, word_len, ret, cleanup); diff --git a/tests/utests/basic/test_plugins.c b/tests/utests/basic/test_plugins.c index d8422d795..d36fa7d16 100644 --- a/tests/utests/basic/test_plugins.c +++ b/tests/utests/basic/test_plugins.c @@ -26,10 +26,31 @@ const char *simple = "module libyang-plugins-simple {" " prefix s;" " typedef note { type string; }" " extension hint { argument value; }" + " extension rt;" " leaf test {" " type s:note {length 255;}" " s:hint \"some hint here\";" " }" + " grouping grp1 {" + " list l1 {key v; leaf v {type string;} leaf k {type string;}}" + " list l2 {key v; leaf v {type string;} leaf k {type string;}}" + " typedef t1 {" + " type string;" + " s:rt;" + " }" + " typedef t2 {" + " type string;" + " s:rt;" + " }" + " }" + " uses grp1 {" + " refine l1 {" + " s:rt;" + " }" + " refine l2 {" + " s:rt;" + " }" + " }" "}"; static void @@ -106,6 +127,29 @@ parse_clb(struct lysp_ctx *UNUSED(pctx), struct lysp_ext_instance *ext) return LY_SUCCESS; } +static LY_ERR +parse_clb2(struct lysp_ctx *UNUSED(pctx), struct lysp_ext_instance *ext) +{ + struct lysp_refine *refine; + struct lysp_tpdf *tpdf; + LY_ARRAY_COUNT_TYPE count = 0; + + if (ext->parent_stmt == LY_STMT_REFINE) { + refine = (struct lysp_refine *)ext->parent; + count = LY_ARRAY_COUNT(refine->exts); + } else if (ext->parent_stmt == LY_STMT_TYPEDEF) { + tpdf = (struct lysp_tpdf *)ext->parent; + count = LY_ARRAY_COUNT(tpdf->exts); + } else { + return LY_SUCCESS; + } + + if (count != 1) { + return LY_EINVAL; + } + return LY_SUCCESS; +} + struct lyplg_ext_record memory_recs[] = { { .module = "libyang-plugins-simple", @@ -124,6 +168,23 @@ struct lyplg_ext_record memory_recs[] = { .plugin.pfree = NULL, .plugin.cfree = NULL }, + { + .module = "libyang-plugins-simple", + .revision = NULL, + .name = "rt", + + .plugin.id = "memory-plugin-v1", + .plugin.parse = parse_clb2, + .plugin.compile = NULL, + .plugin.printer_info = NULL, + .plugin.printer_ctree = NULL, + .plugin.printer_ptree = NULL, + .plugin.node_xpath = NULL, + .plugin.snode = NULL, + .plugin.validate = NULL, + .plugin.pfree = NULL, + .plugin.cfree = NULL + }, {0} /* terminating zeroed item */ };