Skip to content

Commit 6c8709d

Browse files
committed
tree schema BUGFIX submodule double include fix
Fixes #2390
1 parent dbd3a3b commit 6c8709d

File tree

2 files changed

+53
-20
lines changed

2 files changed

+53
-20
lines changed

src/tree_schema_common.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -697,14 +697,15 @@ lysp_check_dup_identities(struct lysp_ctx *ctx, struct lysp_module *mod)
697697
* @param[in] main_ctx Parser context of the main module in case of loading submodule.
698698
* @param[in] main_name Main module name in case of loading submodule.
699699
* @param[in,out] new_mods Set of all the new mods added to the context. Includes this module and all of its imports.
700-
* @param[out] result Parsed YANG schema tree of the requested module (struct lys_module*) or submodule (struct lysp_submodule*).
701-
* If it is a module, it is already in the context!
700+
* @param[out] found Whether any (sub)module was found.
701+
* @param[out] result Parsed YANG schema tree of the requested module (struct lys_module *) or submodule
702+
* (struct lysp_submodule *). If a module, it has already been inserted into the context.
702703
* @return LY_SUCCESS on success.
703704
* @return LY_ERR on error.
704705
*/
705706
static LY_ERR
706707
lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision, struct lysp_ctx *main_ctx,
707-
const char *main_name, struct ly_set *new_mods, void **result)
708+
const char *main_name, struct ly_set *new_mods, ly_bool *found, void **result)
708709
{
709710
struct ly_in *in;
710711
char *filepath = NULL;
@@ -713,6 +714,7 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision,
713714
LY_ERR ret = LY_SUCCESS;
714715
struct lysp_load_module_data mod_data = {0};
715716

717+
*found = 0;
716718
*result = NULL;
717719

718720
LY_CHECK_RET(lys_search_localfile(ly_ctx_get_searchdirs(ctx), !(ctx->flags & LY_CTX_DISABLE_SEARCHDIR_CWD), name,
@@ -740,6 +742,7 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision,
740742
ly_in_free(in, 1);
741743
LY_CHECK_GOTO(ret, cleanup);
742744

745+
*found = 1;
743746
*result = mod;
744747

745748
cleanup:
@@ -766,7 +769,7 @@ lys_load_mod_from_clb_or_file(struct ly_ctx *ctx, const char *name, const char *
766769
LY_ERR r;
767770
const char *module_data = NULL;
768771
LYS_INFORMAT format = LYS_IN_UNKNOWN;
769-
ly_bool clb_used, searchdirs_used;
772+
ly_bool clb_used, searchdirs_used, found = 0;
770773

771774
void (*module_data_free)(void *module_data, void *user_data) = NULL;
772775
struct lysp_load_module_data mod_data = {0};
@@ -794,7 +797,7 @@ lys_load_mod_from_clb_or_file(struct ly_ctx *ctx, const char *name, const char *
794797
searchdirs_used = 0;
795798
}
796799

797-
while (!*mod && (!clb_used || !searchdirs_used)) {
800+
while (!found && (!clb_used || !searchdirs_used)) {
798801
if ((!(ctx->flags & LY_CTX_PREFER_SEARCHDIRS) || searchdirs_used) && !clb_used) {
799802
if (!ctx->imp_clb(name, revision, NULL, NULL, ctx->imp_clb_data, &format, &module_data, &module_data_free)) {
800803
/* parse the module returned by the callback */
@@ -807,6 +810,8 @@ lys_load_mod_from_clb_or_file(struct ly_ctx *ctx, const char *name, const char *
807810
module_data_free((void *)module_data, ctx->imp_clb_data);
808811
}
809812
LY_CHECK_RET(r);
813+
814+
found = 1;
810815
}
811816
clb_used = 1;
812817

@@ -815,7 +820,7 @@ lys_load_mod_from_clb_or_file(struct ly_ctx *ctx, const char *name, const char *
815820
(*mod)->latest_revision |= LYS_MOD_LATEST_IMPCLB;
816821
}
817822
} else if (!searchdirs_used) {
818-
LY_CHECK_RET(lys_parse_localfile(ctx, name, revision, NULL, NULL, new_mods, (void **)mod));
823+
LY_CHECK_RET(lys_parse_localfile(ctx, name, revision, NULL, NULL, new_mods, &found, (void **)mod));
819824
searchdirs_used = 1;
820825

821826
if (*mod && !revision) {
@@ -1119,28 +1124,34 @@ lysp_inject_submodule(struct lysp_ctx *pctx, struct lysp_include *inc)
11191124
/**
11201125
* @brief Load submodule from searchdirs or from callback.
11211126
*
1127+
* Parsing another (YANG 1.0) submodule can cause inserting submodule's include into the main module moving
1128+
* existing includes (changing any pointers to includes).
1129+
*
11221130
* @param[in] pctx Parser context to use.
11231131
* @param[in] name Name of submodule to load.
11241132
* @param[in] revision Revision of submodule to load.
1133+
* @param[in] submod_latest Submodule with the latest revision found in context, otherwise set to NULL.
11251134
* @param[in,out] new_mods Set of all the new mods added to the context. Includes this submodule and all of its imports.
1126-
* @param[out] submod Loaded submodule.
1135+
* @param[out] submod Parsed submodule, may be NULL if an adequate submodule has already been found before.
11271136
* @return LY_SUCCESS on success.
11281137
* @return LY_ERR on error.
11291138
*/
11301139
static LY_ERR
11311140
lysp_load_submod_from_clb_or_file(struct lysp_ctx *pctx, const char *name, const char *revision,
1132-
struct ly_set *new_mods, struct lysp_submodule **submod)
1141+
struct lysp_submodule *submod_latest, struct ly_set *new_mods, struct lysp_submodule **submod)
11331142
{
11341143
LY_ERR r;
11351144
struct ly_ctx *ctx = PARSER_CTX(pctx);
1136-
ly_bool clb_used, searchdirs_used;
1145+
ly_bool clb_used, searchdirs_used, found = 0;
11371146
const char *submodule_data = NULL;
11381147
LYS_INFORMAT format = LYS_IN_UNKNOWN;
11391148

11401149
void (*submodule_data_free)(void *module_data, void *user_data) = NULL;
11411150
struct lysp_load_module_data mod_data = {0};
11421151
struct ly_in *in;
11431152

1153+
assert(!submod_latest || (submod_latest->latest_revision != 2));
1154+
11441155
*submod = NULL;
11451156

11461157
if (!ctx->imp_clb) {
@@ -1157,7 +1168,7 @@ lysp_load_submod_from_clb_or_file(struct lysp_ctx *pctx, const char *name, const
11571168
searchdirs_used = 0;
11581169
}
11591170

1160-
while (!*submod && (!clb_used || !searchdirs_used)) {
1171+
while (!found && (!clb_used || !searchdirs_used)) {
11611172
if ((!(ctx->flags & LY_CTX_PREFER_SEARCHDIRS) || searchdirs_used) && !clb_used) {
11621173
if (!ctx->imp_clb(PARSER_CUR_PMOD(pctx)->mod->name, NULL, name, revision, ctx->imp_clb_data, &format,
11631174
&submodule_data, &submodule_data_free)) {
@@ -1172,16 +1183,18 @@ lysp_load_submod_from_clb_or_file(struct lysp_ctx *pctx, const char *name, const
11721183
submodule_data_free((void *)submodule_data, ctx->imp_clb_data);
11731184
}
11741185
LY_CHECK_RET(r);
1186+
1187+
found = 1;
11751188
}
11761189
clb_used = 1;
11771190
} else if (!searchdirs_used) {
11781191
LY_CHECK_RET(lys_parse_localfile(ctx, name, revision, pctx->main_ctx,
1179-
PARSER_CUR_PMOD(pctx->main_ctx)->mod->name, new_mods, (void **)submod));
1192+
PARSER_CUR_PMOD(pctx->main_ctx)->mod->name, new_mods, &found, (void **)submod));
11801193
searchdirs_used = 1;
11811194
}
11821195
}
11831196

1184-
if (!*submod) {
1197+
if (!*submod && !submod_latest) {
11851198
LOGVAL(ctx, LYVE_REFERENCE, "Including \"%s\" submodule into \"%s\" failed, not found.", name,
11861199
PARSER_CUR_PMOD(pctx)->is_submod ? ((struct lysp_submodule *)PARSER_CUR_PMOD(pctx))->name :
11871200
PARSER_CUR_PMOD(pctx)->mod->name);
@@ -1231,16 +1244,21 @@ lysp_load_submodules(struct lysp_ctx *pctx, struct lysp_module *pmod, struct ly_
12311244
}
12321245

12331246
/* try to load the submodule */
1234-
LY_CHECK_RET(lysp_load_submod_from_clb_or_file(pctx, inc->name, inc->rev[0] ? inc->rev : NULL, new_mods, &submod));
1247+
LY_CHECK_RET(lysp_load_submod_from_clb_or_file(pctx, inc->name, inc->rev[0] ? inc->rev : NULL, inc->submodule,
1248+
new_mods, &submod));
12351249

1236-
/* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting
1237-
* submodule's include into main module, where it is missing */
1238-
inc = &pmod->includes[u];
1239-
inc->submodule = submod;
1250+
if (submod) {
1251+
/* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting
1252+
* submodule's include into main module, where it is missing */
1253+
inc = &pmod->includes[u];
12401254

1241-
if (!submod_included) {
1242-
/* the submodule include is not present in YANG 1.0 main module - add it there */
1243-
LY_CHECK_RET(lysp_inject_submodule(pctx, &pmod->includes[u]));
1255+
assert(!inc->submodule);
1256+
inc->submodule = submod;
1257+
1258+
if (!submod_included) {
1259+
/* the submodule include is not present in YANG 1.0 main module - add it there */
1260+
LY_CHECK_RET(lysp_inject_submodule(pctx, inc));
1261+
}
12441262
}
12451263
}
12461264

tests/utests/schema/test_schema.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,21 @@ test_includes(void **state)
10331033
assert_true(mod->parsed->includes[1].injected);
10341034
}
10351035

1036+
{
1037+
/* YANG 1.0 - including one submodule in 2 includes */
1038+
struct module_clb_list list[] = {
1039+
{"main_d", "module main_d { namespace urn:test:main_d; prefix md; include sub_d_one; include sub_d_two;}"},
1040+
{"sub_d_one", "submodule sub_d_one { belongs-to main_d { prefix md; } }"},
1041+
{"sub_d_two", "submodule sub_d_two { belongs-to main_d { prefix md; } include sub_d_one;}"},
1042+
{NULL, NULL}
1043+
};
1044+
1045+
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
1046+
mod = ly_ctx_load_module(UTEST_LYCTX, "main_d", NULL, NULL);
1047+
assert_non_null(mod);
1048+
assert_int_equal(2, LY_ARRAY_COUNT(mod->parsed->includes));
1049+
}
1050+
10361051
{
10371052
/* YANG 1.1 - the missing include sub_b_two in main_b is error */
10381053
struct module_clb_list list[] = {

0 commit comments

Comments
 (0)