libyang UPDATE handle different contexts in functions
Refs #1738
diff --git a/src/common.h b/src/common.h
index 20b53b0..04430c3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -220,6 +220,13 @@
#define LY_CHECK_ARG_RET(CTX, ...) GETMACRO6(__VA_ARGS__, LY_CHECK_ARG_RET5, LY_CHECK_ARG_RET4, LY_CHECK_ARG_RET3, \
LY_CHECK_ARG_RET2, LY_CHECK_ARG_RET1, DUMMY) (CTX, __VA_ARGS__)
+#define LY_CHECK_CTX_EQUAL_RET2(CTX1, CTX2, RETVAL) if ((CTX1) && (CTX2) && ((CTX1) != (CTX2))) \
+ {LOGERR(CTX1, LY_EINVAL, "Different contexts mixed in a single function call."); return RETVAL;}
+#define LY_CHECK_CTX_EQUAL_RET3(CTX1, CTX2, CTX3, RETVAL) LY_CHECK_CTX_EQUAL_RET2(CTX1, CTX2, RETVAL); \
+ LY_CHECK_CTX_EQUAL_RET2(CTX2, CTX3, RETVAL); LY_CHECK_CTX_EQUAL_RET2(CTX1, CTX3, RETVAL)
+#define LY_CHECK_CTX_EQUAL_RET(CTX, ...) GETMACRO3(__VA_ARGS__, LY_CHECK_CTX_EQUAL_RET3, LY_CHECK_CTX_EQUAL_RET2, \
+ DUMMY) (CTX, __VA_ARGS__)
+
/* count sequence size for LY_VCODE_INCHILDSTMT validation error code */
size_t LY_VCODE_INSTREXP_len(const char *str);
/* default maximum characters to print in LY_VCODE_INCHILDSTMT */
diff --git a/src/tree_data.c b/src/tree_data.c
index dae9816..6a50d73 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -871,9 +871,10 @@
{
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
- struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
+ const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
if (!module) {
module = parent->schema->module;
@@ -941,12 +942,13 @@
{
struct lyd_node *ret = NULL, *key;
const struct lysc_node *schema, *key_s;
- struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
+ const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
const void *key_val;
uint32_t key_len;
LY_ERR rc = LY_SUCCESS;
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
if (!module) {
module = parent->schema->module;
@@ -1085,9 +1087,10 @@
{
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
- struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
+ const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
if (!module) {
module = parent->schema->module;
@@ -1141,6 +1144,7 @@
const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
if (!module) {
module = parent->schema->module;
@@ -1216,9 +1220,10 @@
{
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
- struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
+ const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
if (!module) {
module = parent->schema->module;
@@ -1273,6 +1278,7 @@
size_t pref_len, name_len;
LY_CHECK_ARG_RET(ctx, ctx || parent, name, module || strchr(name, ':'), parent || meta, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
if (!ctx) {
ctx = LYD_CTX(parent);
}
@@ -1314,6 +1320,7 @@
const struct lys_module *mod;
LY_CHECK_ARG_RET(NULL, ctx, attr, parent || meta, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
if (parent && !parent->schema) {
LOGERR(ctx, LY_EINVAL, "Cannot add metadata to an opaque node \"%s\".", ((struct lyd_node_opaq *)parent)->name);
@@ -1353,6 +1360,7 @@
struct lyd_node *ret = NULL;
LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, !prefix || !strcmp(prefix, module_name), LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
if (!ctx) {
ctx = LYD_CTX(parent);
@@ -1380,6 +1388,7 @@
struct lyd_node *ret = NULL;
LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_ns, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
if (!ctx) {
ctx = LYD_CTX(parent);
@@ -2046,6 +2055,7 @@
{
LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent,
!(options & LYD_NEW_PATH_BIN_VALUE) || !(options & LYD_NEW_PATH_CANON_VALUE), LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
return lyd_new_path_(parent, ctx, NULL, path, value, 0, LYD_ANYDATA_STRING, options, node, NULL);
}
@@ -2057,6 +2067,8 @@
{
LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent,
!(options & LYD_NEW_PATH_BIN_VALUE) || !(options & LYD_NEW_PATH_CANON_VALUE), LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
+
return lyd_new_path_(parent, ctx, NULL, path, value, value_len, value_type, options, new_parent, new_node);
}
@@ -2068,6 +2080,8 @@
LY_CHECK_ARG_RET(ctx, ext, path, (path[0] == '/') || parent,
!(options & LYD_NEW_PATH_BIN_VALUE) || !(options & LYD_NEW_PATH_CANON_VALUE), LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
+
return lyd_new_path_(parent, ctx, ext, path, value, 0, LYD_ANYDATA_STRING, options, node, NULL);
}
@@ -2257,6 +2271,7 @@
LY_ERR ret = LY_SUCCESS;
LY_CHECK_ARG_RET(ctx, tree, *tree || ctx, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, ctx, LY_EINVAL);
if (diff) {
*diff = NULL;
}
@@ -2288,13 +2303,15 @@
}
API LY_ERR
-lyd_new_implicit_module(struct lyd_node **tree, const struct lys_module *module, uint32_t implicit_options, struct lyd_node **diff)
+lyd_new_implicit_module(struct lyd_node **tree, const struct lys_module *module, uint32_t implicit_options,
+ struct lyd_node **diff)
{
LY_ERR ret = LY_SUCCESS;
struct lyd_node *root, *d = NULL;
struct ly_set node_when = {0}, node_exts = {0};
LY_CHECK_ARG_RET(NULL, tree, module, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, module ? module->ctx : NULL, LY_EINVAL);
if (diff) {
*diff = NULL;
}
@@ -2656,6 +2673,7 @@
struct lyd_node *iter;
LY_CHECK_ARG_RET(NULL, parent, node, !parent->schema || (parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(LYD_CTX(parent), LYD_CTX(node), LY_EINVAL);
LY_CHECK_RET(lyd_insert_check_schema(parent->schema, NULL, node->schema));
@@ -2683,6 +2701,7 @@
struct lyd_node *iter;
LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(sibling ? LYD_CTX(sibling) : NULL, LYD_CTX(node), LY_EINVAL);
if (sibling) {
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
@@ -2724,6 +2743,7 @@
lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
{
LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
@@ -2743,6 +2763,7 @@
lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
{
LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
@@ -3812,6 +3833,8 @@
LY_ERR ret = LY_SUCCESS;
LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(*target ? LYD_CTX(*target) : NULL, source ? LYD_CTX(source) : NULL, mod ? mod->ctx : NULL,
+ LY_EINVAL);
if (!source) {
/* nothing to merge */
@@ -4080,6 +4103,7 @@
size_t pref_len, name_len;
LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
+ LY_CHECK_CTX_EQUAL_RET(first ? first->annotation->module->ctx : NULL, module ? module->ctx : NULL, NULL);
if (!first) {
return NULL;
@@ -4121,6 +4145,7 @@
ly_bool found;
LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(siblings ? LYD_CTX(siblings) : NULL, LYD_CTX(target), LY_EINVAL);
if (!siblings || (siblings->schema && target->schema &&
(lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema)))) {
@@ -4288,6 +4313,7 @@
struct lyd_node *target = NULL;
LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(siblings ? LYD_CTX(siblings) : NULL, schema->module->ctx, LY_EINVAL);
if (!siblings || (siblings->schema && (lysc_data_parent(siblings->schema) != lysc_data_parent(schema)))) {
/* no data or schema mismatch */
@@ -4330,6 +4356,7 @@
struct lyd_node_inner *parent;
LY_CHECK_ARG_RET(NULL, target, lysc_is_dup_inst_list(target->schema), set, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(siblings ? LYD_CTX(siblings) : NULL, LYD_CTX(target), LY_EINVAL);
LY_CHECK_RET(ly_set_new(set));
diff --git a/src/tree_data.h b/src/tree_data.h
index fa52499..4d04581 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -1845,6 +1845,8 @@
/**
* @brief Compare 2 data nodes if they are equivalent.
*
+ * Works correctly even if @p node1 and @p node2 have different contexts.
+ *
* @param[in] node1 The first node to compare.
* @param[in] node2 The second node to compare.
* @param[in] options Various @ref datacompareoptions.
@@ -1856,6 +1858,8 @@
/**
* @brief Compare 2 lists of siblings if they are equivalent.
*
+ * Works correctly even if @p node1 and @p node2 have different contexts.
+ *
* @param[in] node1 The first sibling list to compare.
* @param[in] node2 The second sibling list to compare.
* @param[in] options Various @ref datacompareoptions.
@@ -1867,6 +1871,8 @@
/**
* @brief Compare 2 metadata.
*
+ * If @p meta1 and @p meta2 have different contexts, they are never equivalent.
+ *
* @param[in] meta1 First metadata.
* @param[in] meta2 Second metadata.
* @return LY_SUCCESS if the metadata are equivalent.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 941895d..b4d8eaa 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -448,6 +448,7 @@
const struct lysc_node *node = NULL;
LY_CHECK_ARG_RET(NULL, module, name, NULL);
+ LY_CHECK_CTX_EQUAL_RET(parent ? parent->module->ctx : NULL, module->ctx, NULL);
if (!nodetype) {
nodetype = LYS_NODETYPE_MASK;
}
@@ -483,6 +484,7 @@
uint32_t i;
LY_CHECK_ARG_RET(NULL, ctx || ctx_node, xpath, set, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
if (!(options & LYXP_SCNODE_ALL)) {
options |= LYXP_SCNODE;
}
@@ -531,6 +533,7 @@
uint32_t i;
LY_CHECK_ARG_RET(NULL, cur_mod, expr, prefixes, set, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(ctx_node ? ctx_node->module->ctx : NULL, cur_mod->ctx, LY_EINVAL);
if (!(options & LYXP_SCNODE_ALL)) {
options = LYXP_SCNODE;
}
@@ -577,6 +580,7 @@
uint32_t i;
LY_CHECK_ARG_RET(NULL, ctx || ctx_node, xpath, set, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
if (!(options & LYXP_SCNODE_ALL)) {
options = LYXP_SCNODE;
}
@@ -658,6 +662,7 @@
struct ly_path *p = NULL;
LY_CHECK_ARG_RET(ctx, ctx || ctx_node, path, set, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(ctx, ctx_node ? ctx_node->module->ctx : NULL, LY_EINVAL);
if (!ctx) {
ctx = ctx_node->module->ctx;
@@ -691,6 +696,7 @@
uint8_t oper;
LY_CHECK_ARG_RET(ctx, ctx || ctx_node, NULL);
+ LY_CHECK_CTX_EQUAL_RET(ctx, ctx_node ? ctx_node->module->ctx : NULL, NULL);
if (!ctx) {
ctx = ctx_node->module->ctx;
diff --git a/src/validation.c b/src/validation.c
index fdfb95d..47b1afc 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1594,6 +1594,7 @@
lyd_validate_all(struct lyd_node **tree, const struct ly_ctx *ctx, uint32_t val_opts, struct lyd_node **diff)
{
LY_CHECK_ARG_RET(NULL, tree, *tree || ctx, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, ctx, LY_EINVAL);
if (!ctx) {
ctx = LYD_CTX(*tree);
}
@@ -1608,6 +1609,7 @@
lyd_validate_module(struct lyd_node **tree, const struct lys_module *module, uint32_t val_opts, struct lyd_node **diff)
{
LY_CHECK_ARG_RET(NULL, tree, *tree || module, LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, module ? module->ctx : NULL, LY_EINVAL);
if (diff) {
*diff = NULL;
}
@@ -1780,6 +1782,7 @@
LY_CHECK_ARG_RET(NULL, op_tree, !op_tree->parent, !dep_tree || !dep_tree->parent, (data_type == LYD_TYPE_RPC_YANG) ||
(data_type == LYD_TYPE_NOTIF_YANG) || (data_type == LYD_TYPE_REPLY_YANG), LY_EINVAL);
+ LY_CHECK_CTX_EQUAL_RET(LYD_CTX(op_tree), dep_tree ? LYD_CTX(dep_tree) : NULL, LY_EINVAL);
if (diff) {
*diff = NULL;
}