GNOME Bugzilla – Bug 573380
gtk_tree_model_iter_parent() fails if the same iterator is used for iter and child.
Last modified: 2016-04-05 15:02:20 UTC
Documentation Section: GtkTreeModel Sets iter to be the parent of child. If child is at the toplevel, and doesn't have a parent, then iter is set to an invalid iterator and FALSE is returned. child will remain a valid node after this function has been called. Correct version: Sets iter to be the parent of child. If child is at the toplevel, and doesn't have a parent, then iter is set to an invalid iterator and FALSE is returned. child will remain a valid node after this function has been called. If iter and child point to the same iterator this function will fail. Other information: Another solution could be to make a local copy of child before iter is initialized.
> If iter and child point to the same iterator this function will fail. If that's intended then I (not a GKT+ maintainer) would like to see a g_warning() for it in the code. > Another solution could be to make a local copy of child before iter is initialized. Yes. To be clear, this would allow the caller to forget the child iter, just changing it to be the parent iter.
The problem is, that the invariant "child != iter" is specified but not enforced. The straight forward fix would be to verify this precondition: g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE); g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (child != NULL, FALSE); + g_return_val_if_fail (iter != child, FALSE); iface = GTK_TREE_MODEL_GET_IFACE (tree_model); g_return_val_if_fail (iface->iter_parent != NULL, FALSE); Well, but it seems to be possible to allow "child == iter" by adding similarly efficient code: diff --git a/gtk/gtktreemodel.c b/gtk/gtktreemodel.c index c8cc7b2..3af92bb 100644 --- a/gtk/gtktreemodel.c +++ b/gtk/gtktreemodel.c @@ -1304,14 +1304,21 @@ gtk_tree_model_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *child) { GtkTreeModelIface *iface; + GtkTreeIter local_child; g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE); g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (child != NULL, FALSE); - + iface = GTK_TREE_MODEL_GET_IFACE (tree_model); g_return_val_if_fail (iface->iter_parent != NULL, FALSE); + if (G_UNLIKELY (iter == child)) + { + local_child = *child; + child = &local_child; + } + INITIALIZE_TREE_ITER (iter); return (* iface->iter_parent) (tree_model, iter, child);
This bug has existed since 2009, and no resolution has occurred. Can at least the documentation be updated? I just spent an inordinate amount of time tracking down why my code didn't work because of this...
A patch might be helpful.
Created attachment 325136 [details] [review] documentation patch
Review of attachment 325136 [details] [review]: Sure