dict BUGFIX revert ffeedfdbce0dd98d30cba9738b1800bac483cefb

This optimization exposes another bug that it is not
possible to solve properly without NBC changes so
wait with it until a new SO version.
diff --git a/src/dict.c b/src/dict.c
index ba574c8..9f741a2 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -104,6 +104,9 @@
     str1 = ((struct ly_dict_rec *)val1_p)->value;
     str2 = ((struct ly_dict_rec *)val2_p)->value;
 
+    LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
+    LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
+
     if (mod) {
         /* used when inserting new values */
         if (strcmp(str1, str2) == 0) {
@@ -174,7 +177,7 @@
     return ret;
 }
 
-static LY_ERR
+LY_ERR
 dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -218,7 +221,9 @@
         return ret;
     }
 
-    *str_p = match->value;
+    if (str_p) {
+        *str_p = match->value;
+    }
 
     return ret;
 }
@@ -264,49 +269,3 @@
 
     return result;
 }
-
-static LY_ERR
-dict_dup(const struct ly_ctx *ctx, char *value, const char **str_p)
-{
-    LY_ERR ret = LY_SUCCESS;
-    struct ly_dict_rec *match = NULL, rec;
-    uint32_t hash;
-
-    /* set new callback to only compare memory addresses */
-    lyht_value_equal_cb prev = lyht_set_cb(ctx->dict.hash_tab, lydict_resize_val_eq);
-
-    LOGDBG(LY_LDGDICT, "duplicating %s", value);
-    hash = lyht_hash(value, strlen(value));
-    rec.value = value;
-
-    ret = lyht_find(ctx->dict.hash_tab, (void *)&rec, hash, (void **)&match);
-    if (ret == LY_SUCCESS) {
-        /* record found, increase refcount */
-        match->refcount++;
-        *str_p = match->value;
-    }
-
-    /* restore callback */
-    lyht_set_cb(ctx->dict.hash_tab, prev);
-
-    return ret;
-}
-
-LIBYANG_API_DEF LY_ERR
-lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p)
-{
-    LY_ERR result;
-
-    LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
-
-    if (!value) {
-        *str_p = NULL;
-        return LY_SUCCESS;
-    }
-
-    pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
-    result = dict_dup(ctx, (char *)value, str_p);
-    pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
-
-    return result;
-}
diff --git a/src/dict.h b/src/dict.h
index bc8cac1..cf897e7 100644
--- a/src/dict.h
+++ b/src/dict.h
@@ -113,18 +113,6 @@
  */
 LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value);
 
-/**
- * @brief Duplicate string in dictionary. Only a reference counter is incremented.
- *
- * @param[in] ctx libyang context handler
- * @param[in] value NULL-terminated string to be duplicated in the dictionary (reference counter is incremented).
- * @param[out] str_p Optional parameter to get pointer to the string corresponding to the @p value and stored in dictionary.
- * @return LY_SUCCESS in case the string already exists in the dictionary.
- * @return LY_ENOTFOUND in case the string was not found.
- * @return LY_ERR on other errors
- */
-LIBYANG_API_DECL LY_ERR lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p);
-
 /** @} dict */
 
 #ifdef __cplusplus
diff --git a/src/path.c b/src/path.c
index 3876762..9a77414 100644
--- a/src/path.c
+++ b/src/path.c
@@ -708,7 +708,7 @@
 
                 /* store the value */
                 LOG_LOCSET(key, NULL);
-                ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
+                ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
                         NULL, format, prefix_data, LYD_HINT_DATA, key, NULL);
                 LOG_LOCBACK(1, 0);
                 LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
@@ -736,7 +736,7 @@
             /* names (keys) are unique - it was checked when parsing */
             LOGVAL(ctx, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.",
                     lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
-            ly_path_predicates_free(ctx_node->module->ctx, *predicates);
+            ly_path_predicates_free(ctx, *predicates);
             *predicates = NULL;
             ret = LY_EVALID;
             goto cleanup;
@@ -771,10 +771,12 @@
         }
 
         /* store the value */
