schema compile FEATURE check of disabled leafref
Even if leafref is disabled by its if-features, all validity checks
must be performed.
diff --git a/src/schema_compile.c b/src/schema_compile.c
index 72d143e..7745b38 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -1275,7 +1275,24 @@
/* for leafref, we need 2 rounds - first detects circular chain by storing the first referred type (which
* can be also leafref, in case it is already resolved, go through the chain and check that it does not
- * point to the starting leafref type). The second round stores the first non-leafref type for later data validation. */
+ * point to the starting leafref type). The second round stores the first non-leafref type for later data validation.
+ * Also do the same check for set of the disabled leafrefs, but without the second round. */
+ while (ds_unres->disabled_leafrefs.count) {
+ node = ds_unres->disabled_leafrefs.objs[ds_unres->disabled_leafrefs.count - 1];
+ cctx.cur_mod = node->module;
+ cctx.pmod = node->module->parsed;
+ LOG_LOCSET(node, NULL, NULL, NULL);
+
+ assert(node->nodetype & (LYS_LEAF | LYS_LEAFLIST));
+ v = 0;
+ while ((ret == LY_SUCCESS) && (lref = lys_type_leafref_next(node, &v))) {
+ ret = lys_compile_unres_leafref(&cctx, node, lref, unres);
+ }
+
+ LOG_LOCBACK(1, 0, 0, 0);
+ LY_CHECK_RET(ret);
+ ly_set_rm_index(&ds_unres->disabled_leafrefs, ds_unres->disabled_leafrefs.count - 1, NULL);
+ }
for (i = processed_leafrefs; i < ds_unres->leafrefs.count; ++i) {
node = ds_unres->leafrefs.objs[i];
cctx.cur_mod = node->module;
@@ -1347,7 +1364,8 @@
}
/* some unres items may have been added */
- if ((processed_leafrefs != ds_unres->leafrefs.count) || ds_unres->xpath.count || ds_unres->dflts.count) {
+ if ((processed_leafrefs != ds_unres->leafrefs.count) || ds_unres->disabled_leafrefs.count ||
+ ds_unres->xpath.count || ds_unres->dflts.count) {
goto resolve_all;
}
@@ -1408,6 +1426,7 @@
ly_set_erase(&unres->ds_unres.dflts, NULL);
ly_set_erase(&unres->ds_unres.xpath, NULL);
ly_set_erase(&unres->ds_unres.leafrefs, NULL);
+ ly_set_erase(&unres->ds_unres.disabled_leafrefs, NULL);
ly_set_erase(&unres->ds_unres.disabled, NULL);
}
diff --git a/src/schema_compile.h b/src/schema_compile.h
index bfbe6c8..474cc22 100644
--- a/src/schema_compile.h
+++ b/src/schema_compile.h
@@ -64,10 +64,11 @@
* so their resolution can only be performed after the whole dep set compilation is done.
*/
struct lys_depset_unres {
- struct ly_set xpath; /**< when/must to check */
- struct ly_set leafrefs; /**< to validate leafref's targets */
- struct ly_set dflts; /**< set of incomplete default values */
- struct ly_set disabled; /**< set of compiled nodes whose if-feature(s) was not satisfied (stored ::lysc_node *) */
+ struct ly_set xpath; /**< when/must to check */
+ struct ly_set leafrefs; /**< to validate target of leafrefs */
+ struct ly_set dflts; /**< set of incomplete default values */
+ struct ly_set disabled; /**< set of compiled nodes whose if-feature(s) was not satisfied (stored ::lysc_node *) */
+ struct ly_set disabled_leafrefs; /**< subset of the lys_depset_unres.disabled to validate target of disabled leafrefs */
};
/**
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index 6201d6d..5ad2608 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -2668,6 +2668,7 @@
struct lysc_node_leaf *leaf)
{
struct lysp_qname *dflt;
+ struct ly_set *leafrefs_set;
LY_CHECK_RET(lys_compile_type(ctx, context_node, leaf->flags, leaf->name, type_p, &leaf->type,
leaf->units ? NULL : &leaf->units, &dflt));
@@ -2677,15 +2678,16 @@
LY_CHECK_RET(lysc_unres_leaf_dflt_add(ctx, leaf, dflt));
}
- if ((leaf->type->basetype == LY_TYPE_LEAFREF) && !(ctx->compile_opts & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
+ leafrefs_set = ctx->compile_opts & LYS_COMPILE_DISABLED ? &ctx->unres->disabled_leafrefs : &ctx->unres->leafrefs;
+ if ((leaf->type->basetype == LY_TYPE_LEAFREF) && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
/* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
- LY_CHECK_RET(ly_set_add(&ctx->unres->leafrefs, leaf, 0, NULL));
- } else if ((leaf->type->basetype == LY_TYPE_UNION) && !(ctx->compile_opts & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
+ LY_CHECK_RET(ly_set_add(leafrefs_set, leaf, 0, NULL));
+ } else if ((leaf->type->basetype == LY_TYPE_UNION) && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
LY_ARRAY_COUNT_TYPE u;
LY_ARRAY_FOR(((struct lysc_type_union *)leaf->type)->types, u) {
if (((struct lysc_type_union *)leaf->type)->types[u]->basetype == LY_TYPE_LEAFREF) {
/* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
- LY_CHECK_RET(ly_set_add(&ctx->unres->leafrefs, leaf, 0, NULL));
+ LY_CHECK_RET(ly_set_add(leafrefs_set, leaf, 0, NULL));
}
}
} else if (leaf->type->basetype == LY_TYPE_EMPTY) {
diff --git a/src/tree_schema.c b/src/tree_schema.c
index b5bf8eb..6ecdf6c 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -1068,6 +1068,7 @@
assert(!unres->ds_unres.xpath.count);
assert(!unres->ds_unres.leafrefs.count);
+ assert(!unres->ds_unres.disabled_leafrefs.count);
assert(!unres->ds_unres.dflts.count);
assert(!unres->ds_unres.disabled.count);
}
diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
index 3985a6b..3847316 100644
--- a/tests/utests/schema/test_tree_schema_compile.c
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -1582,6 +1582,16 @@
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Target of leafref \"ref1\" cannot be referenced because it is disabled by its if-features.", "Schema location /e:ref1.");
+ str = "module en {yang-version 1.1;namespace urn:en;prefix en;feature f1;"
+ "leaf ref1 {if-feature 'f1'; type leafref {path /target;}}"
+ "leaf target {type boolean;}}";
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, &mod));
+
+ str = "module e {yang-version 1.1;namespace urn:e;prefix e;feature f1;"
+ "leaf ref1 {if-feature 'f1'; type leafref {path /target;}}}";
+ assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, &mod));
+ CHECK_LOG_CTX("Not found node \"target\" in path.", "Schema location /e:ref1.");
+
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED);
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module cl {namespace urn:cl;prefix cl;feature f1;"
"leaf f {type string; if-feature 'f1';}"