gplugin/gplugin

Fix N-ary tree data handling
GNode2
2019-05-20, Olaf Hering
131a1c8978b9
Fix N-ary tree data handling

gplugin_file_tree_free_leaves frees elements of type GPluginFileTreeEntry.
gplugin_file_tree_new creates a mix of GPluginFileTreeEntry and GNode.
The result is a segfault because g_free deallocates something that
was not allocated.

Fix this by always storing elements of type GPluginFileTreeEntry into
the tree of GNodes. Adjust gplugin_manager_real_refresh to always
work with elements of GPluginFileTreeEntry when constructing paths.

Adjust gplugin_file_tree_free_non_leaves to work with elements of
type GPluginFileTreeEntry, and skip the root node to avoid a warning
from gplugin_file_tree_entry_free.

Since all nodes are the same, use a single function to free leaves
and non-leaves.
--- a/gplugin/gplugin-file-tree.c Sat Feb 02 07:37:10 2019 +0000
+++ b/gplugin/gplugin-file-tree.c Mon May 20 18:22:20 2019 +0200
@@ -60,23 +60,15 @@
* Helpers
*****************************************************************************/
static gboolean
-gplugin_file_tree_free_leaves(GNode *n, gpointer d) {
- GNode *root = d;
+gplugin_file_tree_free_helper(GNode *n, G_GNUC_UNUSED gpointer d) {
GPluginFileTreeEntry *e = n->data;
- if (n != root)
+ if (e)
gplugin_file_tree_entry_free(e);
return FALSE;
}
-static gboolean
-gplugin_file_tree_free_non_leaves(GNode *n, G_GNUC_UNUSED gpointer d) {
- g_free(n->data);
-
- return FALSE;
-}
-
/******************************************************************************
* FileTree API
*****************************************************************************/
@@ -99,6 +91,7 @@
GDir *dir = NULL;
GError *error = NULL;
GNode *node_dir = NULL;
+ GPluginFileTreeEntry *entry = NULL;
const gchar *path = (const gchar *)iter->data;
const gchar *filename = NULL;
@@ -115,13 +108,13 @@
}
/* we have a usable directory, so prepend it into the tree */
- node_dir = g_node_new(g_strdup(path));
+ entry = gplugin_file_tree_entry_new(path);
+ node_dir = g_node_new(entry);
g_node_prepend(root, node_dir);
/* now run through all of the files and add then to the dir node */
while((filename = g_dir_read_name(dir)) != NULL) {
GNode *file = NULL;
- GPluginFileTreeEntry *entry = NULL;
entry = gplugin_file_tree_entry_new(filename);
file = g_node_new(entry);
@@ -146,10 +139,9 @@
gplugin_file_tree_free(GNode *root) {
g_return_if_fail(root);
- g_node_traverse(root, G_POST_ORDER, G_TRAVERSE_LEAVES, -1,
- gplugin_file_tree_free_leaves, root);
- g_node_traverse(root, G_POST_ORDER, G_TRAVERSE_NON_LEAVES, -1,
- gplugin_file_tree_free_non_leaves, NULL);
+ g_node_traverse(root, G_POST_ORDER,
+ G_TRAVERSE_LEAVES | G_TRAVERSE_NON_LEAVES,
+ -1, gplugin_file_tree_free_helper, NULL);
g_node_destroy(root);
}
--- a/gplugin/gplugin-manager.c Sat Feb 02 07:37:10 2019 +0000
+++ b/gplugin/gplugin-manager.c Mon May 20 18:22:20 2019 +0200
@@ -360,13 +360,13 @@
manager->refresh_needed = FALSE;
for(dir = root->children; dir; dir = dir->next) {
+ GPluginFileTreeEntry *e = dir->data;
GNode *file = NULL;
- const gchar *path = (const gchar *)dir->data;
+ const gchar *path = e->filename;
for(file = dir->children; file; file = file->next) {
GPluginPlugin *plugin = NULL;
GPluginLoader *loader = NULL;
- GPluginFileTreeEntry *e = NULL;
GError *error = NULL;
GSList *l = NULL;
gchar *filename = NULL;