PolKitHashFunc hash_func;
PolKitEqualFunc key_equal_func;
+ PolKitCopyFunc key_copy_func;
+ PolKitCopyFunc value_copy_func;
PolKitFreeFunc key_destroy_func;
PolKitFreeFunc value_destroy_func;
};
* 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
*
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)
{
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;
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;
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;
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;
}
/**
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
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;
/* 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;
}
}
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);
}
/* 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)) {
#include "polkit-policy-file-entry.h"
#include "polkit-debug.h"
#include "polkit-private.h"
+#include "polkit-test.h"
/**
* SECTION:polkit-policy-file
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;
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);
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;
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) {
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:
pd->state_stack[pd->stack_depth] = pd->state;
pd->stack_depth++;
return;
+oom:
+ pd->is_oom = TRUE;
error:
XML_StopParser (pd->parser, FALSE);
}
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;
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;
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);
}
* 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) {
}
/* 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;
{
ParserData *pd = data;
- g_free (pd->elem_lang);
+ p_free (pd->elem_lang);
pd->elem_lang = NULL;
switch (pd->state) {
pd->defaults_allow_inactive,
pd->defaults_allow_active,
pd->annotations);
+ if (pfe == NULL)
+ goto oom;
pd->annotations = NULL;
if (pfe == NULL)
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;
pd->state = STATE_NONE;
return;
+oom:
+ pd->is_oom = 1;
error:
XML_StopParser (pd->parser, FALSE);
}
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,
goto error;
}
- /* clear parser data */
- memset (&pd, 0, sizeof (ParserData));
-
pd.path = path;
pd.parser = XML_ParserCreate (NULL);
pd.stack_depth = 0;
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 */
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';
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:
}
if (policy_file->entries != NULL)
g_slist_free (policy_file->entries);
- g_free (policy_file);
+ p_free (policy_file);
}
/**
**/
void
polkit_policy_file_entry_foreach (PolKitPolicyFile *policy_file,
- PolKitPolicyFileEntryForeachFunc cb,
- void *user_data)
+ PolKitPolicyFileEntryForeachFunc cb,
+ void *user_data)
{
GSList *i;
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 */