-        LOG_LOCSET(ctx_node, NULL);
-        ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
+        if (ctx_node) {
+            LOG_LOCSET(ctx_node, NULL);
+        }
+        ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
                 NULL, format, prefix_data, LYD_HINT_DATA, ctx_node, NULL);
-        LOG_LOCBACK(1, 0);
+        LOG_LOCBACK(ctx_node ? 1 : 0, 0);
         LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
         ++(*tok_idx);
 
@@ -1091,7 +1093,7 @@
     }
     lref = (const struct lysc_type_leafref *)deref_leaf_node->type;
     LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
-    ly_path_free(path2);
+    ly_path_free(ctx, path2);
     path2 = NULL;
 
     /* compile dereferenced leafref expression and append it to the path */
@@ -1099,7 +1101,7 @@
             &path2), cleanup);
     node2 = path2[LY_ARRAY_COUNT(path2) - 1].node;
     LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
-    ly_path_free(path2);
+    ly_path_free(ctx, path2);
     path2 = NULL;
 
     /* properly parsed path must always continue with ')' and '/' */
@@ -1123,9 +1125,9 @@
     LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
 
 cleanup:
-    ly_path_free(path2);
+    ly_path_free(ctx, path2);
     if (ret) {
-        ly_path_free(*path);
+        ly_path_free(ctx, *path);
         *path = NULL;
     }
     return ret;
@@ -1281,7 +1283,7 @@
 
 cleanup:
     if (ret) {
-        ly_path_free(*path);
+        ly_path_free(ctx, *path);
         *path = NULL;
     }
     LOG_LOCBACK(cur_node ? 1 : 0, 0);
@@ -1486,7 +1488,7 @@
 }
 
 void
-ly_path_free(struct ly_path *path)
+ly_path_free(const struct ly_ctx *ctx, struct ly_path *path)
 {
     LY_ARRAY_COUNT_TYPE u;
 
@@ -1495,7 +1497,7 @@
     }
 
     LY_ARRAY_FOR(path, u) {
-        ly_path_predicates_free(path[u].node->module->ctx, path[u].predicates);
+        ly_path_predicates_free(ctx, path[u].predicates);
     }
     LY_ARRAY_FREE(path);
 }
diff --git a/src/path.h b/src/path.h
index 68cf76e..9a9e342 100644
--- a/src/path.h
+++ b/src/path.h
@@ -257,8 +257,9 @@
 /**
  * @brief Free ly_path structure.
  *
+ * @param[in] ctx libyang context.
  * @param[in] path The structure ([sized array](@ref sizedarrays)) to free.
  */
-void ly_path_free(struct ly_path *path);
+void ly_path_free(const struct ly_ctx *ctx, struct ly_path *path);
 
 #endif /* LY_PATH_H_ */
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 921dd6b..8305691 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -352,16 +352,10 @@
 LIBYANG_API_DEF LY_ERR
 lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
 {
-    LY_ERR r;
-
-    if ((r = lydict_dup(ctx, original->_canonical, &dup->_canonical))) {
-        /* in case of error NULL the values so that freeing does not fail */
-        memset(dup, 0, sizeof *dup);
-        return r;
-    }
+    memset(dup, 0, sizeof *dup);
+    LY_CHECK_RET(lydict_insert(ctx, original->_canonical, 0, &dup->_canonical));
     memcpy(dup->fixed_mem, original->fixed_mem, sizeof dup->fixed_mem);
     dup->realtype = original->realtype;
-
     return LY_SUCCESS;
 }
 
@@ -894,7 +888,7 @@
             ly_err_clean((struct ly_ctx *)ctx, e);
         }
 
-        ly_path_free(*path);
+        ly_path_free(ctx, *path);
         *path = NULL;
     }
 
@@ -902,9 +896,9 @@
 }
 
 LIBYANG_API_DEF void
-lyplg_type_lypath_free(const struct ly_ctx *UNUSED(ctx), struct ly_path *path)
+lyplg_type_lypath_free(const struct ly_ctx *ctx, struct ly_path *path)
 {
-    ly_path_free(path);
+    ly_path_free(ctx, path);
 }
 
 LIBYANG_API_DEF LY_ERR
