From 5ce30801f9ccc372bbe9b7c98bb5324b15fb010a Mon Sep 17 00:00:00 2001
From: Michal Vasko <mvasko@cesnet.cz>
Date: Mon, 8 Mar 2021 09:34:04 +0100
Subject: [PATCH] schema tree BUGFIX freeing nodes with no module set

Context must be passed explicitly for these cases.
Fixes #1452
---
 src/parser_yin.c    | 24 ++++++++++++------------
 src/resolve.c       |  2 +-
 src/tree_internal.h |  4 +++-
 src/tree_schema.c   | 27 +++++++++++----------------
 4 files changed, 27 insertions(+), 30 deletions(-)

Index: libyang-1.0.184/src/parser_yin.c
===================================================================
--- libyang-1.0.184.orig/src/parser_yin.c
+++ libyang-1.0.184/src/parser_yin.c
@@ -4284,7 +4284,7 @@ error:
     while (root.child) {
         lyxml_free(ctx, root.child);
     }
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
 
     return NULL;
 }
@@ -4490,7 +4490,7 @@ read_yin_choice(struct lys_module *modul
 
 error:
     lyxml_free(ctx, dflt);
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     return NULL;
 }
 
@@ -4650,7 +4650,7 @@ read_yin_anydata(struct lys_module *modu
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     return NULL;
 }
 
@@ -4871,7 +4871,7 @@ read_yin_leaf(struct lys_module *module,
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     return NULL;
 }
 
@@ -5184,7 +5184,7 @@ read_yin_leaflist(struct lys_module *mod
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     return NULL;
 }
 
