parser BUGFIX memory-leak due to tpdfs_nodes
diff --git a/src/parser_yang.c b/src/parser_yang.c
index aa35b81..48d8d44 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -2694,7 +2694,8 @@
/* store data for collision check */
if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
- LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
+ assert(ctx->main_ctx);
+ LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, parent, 0, NULL));
}
return ret;
@@ -4557,6 +4558,16 @@
LY_CHECK_ERR_RET(!(*context), LOGMEM(ly_ctx), LY_EMEM);
(*context)->format = LYS_IN_YANG;
(*context)->in = in;
+ if (main_ctx) {
+ /* Forward pointer to the main module. */
+ (*context)->main_ctx = main_ctx;
+ } else {
+ /* Set this submodule as the main module because its main
+ * module was not received from the callback or there is no
+ * callback set, see ::lys_parse_load().
+ */
+ (*context)->main_ctx = (struct lys_parser_ctx *)(*context);
+ }
mod_p = calloc(1, sizeof *mod_p);
LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ly_ctx); ret = LY_EMEM, cleanup);
@@ -4566,10 +4577,6 @@
LOG_LOCINIT(NULL, NULL, NULL, in);
- /* map the typedefs and groupings list from main context to the submodule's context */
- memcpy(&(*context)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
- memcpy(&(*context)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
-
/* skip redundant but valid characters at the beginning */
ret = skip_redundant_chars(*context);
LY_CHECK_GOTO(ret, cleanup);
@@ -4629,6 +4636,7 @@
LY_CHECK_ERR_RET(!(*context), LOGMEM(mod->ctx), LY_EMEM);
(*context)->format = LYS_IN_YANG;
(*context)->in = in;
+ (*context)->main_ctx = (struct lys_parser_ctx *)(*context);
mod_p = calloc(1, sizeof *mod_p);
LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
diff --git a/src/parser_yin.c b/src/parser_yin.c
index ea056cb..d090802 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -1621,7 +1621,8 @@
/* store data for collision check */
if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT |
LYS_OUTPUT | LYS_NOTIF))) {
- LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
+ assert(ctx->main_ctx);
+ LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
}
return LY_SUCCESS;
@@ -3704,6 +3705,16 @@
*yin_ctx = calloc(1, sizeof **yin_ctx);
LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
(*yin_ctx)->format = LYS_IN_YIN;
+ if (main_ctx) {
+ /* Forward pointer to the main module. */
+ (*yin_ctx)->main_ctx = main_ctx;
+ } else {
+ /* Set this submodule as the main module because its main
+ * module was not received from the callback or there is no
+ * callback set, see ::lys_parse_load().
+ */
+ (*yin_ctx)->main_ctx = (struct lys_parser_ctx *)(*yin_ctx);
+ }
LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
mod_p = calloc(1, sizeof *mod_p);
@@ -3712,10 +3723,6 @@
mod_p->parsing = 1;
(*yin_ctx)->parsed_mod = (struct lysp_module *)mod_p;
- /* map the typedefs and groupings list from main context to the submodule's context */
- memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
- memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
-
/* check submodule */
kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
(*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
@@ -3770,6 +3777,7 @@
LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
(*yin_ctx)->format = LYS_IN_YIN;
LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
+ (*yin_ctx)->main_ctx = (struct lys_parser_ctx *)(*yin_ctx);
mod_p = calloc(1, sizeof *mod_p);
LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 21188e2..4603fb8 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -1193,10 +1193,6 @@
/* resolve imports and includes */
LY_CHECK_GOTO(ret = lys_resolve_import_include(pctx, (struct lysp_module *)submod, new_mods), error);
- /* remap possibly changed and reallocated typedefs and groupings list back to the main context */
- memcpy(&main_ctx->tpdfs_nodes, &pctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
- memcpy(&main_ctx->grps_nodes, &pctx->grps_nodes, sizeof main_ctx->grps_nodes);
-
if (format == LYS_IN_YANG) {
yang_parser_ctx_free(yangctx);
} else {
@@ -1602,9 +1598,6 @@
}
cleanup:
- if (pctx) {
- ly_set_erase(&pctx->tpdfs_nodes, NULL);
- }
if (format == LYS_IN_YANG) {
yang_parser_ctx_free(yangctx);
} else {
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 6d31a75..234daf8 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -1134,6 +1134,10 @@
yang_parser_ctx_free(struct lys_yang_parser_ctx *ctx)
{
if (ctx) {
+ if (ctx->main_ctx == (struct lys_parser_ctx *)ctx) {
+ ly_set_erase(&ctx->tpdfs_nodes, NULL);
+ ly_set_erase(&ctx->grps_nodes, NULL);
+ }
free(ctx);
}
}
@@ -1142,6 +1146,10 @@
yin_parser_ctx_free(struct lys_yin_parser_ctx *ctx)
{
if (ctx) {
+ if (ctx->main_ctx == (struct lys_parser_ctx *)ctx) {
+ ly_set_erase(&ctx->tpdfs_nodes, NULL);
+ ly_set_erase(&ctx->grps_nodes, NULL);
+ }
lyxml_ctx_free(ctx->xmlctx);
free(ctx);
}
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 33abb83..351290f 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -143,23 +143,33 @@
#define LOGVAL_PARSER(CTX, ...) LOGVAL((CTX) ? PARSER_CTX(CTX) : NULL, __VA_ARGS__)
struct lys_parser_ctx {
- LYS_INFORMAT format; /**< parser format */
- struct ly_set tpdfs_nodes; /**< set of typedef nodes */
- struct ly_set grps_nodes; /**< set of grouping nodes */
- struct lysp_module *parsed_mod; /**< (sub)module being parsed */
+ LYS_INFORMAT format; /**< parser format */
+ struct ly_set tpdfs_nodes; /**< Set of nodes that contain typedef(s). Invalid in case of
+ submodule, use ::lys_parser_ctx.main_ctx instead. */
+ struct ly_set grps_nodes; /**< Set of nodes that contain grouping(s). Invalid in case of
+ submodule, use ::lys_parser_ctx.main_ctx instead. TODO implement. */
+ struct lysp_module *parsed_mod; /**< (sub)module being parsed */
+ struct lys_parser_ctx *main_ctx; /**< This pointer must not be NULL. If this context deals with the submodule,
+ then should be set to the context of the module to which it belongs,
+ otherwise it points to the beginning of this structure. */
};
/**
* @brief Internal context for yang schema parser.
*/
struct lys_yang_parser_ctx {
- LYS_INFORMAT format; /**< parser format */
- struct ly_set tpdfs_nodes; /**< set of typedef nodes */
- struct ly_set grps_nodes; /**< set of grouping nodes */
- struct lysp_module *parsed_mod; /**< (sub)module being parsed */
- struct ly_in *in; /**< input handler for the parser */
- uint64_t indent; /**< current position on the line for YANG indentation */
- uint32_t depth; /**< current number of nested blocks, see ::LY_MAX_BLOCK_DEPTH */
+ LYS_INFORMAT format; /**< parser format */
+ struct ly_set tpdfs_nodes; /**< Set of nodes that contain typedef(s). Invalid in case of
+ submodule, use ::lys_parser_ctx.main_ctx instead. */
+ struct ly_set grps_nodes; /**< Set of nodes that contain grouping(s). Invalid in case of
+ submodule, use ::lys_parser_ctx.main_ctx instead. TODO implement. */
+ struct lysp_module *parsed_mod; /**< (sub)module being parsed */
+ struct lys_parser_ctx *main_ctx; /**< This pointer must not be NULL. If this context deals with the submodule,
+ then should be set to the context of the module to which it belongs,
+ otherwise it points to the beginning of this structure. */
+ struct ly_in *in; /**< input handler for the parser */
+ uint64_t indent; /**< current position on the line for YANG indentation */
+ uint32_t depth; /**< current number of nested blocks, see ::LY_MAX_BLOCK_DEPTH */
};
/**
@@ -171,11 +181,16 @@
* @brief Internal context for yin schema parser.
*/
struct lys_yin_parser_ctx {
- LYS_INFORMAT format; /**< parser format */
- struct ly_set tpdfs_nodes; /**< set of typedef nodes */
- struct ly_set grps_nodes; /**< set of grouping nodes */
- struct lysp_module *parsed_mod;/**< (sub)module being parsed */
- struct lyxml_ctx *xmlctx; /**< context for xml parser */
+ LYS_INFORMAT format; /**< parser format */
+ struct ly_set tpdfs_nodes; /**< Set of nodes that contain typedef(s). Invalid in case of
+ submodule, use ::lys_parser_ctx.main_ctx instead. */
+ struct ly_set grps_nodes; /**< Set of nodes that contain grouping(s). Invalid in case of
+ submodule, use ::lys_parser_ctx.main_ctx instead. TODO implement. */
+ struct lysp_module *parsed_mod; /**< (sub)module being parsed */
+ struct lys_parser_ctx *main_ctx; /**< This pointer must not be NULL. If this context deals with the submodule,
+ then should be set to the context of the module to which it belongs,
+ otherwise it points to the beginning of this structure. */
+ struct lyxml_ctx *xmlctx; /**< context for xml parser */
};
/**