@@ -1013,7 +1007,7 @@
     LY_CHECK_GOTO(lyxp_expr_parse(ctx_node->module->ctx, str_path, 0, 1, target_path), cleanup);
 
 cleanup:
-    ly_path_free(p);
+    ly_path_free(ctx_node->module->ctx, p);
     free(str_path);
     return rc;
 }
diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c
index 6c1629c..00ad45a 100644
--- a/src/plugins_types/instanceid.c
+++ b/src/plugins_types/instanceid.c
@@ -319,7 +319,7 @@
 {
     lydict_remove(ctx, value->_canonical);
     value->_canonical = NULL;
-    ly_path_free(value->target);
+    ly_path_free(ctx, value->target);
 }
 
 /**
diff --git a/src/schema_compile.c b/src/schema_compile.c
index fde3128..bda517c 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -866,7 +866,7 @@
 
     /* get the target node */
     target = p[LY_ARRAY_COUNT(p) - 1].node;
-    ly_path_free(p);
+    ly_path_free(node->module->ctx, p);
 
     if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
         LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target node is %s instead of leaf or leaf-list.",
@@ -1456,7 +1456,7 @@
             ret = ly_path_compile_leafref(cctx.ctx, l->node, cctx.ext, lref->path,
                     (l->node->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
                     LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, &path);
-            ly_path_free(path);
+            ly_path_free(l->node->module->ctx, path);
 
             assert(ret != LY_ERECOMPILE);
             if (ret) {
diff --git a/src/tree_data.c b/src/tree_data.c
index cc33341..e1463ea 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -3624,7 +3624,7 @@
 
 cleanup:
     lyxp_expr_free(LYD_CTX(ctx_node), expr);
-    ly_path_free(lypath);
+    ly_path_free(LYD_CTX(ctx_node), lypath);
     return ret;
 }
 
diff --git a/src/tree_data_new.c b/src/tree_data_new.c
index 2b27be6..f3bd9e7 100644
--- a/src/tree_data_new.c
+++ b/src/tree_data_new.c
@@ -1811,7 +1811,7 @@
             LY_ARRAY_INCREMENT(p);
         }
     }
-    ly_path_free(p);
+    ly_path_free(ctx, p);
     if (!ret) {
         /* set out params only on success */
         if (new_parent) {
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 81bda1b..d7ac8d8 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -644,7 +644,7 @@
     ret = lys_find_lypath_atoms(p, set);
 
 cleanup:
-    ly_path_free(p);
+    ly_path_free(ctx, p);
     lyxp_expr_free(ctx, expr);
     return ret;
 }
@@ -679,7 +679,7 @@
     snode = p[LY_ARRAY_COUNT(p) - 1].node;
 
 cleanup:
-    ly_path_free(p);
+    ly_path_free(ctx, p);
     lyxp_expr_free(ctx, expr);
     return snode;
 }
diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c
index 0faaa3c..dcfb096 100644
--- a/src/tree_schema_common.c
+++ b/src/tree_schema_common.c
@@ -1829,7 +1829,7 @@
 
     /* get the target node */
     target = p[LY_ARRAY_COUNT(p) - 1].node;
-    ly_path_free(p);
+    ly_path_free(node->module->ctx, p);
 
     return target;
 }
diff --git a/src/xpath.c b/src/xpath.c
index 2251eab..0b3062f 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -4042,7 +4042,7 @@
             if (!r) {
                 /* get the target node */
                 target = p[LY_ARRAY_COUNT(p) - 1].node;
-                ly_path_free(p);
+                ly_path_free(set->ctx, p);
 
                 LY_CHECK_RET(lyxp_set_scnode_insert_node(set, target, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL));
             } /* else the target was found before but is disabled so it was removed */
@@ -8272,9 +8272,7 @@
         options &= ~LYXP_SKIP_EXPR;
     }
     lydict_remove(set->ctx, ncname_dict);
-    if (predicates) {
-        ly_path_predicates_free(scnode->module->ctx, predicates);
-    }
+    ly_path_predicates_free(set->ctx, predicates);
     return rc;
 }