[glib/update-variant-child-value-docs] gvariant-core: Add a note about memory safety of children



commit 51b822787ec55c1f03af359160ef48a2ac3a59db
Author: Matthew Leeds <matthew leeds endlessm com>
Date:   Mon Apr 27 16:41:14 2020 -0700

    gvariant-core: Add a note about memory safety of children
    
    When g_variant_get_child() is called on a variant which has not been
    serialized, it serializes it which includes a call to
    g_variant_release_children() and therefore means that any children
    previously retrieved from the variant are no longer valid (unless
    another reference is held on them) and consequently values borrowed from
    those children are no longer safe to access. Add a note to the
    g_variant_get_child_value() documentation to explain this.
    
    Alternatively, we could say that after the child is freed, values
    borrowed from it are no longer valid. But we already have an
    implementation which hasn't changed in years which lets them stay valid
    if the variant was serialized before the first
    g_variant_get_child_value() call.
    
    Here's a demonstration of the memory error:
    
    static const char *get_first_child (GVariant *v) {
        g_autoptr(GVariant) child_v = g_variant_get_child_value (v, 0);
        return g_variant_get_string (child_v, NULL);
    }
    int main(int argc, char **argv) {
        g_autoptr(GVariant) v = g_variant_new("(@ss)", g_variant_new_string ("hello"), "world");
        const char *child1 = get_first_child (v);
        const char *child2;
        g_variant_get_child (v, 1, "&s", &child2);
        printf ("%s\n", child1); // this is a memory error
        return 0;
    }

 glib/gvariant-core.c | 6 ++++++
 1 file changed, 6 insertions(+)
---
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
index f0b372f40..b2470c488 100644
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -1026,6 +1026,12 @@ g_variant_n_children (GVariant *value)
  * The returned value is never floating.  You should free it with
  * g_variant_unref() when you're done with it.
  *
+ * Note that values borrowed from the returned child are not guaranteed to
+ * still be valid after the child is freed even if you still hold a reference
+ * to @value, if @value has not been serialised at the time this function is
+ * called. To avoid this, you can serialize @value by calling
+ * g_variant_get_data() and optionally ignoring the return value.
+ *
  * There may be implementation specific restrictions on deeply nested values,
  * which would result in the unit tuple being returned as the child value,
  * instead of further nested children. #GVariant is guaranteed to handle


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]