Skip to content

Commit 4f9da5e

Browse files
committed
tree schema BUGFIX unlinking derived identities on error
Fixes #1808
1 parent e313c38 commit 4f9da5e

File tree

6 files changed

+98
-19
lines changed

6 files changed

+98
-19
lines changed

src/context.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ ly_ctx_destroy(struct ly_ctx *ctx)
12511251
lysc_module_free(mod->compiled);
12521252
mod->compiled = NULL;
12531253
}
1254-
lys_module_free(ctx->list.objs[ctx->list.count - 1]);
1254+
lys_module_free(ctx->list.objs[ctx->list.count - 1], 0);
12551255
}
12561256
free(ctx->list.objs);
12571257

src/tree_schema.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,7 @@ lys_unres_glob_revert(struct ly_ctx *ctx, struct lys_glob_unres *unres)
11411141
}
11421142

11431143
/* free the module */
1144-
lys_module_free(m);
1144+
lys_module_free(m, 1);
11451145
}
11461146

11471147
if (unres->implementing.count) {
@@ -1713,7 +1713,7 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
17131713
}
17141714
}
17151715
if (!module_created) {
1716-
lys_module_free(mod);
1716+
lys_module_free(mod, 0);
17171717
mod = mod_dup;
17181718
}
17191719

src/tree_schema_free.c

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,74 @@ lysc_must_free(struct ly_ctx *ctx, struct lysc_must *must)
611611
FREE_ARRAY(ctx, must->exts, lysc_ext_instance_free);
612612
}
613613

614+
static void
615+
lysc_ident_derived_unlink(const struct lysc_ident *ident)
616+
{
617+
LY_ARRAY_COUNT_TYPE u, v, w;
618+
const struct lysp_submodule *submod;
619+
const struct lysp_module *base_pmod;
620+
const struct lysp_ident *identp = NULL;
621+
const struct lys_module *mod;
622+
const char *base_name;
623+
624+
/* find the parsed identity */
625+
LY_ARRAY_FOR(ident->module->parsed->identities, u) {
626+
if (ident->module->parsed->identities[u].name == ident->name) {
627+
identp = &ident->module->parsed->identities[u];
628+
base_pmod = ident->module->parsed;
629+
break;
630+
}
631+
}
632+
if (!identp) {
633+
LY_ARRAY_FOR(ident->module->parsed->includes, v) {
634+
submod = ident->module->parsed->includes[v].submodule;
635+
LY_ARRAY_FOR(submod->identities, u) {
636+
if (submod->identities[u].name == ident->name) {
637+
identp = &submod->identities[u];
638+
base_pmod = (struct lysp_module *)submod;
639+
break;
640+
}
641+
}
642+
}
643+
}
644+
assert(identp);
645+
646+
/* remove link from all the foreign bases, it may not be there if identity compilation failed */
647+
LY_ARRAY_FOR(identp->bases, u) {
648+
base_name = strchr(identp->bases[u], ':');
649+
if (!base_name) {
650+
continue;
651+
}
652+
653+
/* prefixed identity */
654+
mod = ly_resolve_prefix(ident->module->ctx, identp->bases[u], base_name - identp->bases[u], LY_VALUE_SCHEMA,
655+
(void *)base_pmod);
656+
if (!mod) {
657+
continue;
658+
}
659+
++base_name;
660+
661+
/* find the compiled base */
662+
LY_ARRAY_FOR(mod->identities, v) {
663+
if (!strcmp(mod->identities[v].name, base_name)) {
664+
/* find the derived link */
665+
LY_ARRAY_FOR(mod->identities[v].derived, w) {
666+
if (mod->identities[v].derived[w] == ident) {
667+
/* remove the link */
668+
LY_ARRAY_DECREMENT(mod->identities[v].derived);
669+
if (w < LY_ARRAY_COUNT(mod->identities[v].derived)) {
670+
memmove(mod->identities[v].derived + w, mod->identities[v].derived + w + 1,
671+
(LY_ARRAY_COUNT(mod->identities[v].derived) - w) * sizeof ident);
672+
}
673+
break;
674+
}
675+
}
676+
break;
677+
}
678+
}
679+
}
680+
}
681+
614682
void
615683
lysc_ident_free(struct ly_ctx *ctx, struct lysc_ident *ident)
616684
{
@@ -1014,14 +1082,23 @@ lysc_module_free(struct lysc_module *module)
10141082
}
10151083

