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;
     }