commit 24d8527: [Minor] Merge OOM fixes from libucl
Vsevolod Stakhov
vsevolod at highsecure.ru
Thu Apr 25 11:35:16 UTC 2019
Author: Vsevolod Stakhov
Date: 2019-04-25 12:13:09 +0100
URL: https://github.com/rspamd/rspamd/commit/24d852704f94f74caf96ddb512ae2fc7e6129c4b
[Minor] Merge OOM fixes from libucl
---
contrib/libucl/kvec.h | 80 +++++++++++++++++++++++----
contrib/libucl/ucl.h | 25 +++++++--
contrib/libucl/ucl_hash.c | 58 ++++++++++++-------
contrib/libucl/ucl_hash.h | 14 ++++-
contrib/libucl/ucl_internal.h | 18 +++++-
contrib/libucl/ucl_parser.c | 126 +++++++++++++++++++++++-------------------
contrib/libucl/ucl_util.c | 48 ++++++++++++----
7 files changed, 259 insertions(+), 110 deletions(-)
diff --git a/contrib/libucl/kvec.h b/contrib/libucl/kvec.h
index b5cce8508..ce6a53640 100644
--- a/contrib/libucl/kvec.h
+++ b/contrib/libucl/kvec.h
@@ -30,11 +30,13 @@
int main() {
kvec_t(int) array;
kv_init(array);
- kv_push(int, array, 10); // append
+ kv_push_safe(int, array, 10, e0); // append
kv_a(int, array, 20) = 5; // dynamic
kv_A(array, 20) = 4; // static
kv_destroy(array);
return 0;
+e0:
+ return 1;
}
*/
@@ -60,8 +62,71 @@ int main() {
#define kv_size(v) ((v).n)
#define kv_max(v) ((v).m)
-#define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m))
+#define kv_resize_safe(type, v, s, el) do { \
+ type *_tp = (type*)realloc((v).a, sizeof(type) * (s)); \
+ if (_tp == NULL) { \
+ goto el; \
+ } else { \
+ (v).a = _tp; \
+ (v).m = (s); \
+ } \
+ } while (0)
+
#define kv_grow_factor 1.5
+#define kv_grow_safe(type, v, el) do { \
+ size_t _ts = ((v).m > 1 ? (v).m * kv_grow_factor : 2); \
+ type *_tp = (type*)realloc((v).a, sizeof(type) * _ts); \
+ if (_tp == NULL) { \
+ goto el; \
+ } else { \
+ (v).a = _tp; \
+ (v).m = _ts; \
+ } \
+ } while (0)
+
+#define kv_copy_safe(type, v1, v0, el) do { \
+ if ((v1).m < (v0).n) kv_resize_safe(type, v1, (v0).n, el); \
+ (v1).n = (v0).n; \
+ memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \
+ } while (0)
+
+#define kv_push_safe(type, v, x, el) do { \
+ if ((v).n == (v).m) { \
+ kv_grow_safe(type, v, el); \
+ } \
+ (v).a[(v).n++] = (x); \
+ } while (0)
+
+#define kv_prepend_safe(type, v, x, el) do { \
+ if ((v).n == (v).m) { \
+ kv_grow_safe(type, v, el); \
+ } \
+ memmove((v).a + 1, (v).a, sizeof(type) * (v).n); \
+ (v).a[0] = (x); \
+ (v).n ++; \
+ } while (0)
+
+#define kv_concat_safe(type, v1, v0, el) do { \
+ if ((v1).m < (v0).n + (v1).n) \
+ kv_resize_safe(type, v1, (v0).n + (v1).n, el); \
+ memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * (v0).n); \
+ (v1).n = (v0).n + (v1).n; \
+ } while (0)
+
+#define kv_del(type, v, i) do { \
+ if ((i) < (v).n) { \
+ memmove((v).a + (i), (v).a + ((i) + 1), sizeof(type) * ((v).n - (i) - 1)); \
+ (v).n --; \
+ } \
+} while (0)
+
+/*
+ * Old (ENOMEM-unsafe) version of kv_xxx macros. Compat-only, not for use in
+ * the new library code.
+ */
+
+#define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m))
+
#define kv_grow(type, v) ((v).m = ((v).m > 1 ? (v).m * kv_grow_factor : 2), \
(v).a = (type*)realloc((v).a, sizeof(type) * (v).m))
@@ -89,15 +154,8 @@ int main() {
#define kv_concat(type, v1, v0) do { \
if ((v1).m < (v0).n + (v1).n) kv_resize(type, v1, (v0).n + (v1).n); \
- memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * ((v0).n + (v1).n)); \
+ memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * (v0).n); \
(v1).n = (v0).n + (v1).n; \
} while (0)
-#define kv_del(type, v, i) do { \
- if ((i) < (v).n) { \
- memmove((v).a + (i), (v).a + ((i) + 1), sizeof(type) * ((v).n - (i) - 1)); \
- (v).n --; \
- } \
-} while (0)
-
-#endif
+#endif /* AC_KVEC_H */
diff --git a/contrib/libucl/ucl.h b/contrib/libucl/ucl.h
index 482812d46..01542d3c7 100644
--- a/contrib/libucl/ucl.h
+++ b/contrib/libucl/ucl.h
@@ -469,8 +469,9 @@ UCL_EXTERN bool ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *e
* Reserve space in ucl array or object for `elt` elements
* @param obj object to reserve
* @param reserved size to reserve in an object
+ * @return 0 on success, -1 on failure (i.e. ENOMEM)
*/
-UCL_EXTERN void ucl_object_reserve (ucl_object_t *obj, size_t reserved);
+UCL_EXTERN bool ucl_object_reserve (ucl_object_t *obj, size_t reserved);
/**
* Append an element to the end of array object
@@ -825,11 +826,14 @@ typedef void* ucl_object_iter_t;
* @param iter opaque iterator, must be set to NULL on the first call:
* ucl_object_iter_t it = NULL;
* while ((cur = ucl_iterate_object (obj, &it)) != NULL) ...
+ * @param ep pointer record exception (such as ENOMEM), could be NULL
* @return the next object or NULL
*/
-UCL_EXTERN const ucl_object_t* ucl_object_iterate (const ucl_object_t *obj,
- ucl_object_iter_t *iter, bool expand_values);
+UCL_EXTERN const ucl_object_t* ucl_object_iterate_with_error (const ucl_object_t *obj,
+ ucl_object_iter_t *iter, bool expand_values, int *ep);
+
#define ucl_iterate_object ucl_object_iterate
+#define ucl_object_iterate(ob, it, ev) ucl_object_iterate_with_error((ob), (it), (ev), NULL)
/**
* Create new safe iterator for the specified object
@@ -838,6 +842,15 @@ UCL_EXTERN const ucl_object_t* ucl_object_iterate (const ucl_object_t *obj,
*/
UCL_EXTERN ucl_object_iter_t ucl_object_iterate_new (const ucl_object_t *obj)
UCL_WARN_UNUSED_RESULT;
+/**
+ * Check safe iterator object after performing some operations on it
+ * (such as ucl_object_iterate_safe()) to see if operation has encountered
+ * fatal exception while performing that operation (e.g. ENOMEM).
+ * @param iter opaque iterator
+ * @return true if exception has occured, false otherwise
+ */
+UCL_EXTERN bool ucl_object_iter_chk_excpn(ucl_object_iter_t *it);
+
/**
* Reset initialized iterator to a new object
* @param obj new object to iterate
@@ -951,8 +964,9 @@ UCL_EXTERN int ucl_parser_get_default_priority (struct ucl_parser *parser);
* @param macro macro name (without leading dot)
* @param handler handler (it is called immediately after macro is parsed)
* @param ud opaque user data for a handler
+ * @return true on success, false on failure (i.e. ENOMEM)
*/
-UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser,
+UCL_EXTERN bool ucl_parser_register_macro (struct ucl_parser *parser,
const char *macro,
ucl_macro_handler handler, void* ud);
@@ -962,8 +976,9 @@ UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser,
* @param macro macro name (without leading dot)
* @param handler handler (it is called immediately after macro is parsed)
* @param ud opaque user data for a handler
+ * @return true on success, false on failure (i.e. ENOMEM)
*/
-UCL_EXTERN void ucl_parser_register_context_macro (struct ucl_parser *parser,
+UCL_EXTERN bool ucl_parser_register_context_macro (struct ucl_parser *parser,
const char *macro,
ucl_context_macro_handler handler,
void* ud);
diff --git a/contrib/libucl/ucl_hash.c b/contrib/libucl/ucl_hash.c
index 628980d28..6594b2557 100644
--- a/contrib/libucl/ucl_hash.c
+++ b/contrib/libucl/ucl_hash.c
@@ -147,17 +147,21 @@ ucl_hash_create (bool ignore_case)
new = UCL_ALLOC (sizeof (ucl_hash_t));
if (new != NULL) {
+ void *h;
kv_init (new->ar);
new->caseless = ignore_case;
if (ignore_case) {
- khash_t(ucl_hash_caseless_node) *h = kh_init (ucl_hash_caseless_node);
- new->hash = (void *)h;
+ h = (void *)kh_init (ucl_hash_caseless_node);
}
else {
- khash_t(ucl_hash_node) *h = kh_init (ucl_hash_node);
- new->hash = (void *)h;
+ h = (void *)kh_init (ucl_hash_node);
}
+ if (h == NULL) {
+ UCL_FREE (sizeof (ucl_hash_t), new);
+ return NULL;
+ }
+ new->hash = h;
}
return new;
}
@@ -190,12 +194,12 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
- hashlin->hash;
+ hashlin->hash;
kh_destroy (ucl_hash_caseless_node, h);
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
- hashlin->hash;
+ hashlin->hash;
kh_destroy (ucl_hash_node, h);
}
@@ -203,16 +207,16 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
UCL_FREE (sizeof (*hashlin), hashlin);
}
-void
+bool
ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
- const char *key, unsigned keylen)
+ const char *key, unsigned keylen)
{
khiter_t k;
int ret;
struct ucl_hash_elt *elt;
if (hashlin == NULL) {
- return;
+ return false;
}
if (hashlin->caseless) {
@@ -221,7 +225,7 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
k = kh_put (ucl_hash_caseless_node, h, obj, &ret);
if (ret > 0) {
elt = &kh_value (h, k);
- kv_push (const ucl_object_t *, hashlin->ar, obj);
+ kv_push_safe (const ucl_object_t *, hashlin->ar, obj, e0);
elt->obj = obj;
elt->ar_idx = kv_size (hashlin->ar) - 1;
}
@@ -232,15 +236,20 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
k = kh_put (ucl_hash_node, h, obj, &ret);
if (ret > 0) {
elt = &kh_value (h, k);
- kv_push (const ucl_object_t *, hashlin->ar, obj);
+ kv_push_safe (const ucl_object_t *, hashlin->ar, obj, e0);
elt->obj = obj;
elt->ar_idx = kv_size (hashlin->ar) - 1;
+ } else if (ret < 0) {
+ goto e0;
}
}
+ return true;
+ e0:
+ return false;
}
void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
- const ucl_object_t *new)
+ const ucl_object_t *new)
{
khiter_t k;
int ret;
@@ -285,13 +294,16 @@ struct ucl_hash_real_iter {
const ucl_object_t **end;
};
+#define UHI_SETERR(ep, ern) {if (ep != NULL) *ep = (ern);}
+
const void*
-ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
+ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
{
struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(*iter);
const ucl_object_t *ret = NULL;
if (hashlin == NULL) {
+ UHI_SETERR(ep, EINVAL);
return NULL;
}
@@ -299,6 +311,7 @@ ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
it = UCL_ALLOC (sizeof (*it));
if (it == NULL) {
+ UHI_SETERR(ep, ENOMEM);
return NULL;
}
@@ -306,6 +319,7 @@ ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
it->end = it->cur + hashlin->ar.n;
}
+ UHI_SETERR(ep, 0);
if (it->cur < it->end) {
ret = *it->cur++;
}
@@ -346,7 +360,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
- hashlin->hash;
+ hashlin->hash;
k = kh_get (ucl_hash_caseless_node, h, &search);
if (k != kh_end (h)) {
@@ -356,7 +370,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
- hashlin->hash;
+ hashlin->hash;
k = kh_get (ucl_hash_node, h, &search);
if (k != kh_end (h)) {
elt = &kh_value (h, k);
@@ -380,7 +394,7 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
- hashlin->hash;
+ hashlin->hash;
k = kh_get (ucl_hash_caseless_node, h, obj);
if (k != kh_end (h)) {
@@ -398,7 +412,7 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
- hashlin->hash;
+ hashlin->hash;
k = kh_get (ucl_hash_node, h, obj);
if (k != kh_end (h)) {
elt = &kh_value (h, k);
@@ -415,14 +429,15 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
}
}
-void ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
+bool
+ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
{
if (hashlin == NULL) {
- return;
+ return false;
}
if (sz > hashlin->ar.m) {
- kv_resize (const ucl_object_t *, hashlin->ar, sz);
+ kv_resize_safe (const ucl_object_t *, hashlin->ar, sz, e0);
if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(
@@ -435,4 +450,7 @@ void ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
kh_resize (ucl_hash_node, h, sz * 2);
}
}
+ return true;
+ e0:
+ return false;
}
\ No newline at end of file
diff --git a/contrib/libucl/ucl_hash.h b/contrib/libucl/ucl_hash.h
index f474b462a..805c8efb2 100644
--- a/contrib/libucl/ucl_hash.h
+++ b/contrib/libucl/ucl_hash.h
@@ -55,8 +55,9 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func);
/**
* Inserts an element in the the hashtable.
+ * @return true on success, false on failure (i.e. ENOMEM)
*/
-void ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key,
+bool ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key,
unsigned keylen);
/**
@@ -81,9 +82,15 @@ const ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key,
* Iterate over hash table
* @param hashlin hash
* @param iter iterator (must be NULL on first iteration)
+ * @param ep pointer record exception (such as ENOMEM), could be NULL
* @return the next object
*/
-const void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter);
+const void* ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep);
+
+/**
+ * Helper macro to support older code
+ */
+#define ucl_hash_iterate(hl, ip) ucl_hash_iterate2((hl), (ip), NULL)
/**
* Check whether an iterator has next element
@@ -92,8 +99,9 @@ bool ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter);
/**
* Reserves space in hash
+ * @return true on sucess, false on failure (e.g. ENOMEM)
* @param hashlin
*/
-void ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz);
+bool ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz);
#endif
diff --git a/contrib/libucl/ucl_internal.h b/contrib/libucl/ucl_internal.h
index edf647827..a7dd6eeac 100644
--- a/contrib/libucl/ucl_internal.h
+++ b/contrib/libucl/ucl_internal.h
@@ -472,12 +472,24 @@ ucl_hash_insert_object (ucl_hash_t *hashlin,
const ucl_object_t *obj,
bool ignore_case)
{
+ ucl_hash_t *nhp;
+
if (hashlin == NULL) {
- hashlin = ucl_hash_create (ignore_case);
+ nhp = ucl_hash_create (ignore_case);
+ if (nhp == NULL) {
+ return NULL;
+ }
+ } else {
+ nhp = hashlin;
+ }
+ if (!ucl_hash_insert (nhp, obj, obj->key, obj->keylen)) {
+ if (nhp != hashlin) {
+ ucl_hash_destroy(nhp, NULL);
+ }
+ return NULL;
}
- ucl_hash_insert (hashlin, obj, obj->key, obj->keylen);
- return hashlin;
+ return nhp;
}
/**
diff --git a/contrib/libucl/ucl_parser.c b/contrib/libucl/ucl_parser.c
index 7752f6661..6a53fe805 100644
--- a/contrib/libucl/ucl_parser.c
+++ b/contrib/libucl/ucl_parser.c
@@ -634,70 +634,51 @@ ucl_parser_add_container (ucl_object_t *obj, struct ucl_parser *parser,
bool is_array, uint32_t level, bool has_obrace)
{
struct ucl_stack *st;
- bool need_free = false;
-
- if (!is_array) {
- if (obj == NULL) {
- obj = ucl_object_new_full (UCL_OBJECT, parser->chunks->priority);
- need_free = true;
- }
- else {
- if (obj->type == UCL_ARRAY) {
- /* Bad combination for merge: array and object */
- ucl_set_err (parser, UCL_EMERGE,
- "cannot merge an array with an object",
- &parser->err);
-
- return NULL;
- }
+ ucl_object_t *nobj;
- obj->type = UCL_OBJECT;
+ if (obj == NULL) {
+ nobj = ucl_object_new_full (is_array ? UCL_ARRAY : UCL_OBJECT, parser->chunks->priority);
+ if (nobj == NULL) {
+ goto enomem0;
}
+ } else {
+ if (obj->type == (is_array ? UCL_OBJECT : UCL_ARRAY)) {
+ /* Bad combination for merge: array and object */
+ ucl_set_err (parser, UCL_EMERGE,
+ "cannot merge an object with an array",
+ &parser->err);
- if (obj->value.ov == NULL) {
- obj->value.ov = ucl_hash_create (parser->flags & UCL_PARSER_KEY_LOWERCASE);
+ return NULL;
}
- parser->state = UCL_STATE_KEY;
+ nobj = obj;
+ nobj->type = is_array ? UCL_ARRAY : UCL_OBJECT;
}
- else {
- if (obj == NULL) {
- obj = ucl_object_new_full (UCL_ARRAY, parser->chunks->priority);
- need_free = true;
- }
- else {
- if (obj->type == UCL_OBJECT) {
- /* Bad combination for merge: array and object */
- ucl_set_err (parser, UCL_EMERGE,
- "cannot merge an object with an array",
- &parser->err);
- return NULL;
+ if (!is_array) {
+ if (nobj->value.ov == NULL) {
+ nobj->value.ov = ucl_hash_create (parser->flags & UCL_PARSER_KEY_LOWERCASE);
+ if (nobj->value.ov == NULL) {
+ goto enomem1;
}
-
- obj->type = UCL_ARRAY;
}
+ parser->state = UCL_STATE_KEY;
+ } else {
parser->state = UCL_STATE_VALUE;
}
st = UCL_ALLOC (sizeof (struct ucl_stack));
if (st == NULL) {
- ucl_set_err (parser, UCL_EINTERNAL, "cannot allocate memory for an object",
- &parser->err);
- if (need_free) {
- ucl_object_unref (obj);
- }
-
- return NULL;
+ goto enomem1;
}
- st->obj = obj;
+ st->obj = nobj;
if (level >= UINT16_MAX) {
ucl_set_err (parser, UCL_ENESTED,
"objects are nesting too deep (over 65535 limit)",
&parser->err);
- if (need_free) {
+ if (nobj != obj) {
ucl_object_unref (obj);
}
@@ -717,9 +698,16 @@ ucl_parser_add_container (ucl_object_t *obj, struct ucl_parser *parser,
}
LL_PREPEND (parser->stack, st);
- parser->cur_obj = obj;
+ parser->cur_obj = nobj;
- return obj;
+ return nobj;
+enomem1:
+ if (nobj != obj)
+ ucl_object_unref (nobj);
+enomem0:
+ ucl_set_err (parser, UCL_EINTERNAL, "cannot allocate memory for an object",
+ &parser->err);
+ return NULL;
}
int
@@ -1194,6 +1182,9 @@ ucl_parser_process_object_element (struct ucl_parser *parser, ucl_object_t *nobj
if (tobj == NULL) {
container = ucl_hash_insert_object (container, nobj,
parser->flags & UCL_PARSER_KEY_LOWERCASE);
+ if (container == NULL) {
+ return false;
+ }
nobj->prev = nobj;
nobj->next = NULL;
parser->stack->obj->len ++;
@@ -1477,6 +1468,9 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk,
/* Create a new object */
nobj = ucl_object_new_full (UCL_NULL, parser->chunks->priority);
+ if (nobj == NULL) {
+ return false;
+ }
keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY],
&key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE,
false, false);
@@ -2672,6 +2666,11 @@ ucl_state_machine (struct ucl_parser *parser)
return true;
}
+#define UPRM_SAFE(fn, a, b, c, el) do { \
+ if (!fn(a, b, c, a)) \
+ goto el; \
+ } while (0)
+
struct ucl_parser*
ucl_parser_new (int flags)
{
@@ -2684,12 +2683,12 @@ ucl_parser_new (int flags)
memset (parser, 0, sizeof (struct ucl_parser));
- ucl_parser_register_macro (parser, "include", ucl_include_handler, parser);
- ucl_parser_register_macro (parser, "try_include", ucl_try_include_handler, parser);
- ucl_parser_register_macro (parser, "includes", ucl_includes_handler, parser);
- ucl_parser_register_macro (parser, "priority", ucl_priority_handler, parser);
- ucl_parser_register_macro (parser, "load", ucl_load_handler, parser);
- ucl_parser_register_context_macro (parser, "inherit", ucl_inherit_handler, parser);
+ UPRM_SAFE(ucl_parser_register_macro, parser, "include", ucl_include_handler, e0);
+ UPRM_SAFE(ucl_parser_register_macro, parser, "try_include", ucl_try_include_handler, e0);
+ UPRM_SAFE(ucl_parser_register_macro, parser, "includes", ucl_includes_handler, e0);
+ UPRM_SAFE(ucl_parser_register_macro, parser, "priority", ucl_priority_handler, e0);
+ UPRM_SAFE(ucl_parser_register_macro, parser, "load", ucl_load_handler, e0);
+ UPRM_SAFE(ucl_parser_register_context_macro, parser, "inherit", ucl_inherit_handler, e0);
parser->flags = flags;
parser->includepaths = NULL;
@@ -2704,6 +2703,9 @@ ucl_parser_new (int flags)
}
return parser;
+e0:
+ ucl_parser_free(parser);
+ return NULL;
}
bool
@@ -2728,49 +2730,59 @@ ucl_parser_get_default_priority (struct ucl_parser *parser)
return parser->default_priority;
}
-void
+bool
ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
ucl_macro_handler handler, void* ud)
{
struct ucl_macro *new;
if (macro == NULL || handler == NULL) {
- return;
+ return false;
}
new = UCL_ALLOC (sizeof (struct ucl_macro));
if (new == NULL) {
- return;
+ return false;
}
memset (new, 0, sizeof (struct ucl_macro));
new->h.handler = handler;
new->name = strdup (macro);
+ if (new->name == NULL) {
+ UCL_FREE (sizeof (struct ucl_macro), new);
+ return false;
+ }
new->ud = ud;
HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
+ return true;
}
-void
+bool
ucl_parser_register_context_macro (struct ucl_parser *parser, const char *macro,
ucl_context_macro_handler handler, void* ud)
{
struct ucl_macro *new;
if (macro == NULL || handler == NULL) {
- return;
+ return false;
}
new = UCL_ALLOC (sizeof (struct ucl_macro));
if (new == NULL) {
- return;
+ return false;
}
memset (new, 0, sizeof (struct ucl_macro));
new->h.context_handler = handler;
new->name = strdup (macro);
*** OUTPUT TRUNCATED, 173 LINES SKIPPED ***
More information about the Commits
mailing list