tree schema BUGFIX unlinking derived identities on error
Fixes #1808
diff --git a/src/context.c b/src/context.c
index 15043d3..7fb58df 100644
--- a/src/context.c
+++ b/src/context.c
@@ -1251,7 +1251,7 @@
lysc_module_free(mod->compiled);
mod->compiled = NULL;
}
- lys_module_free(ctx->list.objs[ctx->list.count - 1]);
+ lys_module_free(ctx->list.objs[ctx->list.count - 1], 0);
}
free(ctx->list.objs);
diff --git a/src/tree_schema.c b/src/tree_schema.c
index eec6e97..c7f75ef 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -1141,7 +1141,7 @@
}
/* free the module */
- lys_module_free(m);
+ lys_module_free(m, 1);
}
if (unres->implementing.count) {
@@ -1713,7 +1713,7 @@
}
}
if (!module_created) {
- lys_module_free(mod);
+ lys_module_free(mod, 0);
mod = mod_dup;
}
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index fdb0bd5..c6c9344 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -611,6 +611,74 @@
FREE_ARRAY(ctx, must->exts, lysc_ext_instance_free);
}
+static void
+lysc_ident_derived_unlink(const struct lysc_ident *ident)
+{
+ LY_ARRAY_COUNT_TYPE u, v, w;
+ const struct lysp_submodule *submod;
+ const struct lysp_module *base_pmod;
+ const struct lysp_ident *identp = NULL;
+ const struct lys_module *mod;
+ const char *base_name;
+
+ /* find the parsed identity */
+ LY_ARRAY_FOR(ident->module->parsed->identities, u) {
+ if (ident->module->parsed->identities[u].name == ident->name) {
+ identp = &ident->module->parsed->identities[u];
+ base_pmod = ident->module->parsed;
+ break;
+ }
+ }
+ if (!identp) {
+ LY_ARRAY_FOR(ident->module->parsed->includes, v) {
+ submod = ident->module->parsed->includes[v].submodule;
+ LY_ARRAY_FOR(submod->identities, u) {
+ if (submod->identities[u].name == ident->name) {
+ identp = &submod->identities[u];
+ base_pmod = (struct lysp_module *)submod;
+ break;
+ }
+ }
+ }
+ }
+ assert(identp);
+
+ /* remove link from all the foreign bases, it may not be there if identity compilation failed */
+ LY_ARRAY_FOR(identp->bases, u) {
+ base_name = strchr(identp->bases[u], ':');
+ if (!base_name) {
+ continue;
+ }
+
+ /* prefixed identity */
+ mod = ly_resolve_prefix(ident->module->ctx, identp->bases[u], base_name - identp->bases[u], LY_VALUE_SCHEMA,
+ (void *)base_pmod);
+ if (!mod) {
+ continue;
+ }
+ ++base_name;
+
+ /* find the compiled base */
+ LY_ARRAY_FOR(mod->identities, v) {
+ if (!strcmp(mod->identities[v].name, base_name)) {
+ /* find the derived link */
+ LY_ARRAY_FOR(mod->identities[v].derived, w) {
+ if (mod->identities[v].derived[w] == ident) {
+ /* remove the link */
+ LY_ARRAY_DECREMENT(mod->identities[v].derived);
+ if (w < LY_ARRAY_COUNT(mod->identities[v].derived)) {
+ memmove(mod->identities[v].derived + w, mod->identities[v].derived + w + 1,
+ (LY_ARRAY_COUNT(mod->identities[v].derived) - w) * sizeof ident);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
void
lysc_ident_free(struct ly_ctx *ctx, struct lysc_ident *ident)
{
@@ -1014,14 +1082,23 @@
}
void
-lys_module_free(struct lys_module *module)
+lys_module_free(struct lys_module *module, ly_bool remove_links)
{
+ LY_ARRAY_COUNT_TYPE u;
+
if (!module) {
return;
}
+
assert(!module->implemented);
assert(!module->compiled);
+ if (remove_links) {
+ /* remove derived identity links */
+ LY_ARRAY_FOR(module->identities, u) {
+ lysc_ident_derived_unlink(&module->identities[u]);
+ }
+ }
FREE_ARRAY(module->ctx, module->identities, lysc_ident_free);
lysp_module_free(module->parsed);
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index a5ff013..a62f273 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -809,8 +809,10 @@
* @brief Free the schema structure. It just frees, it does not remove the schema from its context.
*
* @param[in,out] module Schema module structure to free.
+ * @param[in] remove_links Whether to remove links in other modules to structures in this module. Not needed if
+ * the whole context is being freed.
*/
-void lys_module_free(struct lys_module *module);
+void lys_module_free(struct lys_module *module, ly_bool remove_links);
/**
* @brief match yang keyword