don't free or modify static strings, dup them when needed and clear the
authorMichael Natterer <mitch@imendio.com>
Tue, 24 Apr 2007 13:36:58 +0000 (13:36 +0000)
committerMichael Natterer <mitch@src.gnome.org>
Tue, 24 Apr 2007 13:36:58 +0000 (13:36 +0000)
2007-04-24  Michael Natterer  <mitch@imendio.com>

* gobject/gparamspecs.c (param_string_validate): don't free or
modify static strings, dup them when needed and clear the
G_VALUE_NOCOPY_CONTENTS flag. Fixes bug #432895.

* tests/gobject/paramspec-test.c: test all GParamSpecString
validations with static and allocated strings.

svn path=/trunk/; revision=5454

ChangeLog
gobject/gparamspecs.c
tests/gobject/paramspec-test.c

index b7c92e6..a5b39c0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-04-24  Michael Natterer  <mitch@imendio.com>
+
+       * gobject/gparamspecs.c (param_string_validate): don't free or
+       modify static strings, dup them when needed and clear the
+       G_VALUE_NOCOPY_CONTENTS flag. Fixes bug #432895.
+
+       * tests/gobject/paramspec-test.c: test all GParamSpecString
+       validations with static and allocated strings.
+
 2007-04-19  William Jon McCann  <mccann@jhu.edu>
 
        * glib/gkeyfile.[ch]: (find_file_in_data_dirs),
index 78bb7cb..ea502b3 100644 (file)
@@ -629,6 +629,12 @@ param_string_validate (GParamSpec *pspec,
       
       if (sspec->cset_first && !strchr (sspec->cset_first, string[0]))
        {
+          if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
+            {
+              value->data[0].v_pointer = g_strdup (string);
+              string = value->data[0].v_pointer;
+              value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
+            }
          string[0] = sspec->substitutor;
          changed++;
        }
@@ -636,13 +642,23 @@ param_string_validate (GParamSpec *pspec,
        for (s = string + 1; *s; s++)
          if (!strchr (sspec->cset_nth, *s))
            {
+              if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
+                {
+                  value->data[0].v_pointer = g_strdup (string);
+                  s = (gchar*) value->data[0].v_pointer + (s - string);
+                  string = value->data[0].v_pointer;
+                  value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
+                }
              *s = sspec->substitutor;
              changed++;
            }
     }
   if (sspec->null_fold_if_empty && string && string[0] == 0)
     {
-      g_free (value->data[0].v_pointer);
+      if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
+        g_free (value->data[0].v_pointer);
+      else
+        value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
       value->data[0].v_pointer = NULL;
       changed++;
       string = value->data[0].v_pointer;
index 4f3c5b4..16ee3b1 100644 (file)
@@ -71,6 +71,78 @@ test_param_spec_char (void)
 }
 
 static void
+test_param_spec_string (void)
+{
+  GParamSpec *pspec;
+  GValue value = { 0, };
+  gboolean modified;
+
+  pspec = g_param_spec_string ("string", "nick", "blurb",
+                               NULL, G_PARAM_READWRITE);
+  g_value_init (&value, G_TYPE_STRING);
+
+  g_value_set_string (&value, "foobar");
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (!modified);
+
+  g_value_set_string (&value, "");
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (!modified && g_value_get_string (&value) != NULL);
+
+  /* test ensure_non_null */
+
+  G_PARAM_SPEC_STRING (pspec)->ensure_non_null = TRUE;
+
+  g_value_set_string (&value, NULL);
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (modified && g_value_get_string (&value) != NULL);
+
+  G_PARAM_SPEC_STRING (pspec)->ensure_non_null = FALSE;
+
+  /* test null_fold_if_empty */
+
+  G_PARAM_SPEC_STRING (pspec)->null_fold_if_empty = TRUE;
+
+  g_value_set_string (&value, "");
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (modified && g_value_get_string (&value) == NULL);
+
+  g_value_set_static_string (&value, "");
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (modified && g_value_get_string (&value) == NULL);
+
+  G_PARAM_SPEC_STRING (pspec)->null_fold_if_empty = FALSE;
+
+  /* test cset_first */
+
+  G_PARAM_SPEC_STRING (pspec)->cset_first = g_strdup ("abc");
+  G_PARAM_SPEC_STRING (pspec)->substitutor = '-';
+
+  g_value_set_string (&value, "ABC");
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (modified && g_value_get_string (&value)[0] == '-');
+
+  g_value_set_static_string (&value, "ABC");
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (modified && g_value_get_string (&value)[0] == '-');
+
+  /* test cset_nth */
+
+  G_PARAM_SPEC_STRING (pspec)->cset_nth = g_strdup ("abc");
+
+  g_value_set_string (&value, "aBC");
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (modified && g_value_get_string (&value)[1] == '-');
+
+  g_value_set_static_string (&value, "aBC");
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (modified && g_value_get_string (&value)[1] == '-');
+
+  g_value_unset (&value);
+  g_param_spec_unref (pspec);
+}
+
+static void
 test_param_spec_override (void)
 {
   GParamSpec *ospec, *pspec;
@@ -140,6 +212,7 @@ main (int argc, char *argv[])
   g_type_init (); 
   
   test_param_spec_char ();
+  test_param_spec_string ();
   test_param_spec_override ();
   test_param_spec_gtype ();