instid BUGFIX do not compile path for schema default values
Because it causes issues when freeing the modules,
depending on the order, freed nodes may be accessed.
diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c
index c23ddb5..46bb4ba 100644
--- a/src/plugins_types/instanceid.c
+++ b/src/plugins_types/instanceid.c
@@ -253,10 +253,13 @@
}
LIBYANG_API_DEF const void *
-lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
+lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *prefix_data, ly_bool *dynamic, size_t *value_len)
{
- char *ret;
+ char *ret = NULL;
+ struct ly_path *p = NULL;
+ const struct ly_path *target;
+ struct ly_err_item *err;
if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
if (dynamic) {
@@ -268,14 +271,34 @@
return value->_canonical;
}
- /* print the value in the specific format */
- if (instanceid_path2str(value->target, format, prefix_data, &ret)) {
- return NULL;
+ if (!value->target) {
+ /* schema default value, compile it first */
+ if (lyplg_type_lypath_new(ctx, value->_canonical, strlen(value->_canonical), 0, LY_VALUE_JSON, NULL, NULL,
+ NULL, &p, &err)) {
+ if (err) {
+ ly_err_print(ctx, err);
+ ly_err_free(err);
+ }
+ goto cleanup;
+ }
+
+ target = p;
+ } else {
+ target = value->target;
}
+
+ /* print the value in the specific format */
+ if (instanceid_path2str(target, format, prefix_data, &ret)) {
+ goto cleanup;
+ }
+
*dynamic = 1;
if (value_len) {
*value_len = strlen(ret);
}
+
+cleanup:
+ ly_path_free(p);
return ret;
}
@@ -283,6 +306,7 @@
lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
+ struct ly_err_item *err;
memset(dup, 0, sizeof *dup);
@@ -290,9 +314,21 @@
ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
LY_CHECK_GOTO(ret, error);
- /* copy path */
- ret = ly_path_dup(ctx, original->target, &dup->target);
- LY_CHECK_GOTO(ret, error);
+ if (!original->target) {
+ /* schema default value, needs to be compiled */
+ if (lyplg_type_lypath_new(ctx, original->_canonical, strlen(original->_canonical), 0, LY_VALUE_JSON, NULL, NULL,
+ NULL, &dup->target, &err)) {
+ if (err) {
+ ly_err_print(ctx, err);
+ ly_err_free(err);
+ }
+ goto error;
+ }
+ } else {
+ /* copy path */
+ ret = ly_path_dup(ctx, original->target, &dup->target);
+ LY_CHECK_GOTO(ret, error);
+ }
dup->realtype = original->realtype;
return LY_SUCCESS;
diff --git a/src/schema_compile.c b/src/schema_compile.c
index fde3128..bb83147 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -963,6 +963,12 @@
}
LY_ATOMIC_INC_BARRIER(((struct lysc_type *)storage->realtype)->refcount);
+ if (storage->realtype->basetype == LY_TYPE_INST) {
+ /* ly_path includes references to other nodes, in case they are in foreign modules, the context would
+ * need to be freed in specific order to avoid accessing freed memory, so just avoid storing it */
+ ly_path_free(storage->target);
+ storage->target = NULL;
+ }
return LY_SUCCESS;
}
diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
index e6113dc..04c30db 100644
--- a/tests/utests/schema/test_tree_schema_compile.c
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -1233,8 +1233,7 @@
{
struct lys_module *mod;
struct lysc_type *type;
-
- // char *str;
+ char *str;
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;typedef mytype {type instance-identifier {require-instance false;}}"
"leaf l1 {type instance-identifier {require-instance true;}}"
@@ -1255,14 +1254,14 @@
assert_int_equal(1, ((struct lysc_type_instanceid *)type)->require_instance);
/* default value */
- /* TODO needs a new SO for a proper fix; str = "module b1 {namespace urn:b1;prefix b1;"
+ str = "module b1 {namespace urn:b1;prefix b1;"
"leaf l1 {type string;}}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, str);
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED);
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b2 {namespace urn:b2;prefix b2;"
"import b1 {prefix b1;}"
"leaf l1 {type instance-identifier; default \"/b1:l1\";}}", LYS_IN_YANG, NULL));
- ly_ctx_set_options(UTEST_LYCTX, 0);*/
+ ly_ctx_set_options(UTEST_LYCTX, 0);
/* invalid cases */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG, NULL));