@@ -5556,7 +5556,7 @@ read_yin_list(struct lys_module *module,
 
 error:
 
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     while (root.child) {
         lyxml_free(ctx, root.child);
     }
@@ -5779,7 +5779,7 @@ read_yin_container(struct lys_module *mo
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     while (root.child) {
         lyxml_free(ctx, root.child);
     }
@@ -5923,7 +5923,7 @@ read_yin_grouping(struct lys_module *mod
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     while (root.child) {
         lyxml_free(ctx, root.child);
     }
@@ -6098,7 +6098,7 @@ read_yin_input_output(struct lys_module
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     while (root.child) {
         lyxml_free(ctx, root.child);
     }
@@ -6278,7 +6278,7 @@ read_yin_notif(struct lys_module *module
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     while (root.child) {
         lyxml_free(ctx, root.child);
     }
@@ -6429,7 +6429,7 @@ read_yin_rpc_action(struct lys_module *m
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     while (root.child) {
         lyxml_free(ctx, root.child);
     }
@@ -6582,7 +6582,7 @@ read_yin_uses(struct lys_module *module,
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     return NULL;
 }
 
Index: libyang-1.0.184/src/resolve.c
===================================================================
--- libyang-1.0.184.orig/src/resolve.c
+++ libyang-1.0.184/src/resolve.c
@@ -5592,7 +5592,7 @@ nextsibling:
 
 fail:
     LY_TREE_FOR_SAFE(uses->child, next, iter) {
-        lys_node_free(iter, NULL, 0);
+        lys_node_free(ctx, iter, NULL, 0);
     }
     free(refine_nodes);
     return -1;
Index: libyang-1.0.184/src/tree_internal.h
===================================================================
--- libyang-1.0.184.orig/src/tree_internal.h
+++ libyang-1.0.184/src/tree_internal.h
@@ -368,12 +368,14 @@ void lys_node_unlink(struct lys_node *no
 /**
  * @brief Free the schema node structure, includes unlinking it from the tree
  *
+ * @param[in] ctx libang context to use, @p node may not have it filled (in groupings, for example).
  * @param[in] node Schema tree node to free. Do not use the pointer after calling this function.
  * @param[in] private_destructor Optional destructor function for private objects assigned
  * to the nodes via lys_set_private(). If NULL, the private objects are not freed by libyang.
  * @param[in] shallow Whether to do a shallow free only (on a shallow copy of a node).
  */
-void lys_node_free(struct lys_node *node, void (*private_destructor)(const struct lys_node *node, void *priv), int shallow);
+void lys_node_free(struct ly_ctx *ctx, struct lys_node *node,
+                   void (*private_destructor)(const struct lys_node *node, void *priv), int shallow);
 
 /**
  * @brief Free (and unlink it from the context) the specified schema.
Index: libyang-1.0.184/src/tree_schema.c
===================================================================
--- libyang-1.0.184.orig/src/tree_schema.c
+++ libyang-1.0.184/src/tree_schema.c
@@ -938,7 +938,7 @@ skip_nodetype_check:
         iter->next = NULL;
         iter->prev = iter;
         iter->parent = NULL;
-        lys_node_free(iter, NULL, 0);
+        lys_node_free(ctx, iter, NULL, 0);
     } else {
         if (shortcase) {
             /* create the implicit case to allow it to serve as a target of the augments,
@@ -2460,7 +2460,7 @@ lys_augment_free(struct ly_ctx *ctx, str
     /* children from a resolved augment are freed under the target node */
     if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
         LY_TREE_FOR_SAFE(aug->child, next, sub) {
-            lys_node_free(sub, private_destructor, 0);
+            lys_node_free(ctx, sub, private_destructor, 0);
         }
     }
 
@@ -2718,11 +2718,11 @@ lys_deviation_free(struct lys_module *mo
 
                 LY_TREE_DFS_END(dev->orig_node, next, elem);
             }
-            lys_node_free(dev->orig_node, NULL, 0);
+            lys_node_free(ctx, dev->orig_node, NULL, 0);
         } else {
             /* it's just a shallow copy, freeing one node */
             dev->orig_node->module = module;
-            lys_node_free(dev->orig_node, NULL, 1);
+            lys_node_free(ctx, dev->orig_node, NULL, 1);
         }
     }
 
@@ -2794,20 +2794,15 @@ lys_uses_free(struct ly_ctx *ctx, struct
 }
 
 void
-lys_node_free(struct lys_node *node, void (*private_destructor)(const struct lys_node *node, void *priv), int shallow)
+lys_node_free(struct ly_ctx *ctx, struct lys_node *node,
+              void (*private_destructor)(const struct lys_node *node, void *priv), int shallow)
 {
-    struct ly_ctx *ctx;
     struct lys_node *sub, *next;
 
     if (!node) {
         return;
     }
 
-    assert(node->module);
-    assert(node->module->ctx);
-
-    ctx = node->module->ctx;
-
     /* remove private object */
     if (node->priv && private_destructor) {
         private_destructor(node, node->priv);
@@ -2823,7 +2818,7 @@ lys_node_free(struct lys_node *node, voi
 
     if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
         LY_TREE_FOR_SAFE(node->child, next, sub) {
-            lys_node_free(sub, private_destructor, 0);
+            lys_node_free(ctx, sub, private_destructor, 0);
         }
     }
 
@@ -2938,7 +2933,7 @@ module_free_common(struct lys_module *mo
      * are placed in the main module altogether */
     if (!module->type) {
         LY_TREE_FOR_SAFE(module->data, next, iter) {
-            lys_node_free(iter, private_destructor, 0);
+            lys_node_free(ctx, iter, private_destructor, 0);
         }
     }
 
@@ -3501,7 +3496,7 @@ lys_node_dup_recursion(struct lys_module
     return retval;
 
 error:
-    lys_node_free(retval, NULL, 0);
+    lys_node_free(ctx, retval, NULL, 0);
     return NULL;
 }
 
@@ -5141,7 +5136,7 @@ lys_submodule_module_data_free(struct ly
     /* remove parsed data */
     LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
         if (elem->module == (struct lys_module *)submodule) {
-            lys_node_free(elem, NULL, 0);
+            lys_node_free(submodule->ctx, elem, NULL, 0);
         }
     }
 }
@@ -5538,7 +5533,7 @@ lys_extension_instances_free(struct ly_c
                 case LY_STMT_USES:
                     pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
                     LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
-                        lys_node_free(siter, NULL, 0);
+                        lys_node_free(ctx, siter, NULL, 0);
                     }
                     *pp = NULL;
                     break;
