PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Tue Nov 6 09:06:41 PST 2007


 polkit/polkit-error.c             |    5 
 polkit/polkit-hash.c              |  103 +++++++++++++-------
 polkit/polkit-hash.h              |   20 +++
 polkit/polkit-memory.c            |   38 +++++++
 polkit/polkit-memory.h            |    3 
 polkit/polkit-policy-file-entry.c |    4 
 polkit/polkit-policy-file.c       |  192 +++++++++++++++++++++++++++-----------
 polkit/polkit-test.c              |    3 
 polkit/polkit-test.h              |    1 
 9 files changed, 271 insertions(+), 98 deletions(-)

New commits:
commit 66da3caa360b2a85d06a40336ec727c20cb7b0c6
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue Nov 6 12:03:42 2007 -0500

    add unit tests for PolKitPolicyFile and add some features to PolKitHash

diff --git a/polkit/polkit-error.c b/polkit/polkit-error.c
index 19c7f76..f87f817 100644
--- a/polkit/polkit-error.c
+++ b/polkit/polkit-error.c
@@ -177,10 +177,12 @@ polkit_error_set_error (PolKitError **error, PolKitErrorCode error_code, const c
         va_list args;
         PolKitError *e;
 
-        g_return_val_if_fail (error != NULL, FALSE);
         g_return_val_if_fail (format != NULL, FALSE);
         g_return_val_if_fail (error_code >= 0 && error_code < POLKIT_ERROR_NUM_ERROR_CODES, FALSE);
 
+        if (error == NULL)
+                goto out;
+
         e = p_new0 (PolKitError, 1);
         if (e == NULL) {
                 *error = &_oom_error;
@@ -198,6 +200,7 @@ polkit_error_set_error (PolKitError **error, PolKitErrorCode error_code, const c
                 }
         }
 
+out:
         return TRUE;
 }
 
diff --git a/polkit/polkit-hash.c b/polkit/polkit-hash.c
index 13cc0b4..47e0801 100644
--- a/polkit/polkit-hash.c
+++ b/polkit/polkit-hash.c
@@ -70,6 +70,8 @@ struct _PolKitHash
 
         PolKitHashFunc  hash_func;
         PolKitEqualFunc key_equal_func;
+        PolKitCopyFunc  key_copy_func;
+        PolKitCopyFunc  value_copy_func;
         PolKitFreeFunc  key_destroy_func;
         PolKitFreeFunc  value_destroy_func;
 };
@@ -78,6 +80,8 @@ struct _PolKitHash
  * polkit_hash_new:
  * @hash_func: The hash function to use
  * @key_equal_func: The function used to determine key equality
+ * @key_copy_func: Function for copying keys or #NULL
+ * @value_copy_func: Function for copying values or #NULL
  * @key_destroy_func: Function for freeing keys or #NULL
  * @value_destroy_func: Function for freeing values or #NULL
  *