10161084
void
1017-
lys_module_free(struct lys_module *module)
1085+
lys_module_free(struct lys_module *module, ly_bool remove_links)
10181086
{
1087+
LY_ARRAY_COUNT_TYPE u;
1088+
10191089
if (!module) {
10201090
return;
10211091
}
1092+
10221093
assert(!module->implemented);
10231094
assert(!module->compiled);
10241095

1096+
if (remove_links) {
1097+
/* remove derived identity links */
1098+
LY_ARRAY_FOR(module->identities, u) {
1099+
lysc_ident_derived_unlink(&module->identities[u]);
1100+
}
1101+
}
10251102
FREE_ARRAY(module->ctx, module->identities, lysc_ident_free);
10261103
lysp_module_free(module->parsed);
10271104

src/tree_schema_internal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,8 +809,10 @@ void lysc_module_free(struct lysc_module *module);
809809
* @brief Free the schema structure. It just frees, it does not remove the schema from its context.
810810
*
811811
* @param[in,out] module Schema module structure to free.
812+
* @param[in] remove_links Whether to remove links in other modules to structures in this module. Not needed if
813+
* the whole context is being freed.
812814
*/
813-
void lys_module_free(struct lys_module *module);
815+
void lys_module_free(struct lys_module *module, ly_bool remove_links);
814816

815817
/**
816818
* @brief match yang keyword

tests/utests/schema/test_parser_yang.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ setup(void **state)
104104
static int
105105
teardown(void **state)
106106
{
107-
lys_module_free(PARSER_CUR_PMOD(YCTX)->mod);
107+
lys_module_free(PARSER_CUR_PMOD(YCTX)->mod, 0);
108108
LOG_LOCBACK(0, 0, 0, 1);
109109

110110
ly_set_free(YCTX->parsed_mods, NULL);
@@ -552,7 +552,7 @@ mod_renew(struct lys_yang_parser_ctx *ctx)
552552
struct ly_ctx *ly_ctx = PARSER_CUR_PMOD(ctx)->mod->ctx;
553553
struct lysp_module *pmod;
554554

555-
lys_module_free(PARSER_CUR_PMOD(ctx)->mod);
555+
lys_module_free(PARSER_CUR_PMOD(ctx)->mod, 0);
556556
pmod = calloc(1, sizeof *pmod);
557557
ctx->parsed_mods->objs[0] = pmod;
558558
pmod->mod = calloc(1, sizeof *pmod->mod);
@@ -570,7 +570,7 @@ submod_renew(struct lys_yang_parser_ctx *ctx)
570570
struct ly_ctx *ly_ctx = PARSER_CUR_PMOD(ctx)->mod->ctx;
571571
struct lysp_submodule *submod;
572572

573-
lys_module_free(PARSER_CUR_PMOD(ctx)->mod);
573+
lys_module_free(PARSER_CUR_PMOD(ctx)->mod, 0);
574574
submod = calloc(1, sizeof *submod);
575575
ctx->parsed_mods->objs[0] = submod;
576576
submod->mod = calloc(1, sizeof *submod->mod);
@@ -772,23 +772,23 @@ test_module(void **state)
772772
assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m));
773773
CHECK_LOG_CTX("Trailing garbage \"module q {names...\" after module, expected end-of-input.", "Line number 1.");
774774
yang_parser_ctx_free(ctx_p);
775-
lys_module_free(m);
775+
lys_module_free(m, 0);
776776

777777
in.current = "prefix " SCHEMA_BEGINNING "}";
778778
m = calloc(1, sizeof *m);
779779
m->ctx = PARSER_CUR_PMOD(YCTX)->mod->ctx;
780780
assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m));
781781
CHECK_LOG_CTX("Invalid keyword \"prefix\", expected \"module\" or \"submodule\".", "Line number 1.");
782782
yang_parser_ctx_free(ctx_p);
783-
lys_module_free(m);
783+
lys_module_free(m, 0);
784784

785785
in.current = "module " SCHEMA_BEGINNING "leaf enum {type enumeration {enum seven { position 7;}}}}";
786786
m = calloc(1, sizeof *m);
787787
m->ctx = PARSER_CUR_PMOD(YCTX)->mod->ctx;
788788
assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m));
789789
CHECK_LOG_CTX("Invalid keyword \"position\" as a child of \"enum\".", "Line number 1.");
790790
yang_parser_ctx_free(ctx_p);
791-
lys_module_free(m);
791+
lys_module_free(m, 0);
792792

793793
/* extensions */
794794
TEST_GENERIC("prefix:test;}", mod->exts,

tests/utests/schema/test_parser_yin.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ setup(void **state)
162162
static int
163163
teardown_ctx(void **UNUSED(state))
164164
{
165-
lys_module_free(PARSER_CUR_PMOD(YCTX)->mod);
165+
lys_module_free(PARSER_CUR_PMOD(YCTX)->mod, 0);
166166
yin_parser_ctx_free(YCTX);
167167
YCTX = NULL;
168168

@@ -3428,7 +3428,7 @@ mod_renew(struct lys_yin_parser_ctx *ctx)
34283428
struct ly_ctx *ly_ctx = PARSER_CUR_PMOD(ctx)->mod->ctx;
34293429
struct lysp_module *pmod;
34303430

3431-
lys_module_free(PARSER_CUR_PMOD(ctx)->mod);
3431+
lys_module_free(PARSER_CUR_PMOD(ctx)->mod, 0);
34323432
pmod = calloc(1, sizeof *pmod);
34333433
ctx->parsed_mods->objs[0] = pmod;
34343434
pmod->mod = calloc(1, sizeof *pmod->mod);
@@ -3558,7 +3558,7 @@ submod_renew(struct lys_yin_parser_ctx *ctx, const char *belongs_to)
35583558
struct ly_ctx *ly_ctx = PARSER_CUR_PMOD(ctx)->mod->ctx;
35593559
struct lysp_submodule *submod;
35603560

3561-
lys_module_free(PARSER_CUR_PMOD(ctx)->mod);
3561+
lys_module_free(PARSER_CUR_PMOD(ctx)->mod, 0);
35623562
submod = calloc(1, sizeof *submod);
35633563
ctx->parsed_mods->objs[0] = submod;
35643564
submod->mod = calloc(1, sizeof *submod->mod);
@@ -3717,7 +3717,7 @@ test_yin_parse_module(void **state)
37173717
assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS);
37183718
assert_null(mod->parsed->exts->child->next->child);
37193719
assert_string_equal(mod->parsed->exts->child->next->arg, "test");
3720-
lys_module_free(mod);
3720+
lys_module_free(mod, 0);
37213721
yin_parser_ctx_free(yin_ctx);
37223722
ly_in_free(in, 0);
37233723
mod = NULL;
@@ -3755,7 +3755,7 @@ test_yin_parse_module(void **state)
37553755
"</module>\n";
37563756
assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
37573757
assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS);
3758-
lys_module_free(mod);
3758+
lys_module_free(mod, 0);
37593759
yin_parser_ctx_free(yin_ctx);
37603760
ly_in_free(in, 0);
37613761
mod = NULL;
@@ -3770,7 +3770,7 @@ test_yin_parse_module(void **state)
37703770
"</module>\n";
37713771
assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
37723772
assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS);
3773-
lys_module_free(mod);
3773+
lys_module_free(mod, 0);
37743774
yin_parser_ctx_free(yin_ctx);
37753775
ly_in_free(in, 0);
37763776
mod = NULL;
@@ -3783,7 +3783,7 @@ test_yin_parse_module(void **state)
37833783
assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
37843784
assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_EINVAL);
37853785
CHECK_LOG_CTX("Input data contains submodule which cannot be parsed directly without its main module.", NULL);
3786-
lys_module_free(mod);
3786+
lys_module_free(mod, 0);
37873787
yin_parser_ctx_free(yin_ctx);
37883788
ly_in_free(in, 0);
37893789

@@ -3798,7 +3798,7 @@ test_yin_parse_module(void **state)
37983798
assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
37993799
assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_EVALID);
38003800
CHECK_LOG_CTX("Trailing garbage \"<module>\" after module, expected end-of-input.", "Line number 6.");
3801-
lys_module_free(mod);
3801+
lys_module_free(mod, 0);
38023802
yin_parser_ctx_free(yin_ctx);
38033803
ly_in_free(in, 0);
38043804
mod = NULL;

0 commit comments

Comments
 (0)