@@ -90,6 +94,8 @@ struct _PolKitHash
 PolKitHash *
 polkit_hash_new (PolKitHashFunc  hash_func,
                  PolKitEqualFunc key_equal_func,
+                 PolKitCopyFunc  key_copy_func,
+                 PolKitCopyFunc  value_copy_func,
                  PolKitFreeFunc  key_destroy_func,
                  PolKitFreeFunc  value_destroy_func)
 {
@@ -104,6 +110,8 @@ polkit_hash_new (PolKitHashFunc  hash_func,
 
         h->refcount = 1;
         h->hash_func = hash_func;
+        h->key_copy_func = key_copy_func;
+        h->value_copy_func = value_copy_func;
         h->key_equal_func = key_equal_func;
         h->key_destroy_func = key_destroy_func;
         h->value_destroy_func = value_destroy_func;
@@ -198,14 +206,32 @@ polkit_hash_insert (PolKitHash *hash,
                     void *value)
 {
         int bucket;
-        polkit_bool_t ret;
         PolKitHashNode **nodep;
         PolKitHashNode *node;
+        void *key_copy;
+        void *value_copy;
 
         g_return_val_if_fail (hash != NULL, FALSE);
         g_return_val_if_fail (key != NULL, FALSE);
 
-        ret = FALSE;
+        key_copy = NULL;
+        value_copy = NULL;
+        if (hash->key_copy_func != NULL) {
+                key_copy = hash->key_copy_func (key);
+                if (key_copy == NULL) {
+                        goto oom;
+                }
+        } else {
+                key_copy = key;
+        }
+        if (hash->value_copy_func != NULL) {
+                value_copy = hash->value_copy_func (value);
+                if (value_copy == NULL) {
+                        goto oom;
+                }
+        } else {
+                value_copy = value;
+        }
 
         bucket = hash->hash_func (key) % hash->num_top_nodes;
 
@@ -221,10 +247,10 @@ polkit_hash_insert (PolKitHash *hash,
                                 hash->key_destroy_func (node->key);
                         if (hash->value_destroy_func != NULL)
                                 hash->value_destroy_func (node->value);
-                        node->key = key;
-                        node->value = value;
 
-                        ret = TRUE;
+                        node->key = key_copy;
+                        node->value = value_copy;
+
                         goto out;
                 } else {
                         node = node->next;
@@ -233,16 +259,23 @@ polkit_hash_insert (PolKitHash *hash,
 
         node = p_new0 (PolKitHashNode, 1);
         if (node == NULL)
-                goto out;
+                goto oom;
 
-        node->key = key;
-        node->value = value;
+        node->key = key_copy;
+        node->value = value_copy;
         *nodep = node;
 
-        ret = TRUE;
-
 out:
-        return ret;
+        return TRUE;
+
+oom:
+        if (key_copy != NULL && hash->key_copy_func != NULL && hash->key_destroy_func != NULL)
+                hash->key_destroy_func (key_copy);
+
+        if (value_copy != NULL && hash->value_copy_func != NULL && hash->value_destroy_func != NULL)
+                hash->value_destroy_func (value_copy);
+
+        return FALSE;
 }
 
 /**
@@ -395,6 +428,20 @@ polkit_hash_str_equal_func (const void *v1, const void *v2)
         return g_str_equal (v1, v2);
 }
 
+/**
+ * polkit_hash_str_copy:
+ * @p: void pointer to string
+ *
+ * Similar to p_strdup() except for types.
+ *
+ * Returns: a void pointer to a copy or #NULL on OOM
+ */
+void *
+polkit_hash_str_copy (const void *p)
+{
+        return (void *) p_strdup ((const char *) p);
+}
+
 #ifdef POLKIT_BUILD_TESTS
 
 static polkit_bool_t
@@ -421,7 +468,9 @@ _run_test (void)
         polkit_bool_t found;
 
         /* string hash tables */
-        if ((h = polkit_hash_new (polkit_hash_str_hash_func, polkit_hash_str_equal_func, p_free, p_free)) != NULL) {
+        if ((h = polkit_hash_new (polkit_hash_str_hash_func, polkit_hash_str_equal_func, 
+                                  polkit_hash_str_copy, polkit_hash_str_copy,
+                                  p_free, p_free)) != NULL) {
                 int n;
                 char *key;
                 char *value;
@@ -441,22 +490,7 @@ _run_test (void)
 
                 /* first insert the values */
                 for (n = 0; test_data [n*2] != NULL; n++) {
-
-                        key = p_strdup (test_data [n*2]);
-
-                        if (key == NULL) {
-                                goto oom;
-                        }
-
-                        value = p_strdup (test_data [n*2 + 1]);
-                        if (value == NULL) {
-                                p_free (key);
-                                goto oom;
-                        }
-
-                        if (!polkit_hash_insert (h, key, value)) {
-                                p_free (key);
-                                p_free (value);
+                        if (!polkit_hash_insert (h, test_data [n*2], test_data [n*2 + 1])) {
                                 goto oom;
                         }
                 }
@@ -473,15 +507,8 @@ _run_test (void)
                 g_assert (polkit_hash_lookup (h, "unknown", &found) == NULL && !found);
 
                 /* replace key */
-                key = p_strdup ("key1");
                 if (key != NULL) {
-                        value = p_strdup ("val1-replaced");
-                        if (value == NULL) {
-                                p_free (key);
-                        } else {
-                                /* this can never fail because on replace no new node is ever created */
-                                g_assert (polkit_hash_insert (h, key, value));
-
+                        if (polkit_hash_insert (h, "key1", "val1-replaced")) {
                                 /* check for replaced value */
                                 value = polkit_hash_lookup (h, "key1", &found);
                                 g_assert (found && value != NULL && strcmp (value, "val1-replaced") == 0);
@@ -503,7 +530,9 @@ _run_test (void)
         }
 
         /* direct hash tables */
-        if ((h = polkit_hash_new (polkit_hash_direct_hash_func, polkit_hash_direct_equal_func, NULL, NULL)) != NULL) {
+        if ((h = polkit_hash_new (polkit_hash_direct_hash_func, polkit_hash_direct_equal_func, 
+                                  NULL, NULL, 
+                                  NULL, NULL)) != NULL) {
                 if (polkit_hash_insert (h, h, h)) {
                         g_assert ((polkit_hash_lookup (h, h, &found) == h) && found);
                         if (polkit_hash_insert (h, h, NULL)) {
diff --git a/polkit/polkit-hash.h b/polkit/polkit-hash.h
index 36e2900..d841559 100644
--- a/polkit/polkit-hash.h
+++ b/polkit/polkit-hash.h
@@ -74,13 +74,28 @@ typedef polkit_bool_t (*PolKitEqualFunc) (const void *key1, const void *key2);
  *
  * Specifies the type of function which is called when a data element
  * is destroyed. It is passed the pointer to the data element and
- * should free any memory and resources allocated for it.
+ * should free any memory and resources allocated for it. The function
+ * p_free() or any of the object unref functions can be passed here.
  *
  * Since: 0.7
  */
 typedef void (*PolKitFreeFunc) (void *p);
 
 /**
+ * PolKitCopyFunc:
+ * @p: pointer
+ *
+ * Specifies the type of function which is called when a data element
+ * is to be cloned or reffed. It is passed the pointer to the data
+ * element and should return a new pointer to a reffed or cloned
+ * object. The function polkit_hash_str_copy() or any of the object
+ * ref functions can be passed here.
+ *
+ * Since: 0.7
+ */
+typedef void *(*PolKitCopyFunc) (const void *p);
+
+/**
  * PolKitHashForeachFunc:
  * @hash: the hash table
  * @key: key
@@ -101,6 +116,8 @@ typedef polkit_bool_t (*PolKitHashForeachFunc) (PolKitHash *hash,
 
 PolKitHash *polkit_hash_new (PolKitHashFunc  hash_func,
                              PolKitEqualFunc key_equal_func,
+                             PolKitCopyFunc  key_copy_func,
+                             PolKitCopyFunc  value_copy_func,
                              PolKitFreeFunc  key_destroy_func,
                              PolKitFreeFunc  value_destroy_func);
 
@@ -119,6 +136,7 @@ polkit_bool_t   polkit_hash_direct_equal_func (const void *v1, const void *v2);
 
 polkit_uint32_t polkit_hash_str_hash_func     (const void *key);
 polkit_bool_t   polkit_hash_str_equal_func    (const void *v1, const void *v2);
+void           *polkit_hash_str_copy          (const void *p);
 
 POLKIT_END_DECLS
 
diff --git a/polkit/polkit-memory.c b/polkit/polkit-memory.c
index 1c4cc98..5712a59 100644
--- a/polkit/polkit-memory.c
+++ b/polkit/polkit-memory.c
@@ -181,6 +181,38 @@ out:
         return p;
 }
 
+/**
+ * p_strndup:
+ * @s: string
+ * @n: size
+ *
+ * Duplicate a string but copy at most @n characters. If @s is longer
+ * than @n, only @n characters are copied, and a terminating null byte
+ * is added. Similar to strndup(3).
+ *
+ * Returns: Allocated memory or #NULL on OOM. Free with p_free().
+ *
+ * Since: 0.7
+ */
+char *
+p_strndup (const char *s, size_t n)
+{
+        void *p;
+        size_t len;
+
+        len = strlen (s) + 1;
+        if (len > n)
+                len = n;
+
+        p = p_malloc (len + 1);
+        if (p == NULL)
+                goto out;
+
+        memcpy (p, s, len + 1);
+out:
+        return p;
+}
+
 /*--------------------------------------------------------------------------------------------------------------*/
 #else
 /*--------------------------------------------------------------------------------------------------------------*/
@@ -231,6 +263,12 @@ p_strdup (const char *s)
         return strdup (s);
 }
 
+char *
+p_strndup (const char *s, size_t n)
+{
+        return strndup (s, n);
+}
+
 #endif /* POLKIT_BUILD_TESTS */
 
 /**
diff --git a/polkit/polkit-memory.h b/polkit/polkit-memory.h
index d7880ea..607c2e5 100644
--- a/polkit/polkit-memory.h
+++ b/polkit/polkit-memory.h
@@ -61,7 +61,8 @@ void  p_free    (void *memory);
  */
 #define p_new0(type, count) ((type*)p_malloc0 (sizeof (type) * (count)));
 
-char *p_strdup  (const char *s);
+char *p_strdup         (const char *s);
+char *p_strndup        (const char *s, size_t n);
 char* p_strdup_printf  (const char *format, ...);
 char* p_strdup_vprintf (const char *format, va_list args);
 
diff --git a/polkit/polkit-policy-file-entry.c b/polkit/polkit-policy-file-entry.c
index 53bcce5..5517ea2 100644
--- a/polkit/polkit-policy-file-entry.c
+++ b/polkit/polkit-policy-file-entry.c
@@ -386,8 +386,8 @@ _run_test (void)
 
         if ((a = polkit_hash_new (polkit_hash_str_hash_func,
                                   polkit_hash_str_equal_func,
-                                  NULL,
-                                  NULL)) == NULL)
+                                  NULL, NULL,
+                                  NULL, NULL)) == NULL)
                 goto oom;
 
         if (!polkit_hash_insert (a, "a1", "v1"))
diff --git a/polkit/polkit-policy-file.c b/polkit/polkit-policy-file.c
index a6ee2b0..e69d3bf 100644
--- a/polkit/polkit-policy-file.c
+++ b/polkit/polkit-policy-file.c
@@ -46,6 +46,7 @@
 #include "polkit-policy-file-entry.h"
 #include "polkit-debug.h"
 #include "polkit-private.h"
+#include "polkit-test.h"
 
 /**
  * SECTION:polkit-policy-file
@@ -96,13 +97,13 @@ typedef struct {
         PolKitResult defaults_allow_any;
         PolKitResult defaults_allow_inactive;
         PolKitResult defaults_allow_active;
-
+        
         PolKitPolicyFile *pf;
 
         polkit_bool_t load_descriptions;
 
-        GHashTable *policy_descriptions;
-        GHashTable *policy_messages;
+        PolKitHash *policy_descriptions;
+        PolKitHash *policy_messages;
 
         char *policy_description_nolang;
         char *policy_message_nolang;
@@ -115,26 +116,28 @@ typedef struct {
 
         char *annotate_key;
         PolKitHash *annotations;
+
+        polkit_bool_t is_oom;
 } ParserData;
 
 static void
 pd_unref_action_data (ParserData *pd)
 {
-        g_free (pd->action_id);
+        p_free (pd->action_id);
         pd->action_id = NULL;
-        g_free (pd->policy_description_nolang);
+        p_free (pd->policy_description_nolang);
         pd->policy_description_nolang = NULL;
-        g_free (pd->policy_message_nolang);
+        p_free (pd->policy_message_nolang);
         pd->policy_message_nolang = NULL;
         if (pd->policy_descriptions != NULL) {
-                g_hash_table_destroy (pd->policy_descriptions);
+                polkit_hash_unref (pd->policy_descriptions);
                 pd->policy_descriptions = NULL;
         }
         if (pd->policy_messages != NULL) {
-                g_hash_table_destroy (pd->policy_messages);
+                polkit_hash_unref (pd->policy_messages);
                 pd->policy_messages = NULL;
         }
-        g_free (pd->annotate_key);
+        p_free (pd->annotate_key);
         pd->annotate_key = NULL;
         if (pd->annotations != NULL) {
                 polkit_hash_unref (pd->annotations);
@@ -170,9 +173,17 @@ _start (void *data, const char *el, const char **attr)
                                 goto error;
 
                         pd_unref_action_data (pd);
-                        pd->action_id = g_strdup (attr[1]);
-                        pd->policy_descriptions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-                        pd->policy_messages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+                        pd->action_id = p_strdup (attr[1]);
+                        if (pd->action_id == NULL)
+                                goto oom;
+                        pd->policy_descriptions = polkit_hash_new (polkit_hash_str_hash_func, 
+                                                                   polkit_hash_str_equal_func, 
+                                                                   polkit_hash_str_copy, polkit_hash_str_copy,
+                                                                   p_free, p_free);
+                        pd->policy_messages = polkit_hash_new (polkit_hash_str_hash_func, 
+                                                               polkit_hash_str_equal_func, 
+                                                               polkit_hash_str_copy, polkit_hash_str_copy,
+                                                               p_free, p_free);
 
                         /* initialize defaults */
                         pd->defaults_allow_any = POLKIT_RESULT_NO;
@@ -185,12 +196,16 @@ _start (void *data, const char *el, const char **attr)
                         state = STATE_IN_DEFAULTS;
                 } else if (strcmp (el, "description") == 0) {
                         if (num_attr == 2 && strcmp (attr[0], "xml:lang") == 0) {
-                                pd->elem_lang = g_strdup (attr[1]);
+                                pd->elem_lang = p_strdup (attr[1]);
+                                if (pd->elem_lang == NULL)
+                                        goto oom;
                         }
                         state = STATE_IN_ACTION_DESCRIPTION;
                 } else if (strcmp (el, "message") == 0) {
                         if (num_attr == 2 && strcmp (attr[0], "xml:lang") == 0) {
-                                pd->elem_lang = g_strdup (attr[1]);
+                                pd->elem_lang = p_strdup (attr[1]);
+                                if (pd->elem_lang == NULL)
+                                        goto oom;
                         }
                         state = STATE_IN_ACTION_MESSAGE;
                 } else if (strcmp (el, "annotate") == 0) {
@@ -198,8 +213,10 @@ _start (void *data, const char *el, const char **attr)
                                 goto error;
                         state = STATE_IN_ANNOTATE;
 
-                        g_free (pd->annotate_key);
-                        pd->annotate_key = g_strdup (attr[1]);
+                        p_free (pd->annotate_key);
+                        pd->annotate_key = p_strdup (attr[1]);
+                        if (pd->annotate_key == NULL)
+                                goto oom;
                 }
                 break;
         case STATE_IN_ACTION_DESCRIPTION:
@@ -238,6 +255,8 @@ _start (void *data, const char *el, const char **attr)
         pd->state_stack[pd->stack_depth] = pd->state;
         pd->stack_depth++;
         return;
+oom:
+        pd->is_oom = TRUE;
 error:
         XML_StopParser (pd->parser, FALSE);
 }
@@ -248,16 +267,21 @@ _cdata (void *data, const char *s, int len)
         char *str;
         ParserData *pd = data;
 
-        str = g_strndup (s, len);
+        str = p_strndup (s, len);
+        if (str == NULL)
+                goto oom;
+
         switch (pd->state) {
 
         case STATE_IN_ACTION_DESCRIPTION:
                 if (pd->load_descriptions) {
                         if (pd->elem_lang == NULL) {
-                                g_free (pd->policy_description_nolang);
-                                pd->policy_description_nolang = g_strdup (str);
+                                p_free (pd->policy_description_nolang);
+                                pd->policy_description_nolang = str;
+                                str = NULL;
                         } else {
-                                g_hash_table_insert (pd->policy_descriptions, g_strdup (pd->elem_lang), g_strdup (str));
+                                if (!polkit_hash_insert (pd->policy_descriptions, pd->elem_lang, str))
+                                        goto oom;
                         }
                 }
                 break;
@@ -265,10 +289,12 @@ _cdata (void *data, const char *s, int len)
         case STATE_IN_ACTION_MESSAGE:
                 if (pd->load_descriptions) {
                         if (pd->elem_lang == NULL) {
-                                g_free (pd->policy_message_nolang);
-                                pd->policy_message_nolang = g_strdup (str);
+                                p_free (pd->policy_message_nolang);
+                                pd->policy_message_nolang = str;
+                                str = NULL;
                         } else {
-                                g_hash_table_insert (pd->policy_messages, g_strdup (pd->elem_lang), g_strdup (str));
+                                if (!polkit_hash_insert (pd->policy_messages, pd->elem_lang, str))
+                                        goto oom;
                         }
                 }
                 break;
@@ -290,19 +316,24 @@ _cdata (void *data, const char *s, int len)
                 if (pd->annotations == NULL) {
                         pd->annotations = polkit_hash_new (polkit_hash_str_hash_func, 
                                                            polkit_hash_str_equal_func, 
-                                                           p_free, 
-                                                           p_free);
+                                                           polkit_hash_str_copy, polkit_hash_str_copy,
+                                                           p_free, p_free);
+                        if (pd->annotations == NULL)
+                                goto oom;
                 }
-                polkit_hash_insert (pd->annotations, p_strdup (pd->annotate_key), p_strdup (str));
+                if (!polkit_hash_insert (pd->annotations, pd->annotate_key, str))
+                        goto oom;
                 break;
 
         default:
                 break;
         }
-        g_free (str);
+        p_free (str);
         return;
+oom:
+        pd->is_oom = TRUE;
 error:
-        g_free (str);
+        p_free (str);
         XML_StopParser (pd->parser, FALSE);
 }
 
@@ -318,10 +349,10 @@ error:
  * Returns: the localized string to use
  */
 static const char *
-_localize (GHashTable *translations, const char *untranslated, const char *lang)
+_localize (PolKitHash *translations, const char *untranslated, const char *lang)
 {
         const char *result;
-        char *lang2;
+        char lang2[256];
         int n;
 
         if (lang == NULL) {
@@ -330,20 +361,19 @@ _localize (GHashTable *translations, const char *untranslated, const char *lang)
         }
 
         /* first see if we have the translation */
-        result = g_hash_table_lookup (translations, lang);
+        result = (const char *) polkit_hash_lookup (translations, (void *) lang, NULL);
         if (result != NULL)
                 goto out;
 
         /* we could have a translation for 'da' but lang=='da_DK'; cut off the last part and try again */
-        lang2 = g_strdup (lang);
+        strncpy (lang2, lang, sizeof (lang2));
         for (n = 0; lang2[n] != '\0'; n++) {
                 if (lang2[n] == '_') {
                         lang2[n] = '\0';
                         break;
                 }
         }
-        result = g_hash_table_lookup (translations, lang2);
-        g_free (lang2);
+        result = (const char *) polkit_hash_lookup (translations, (void *) lang2, NULL);
         if (result != NULL)
                 goto out;
 
@@ -358,7 +388,7 @@ _end (void *data, const char *el)
 {
         ParserData *pd = data;
 
-        g_free (pd->elem_lang);
+        p_free (pd->elem_lang);
         pd->elem_lang = NULL;
 
         switch (pd->state) {
@@ -374,6 +404,8 @@ _end (void *data, const char *el)
                                                      pd->defaults_allow_inactive,
                                                      pd->defaults_allow_active,
                                                      pd->annotations);
+                if (pfe == NULL)
+                        goto oom;
                 pd->annotations = NULL;
 
                 if (pfe == NULL)
@@ -387,10 +419,12 @@ _end (void *data, const char *el)
                         policy_message = NULL;
                 }
 
-                if (pd->load_descriptions)
-                        _polkit_policy_file_entry_set_descriptions (pfe,
-                                                                    policy_description,
-                                                                    policy_message);
+                if (pd->load_descriptions) {
+                        if (!_polkit_policy_file_entry_set_descriptions (pfe,
+                                                                         policy_description,
+                                                                         policy_message))
+                                goto oom;
+                }
 
                 pd->pf->entries = g_slist_prepend (pd->pf->entries, pfe);
                 break;
@@ -410,6 +444,8 @@ _end (void *data, const char *el)
                 pd->state = STATE_NONE;
 
         return;
+oom:
+        pd->is_oom = 1;
 error:
         XML_StopParser (pd->parser, FALSE);
 }
@@ -438,6 +474,9 @@ polkit_policy_file_new (const char *path, polkit_bool_t load_descriptions, PolKi
 
         pf = NULL;
 
+        /* clear parser data */
+        memset (&pd, 0, sizeof (ParserData));
+
         if (!g_str_has_suffix (path, ".policy")) {
                 polkit_error_set_error (error, 
                                         POLKIT_ERROR_POLICY_FILE_INVALID,
@@ -455,9 +494,6 @@ polkit_policy_file_new (const char *path, polkit_bool_t load_descriptions, PolKi
 		goto error;
         }
 
-        /* clear parser data */
-        memset (&pd, 0, sizeof (ParserData));
-
         pd.path = path;
         pd.parser = XML_ParserCreate (NULL);
         pd.stack_depth = 0;
@@ -472,7 +508,10 @@ polkit_policy_file_new (const char *path, polkit_bool_t load_descriptions, PolKi
 	XML_SetElementHandler (pd.parser, _start, _end);
 	XML_SetCharacterDataHandler (pd.parser, _cdata);
 
-        pf = g_new0 (PolKitPolicyFile, 1);
+        pf = p_new0 (PolKitPolicyFile, 1);
+        if (pf == NULL)
+                goto error;
+
         pf->refcount = 1;
 
         /* init parser data */
@@ -482,7 +521,9 @@ polkit_policy_file_new (const char *path, polkit_bool_t load_descriptions, PolKi
         lang = getenv ("LANG");
         if (lang != NULL) {
                 int n;
-                pd.lang = g_strdup (lang);
+                pd.lang = p_strdup (lang);
+                if (pd.lang == NULL)
+                        goto error;
                 for (n = 0; pd.lang[n] != '\0'; n++) {
                         if (pd.lang[n] == '.') {
                                 pd.lang[n] = '\0';
@@ -494,18 +535,23 @@ polkit_policy_file_new (const char *path, polkit_bool_t load_descriptions, PolKi
         xml_res = XML_Parse (pd.parser, buf, buflen, 1);
 
 	if (xml_res == 0) {
-                polkit_error_set_error (error, POLKIT_ERROR_POLICY_FILE_INVALID,
-                                        "%s:%d: parse error: %s",
-                                        path, 
-                                        (int) XML_GetCurrentLineNumber (pd.parser),
-                                        XML_ErrorString (XML_GetErrorCode (pd.parser)));
-
+                if (pd.is_oom) {
+                        polkit_error_set_error (error, POLKIT_ERROR_OUT_OF_MEMORY,
+                                                "Out of memory parsing %s",
+                                                path);
+                } else {
+                        polkit_error_set_error (error, POLKIT_ERROR_POLICY_FILE_INVALID,
+                                                "%s:%d: parse error: %s",
+                                                path, 
+                                                (int) XML_GetCurrentLineNumber (pd.parser),
+                                                XML_ErrorString (XML_GetErrorCode (pd.parser)));
+                }
 		XML_ParserFree (pd.parser);
-		g_free (buf);
+		p_free (buf);
 		goto error;
 	}
 	XML_ParserFree (pd.parser);
-	g_free (buf);
+	p_free (buf);
         pd_unref_action_data (&pd);
         return pf;
 error:
@@ -552,7 +598,7 @@ polkit_policy_file_unref (PolKitPolicyFile *policy_file)
         }
         if (policy_file->entries != NULL)
                 g_slist_free (policy_file->entries);
-        g_free (policy_file);
+        p_free (policy_file);
 }
 
 /**
@@ -565,8 +611,8 @@ polkit_policy_file_unref (PolKitPolicyFile *policy_file)
  **/
 void
 polkit_policy_file_entry_foreach (PolKitPolicyFile                 *policy_file,
-                                     PolKitPolicyFileEntryForeachFunc  cb,
-                                     void                              *user_data)
+                                  PolKitPolicyFileEntryForeachFunc  cb,
+                                  void                              *user_data)
 {
         GSList *i;
 
@@ -578,3 +624,39 @@ polkit_policy_file_entry_foreach (PolKitPolicyFile                 *policy_file,
                 cb (policy_file, pfe, user_data);
         }
 }
+
+#ifdef POLKIT_BUILD_TESTS
+
+#define TEST_DATA_DIR "/home/davidz/Hacking/PolicyKit/test/"
+
+static polkit_bool_t
+_run_test (void)
+{
+        PolKitPolicyFile *pf;
+        PolKitError *error;
+
+        error = NULL;
+        g_assert (polkit_policy_file_new (TEST_DATA_DIR "bad.extension", TRUE, &error) == NULL);
+        g_assert (polkit_error_get_error_code (error) == POLKIT_ERROR_OUT_OF_MEMORY ||
+                  polkit_error_get_error_code (error) == POLKIT_ERROR_POLICY_FILE_INVALID);
+        polkit_error_free (error);
+        error = NULL;
+
+        if ((pf = polkit_policy_file_new (TEST_DATA_DIR "test-valid-1.policy", TRUE, NULL)) == NULL)
+                goto oom;
+
+oom:
+        if (pf != NULL)
+                polkit_policy_file_unref (pf);
+
+        return TRUE;
+}
+
+PolKitTest _test_policy_file = {
+        "polkit_policy_file",
+        NULL,
+        NULL,
+        _run_test
+};
+
+#endif /* POLKIT_BUILD_TESTS */
diff --git a/polkit/polkit-test.c b/polkit/polkit-test.c
index df6a6dd..afc54d3 100644
--- a/polkit/polkit-test.c
+++ b/polkit/polkit-test.c
@@ -32,6 +32,7 @@
 #define MAX_TESTS 64
 
 static PolKitTest *tests[] = {
+        &_test_hash,
         &_test_action,
         &_test_error,
         &_test_result,
@@ -40,7 +41,7 @@ static PolKitTest *tests[] = {
         &_test_caller,
         &_test_policy_default,
         &_test_policy_file_entry,
-        &_test_hash,
+        &_test_policy_file,
 };
 
 int 
diff --git a/polkit/polkit-test.h b/polkit/polkit-test.h
index cf85714..651c5f5 100644
--- a/polkit/polkit-test.h
+++ b/polkit/polkit-test.h
@@ -59,6 +59,7 @@ extern PolKitTest _test_caller;
 extern PolKitTest _test_policy_default;
 extern PolKitTest _test_policy_file_entry;
 extern PolKitTest _test_hash;
+extern PolKitTest _test_policy_file;
 
 POLKIT_END_DECLS
 


More information about the hal-commit mailing list