summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-08-18 13:17:16 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-08-18 13:17:16 +0100
commita22ea751b62b7be2f879a77c71588d1b5aa2f643 (patch)
tree2d3268b4e3093ba51f3a6e99aff467f7453daa2e /contrib
parentf4e5deb129c8e9a50175af83966e9c2f63c05cff (diff)
downloadrspamd-a22ea751b62b7be2f879a77c71588d1b5aa2f643.tar.gz
rspamd-a22ea751b62b7be2f879a77c71588d1b5aa2f643.zip
Update libucl and use UCL_RANDOM_FUNCTION.
Diffstat (limited to 'contrib')
-rw-r--r--contrib/libucl/ucl.h43
-rw-r--r--contrib/libucl/ucl_hash.c15
-rw-r--r--contrib/libucl/ucl_internal.h17
-rw-r--r--contrib/libucl/ucl_parser.c57
-rw-r--r--contrib/libucl/ucl_util.c50
5 files changed, 168 insertions, 14 deletions
diff --git a/contrib/libucl/ucl.h b/contrib/libucl/ucl.h
index 4d417eebe..2e0183671 100644
--- a/contrib/libucl/ucl.h
+++ b/contrib/libucl/ucl.h
@@ -176,12 +176,13 @@ typedef enum ucl_string_flags {
* Basic flags for an object
*/
typedef enum ucl_object_flags {
- UCL_OBJECT_ALLOCATED_KEY = 0x1, /**< An object has key allocated internally */
- UCL_OBJECT_ALLOCATED_VALUE = 0x2, /**< An object has a string value allocated internally */
- UCL_OBJECT_NEED_KEY_ESCAPE = 0x4, /**< The key of an object need to be escaped on output */
- UCL_OBJECT_EPHEMERAL = 0x8, /**< Temporary object that does not need to be freed really */
- UCL_OBJECT_MULTILINE = 0x10, /**< String should be displayed as multiline string */
- UCL_OBJECT_MULTIVALUE = 0x20 /**< Object is a key with multiple values */
+ UCL_OBJECT_ALLOCATED_KEY = (1 << 0), /**< An object has key allocated internally */
+ UCL_OBJECT_ALLOCATED_VALUE = (1 << 1), /**< An object has a string value allocated internally */
+ UCL_OBJECT_NEED_KEY_ESCAPE = (1 << 2), /**< The key of an object need to be escaped on output */
+ UCL_OBJECT_EPHEMERAL = (1 << 3), /**< Temporary object that does not need to be freed really */
+ UCL_OBJECT_MULTILINE = (1 << 4), /**< String should be displayed as multiline string */
+ UCL_OBJECT_MULTIVALUE = (1 << 5), /**< Object is a key with multiple values */
+ UCL_OBJECT_INHERITED = (1 << 6) /**< Object has been inherited from another */
} ucl_object_flags_t;
/**
@@ -805,6 +806,21 @@ typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len,
const ucl_object_t *arguments,
void* ud);
+/**
+ * Context dependent macro handler for a parser
+ * @param data the content of macro
+ * @param len the length of content
+ * @param arguments arguments object
+ * @param context previously parsed context
+ * @param ud opaque user data
+ * @param err error pointer
+ * @return true if macro has been parsed
+ */
+typedef bool (*ucl_context_macro_handler) (const unsigned char *data, size_t len,
+ const ucl_object_t *arguments,
+ const ucl_object_t *context,
+ void* ud);
+
/* Opaque parser */
struct ucl_parser;
@@ -831,10 +847,23 @@ UCL_EXTERN bool ucl_parser_set_default_priority (struct ucl_parser *parser,
* @param handler handler (it is called immediately after macro is parsed)
* @param ud opaque user data for a handler
*/
-UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
+UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser,
+ const char *macro,
ucl_macro_handler handler, void* ud);
/**
+ * Register new context dependent handler for a macro
+ * @param parser parser object
+ * @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
+ */
+UCL_EXTERN void ucl_parser_register_context_macro (struct ucl_parser *parser,
+ const char *macro,
+ ucl_context_macro_handler handler,
+ void* ud);
+
+/**
* Handler to detect unregistered variables
* @param data variable data
* @param len length of variable
diff --git a/contrib/libucl/ucl_hash.c b/contrib/libucl/ucl_hash.c
index 183eac84f..7de8196fa 100644
--- a/contrib/libucl/ucl_hash.c
+++ b/contrib/libucl/ucl_hash.c
@@ -46,8 +46,12 @@ ucl_hash_seed (void)
static uint64_t seed;
if (seed == 0) {
+#ifdef UCL_RANDOM_FUNCTION
+ seed = UCL_RANDOM_FUNCTION;
+#else
/* Not very random but can be useful for our purposes */
seed = time (NULL);
+#endif
}
return seed;
@@ -88,7 +92,14 @@ static const unsigned char lc_map[256] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
-#if (defined(WORD_BIT) && WORD_BIT == 64) || (defined(__WORDSIZE) && __WORDSIZE == 64)
+#if (defined(WORD_BIT) && WORD_BIT == 64) || \
+ (defined(__WORDSIZE) && __WORDSIZE == 64) || \
+ defined(__x86_64__) || \
+ defined(__amd64__)
+#define UCL64_BIT_HASH 1
+#endif
+
+#ifdef UCL64_BIT_HASH
static inline uint32_t
ucl_hash_func (const ucl_object_t *o)
{
@@ -115,7 +126,7 @@ ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt, 1,
ucl_hash_func, ucl_hash_equal)
-#if (defined(WORD_BIT) && WORD_BIT == 64) || (defined(__WORDSIZE) && __WORDSIZE == 64)
+#ifdef UCL64_BIT_HASH
static inline uint32_t
ucl_hash_caseless_func (const ucl_object_t *o)
{
diff --git a/contrib/libucl/ucl_internal.h b/contrib/libucl/ucl_internal.h
index fe926dbaa..885e8c57f 100644
--- a/contrib/libucl/ucl_internal.h
+++ b/contrib/libucl/ucl_internal.h
@@ -145,8 +145,12 @@ enum ucl_character_type {
struct ucl_macro {
char *name;
- ucl_macro_handler handler;
+ union {
+ ucl_macro_handler handler;
+ ucl_context_macro_handler context_handler;
+ } h;
void* ud;
+ bool is_context;
UT_hash_handle hh;
};
@@ -274,6 +278,17 @@ bool ucl_priority_handler (const unsigned char *data, size_t len,
*/
bool ucl_load_handler (const unsigned char *data, size_t len,
const ucl_object_t *args, void* ud);
+/**
+ * Handle inherit macro
+ * @param data include data
+ * @param len length of data
+ * @param args UCL object representing arguments to the macro
+ * @param ctx the current context object
+ * @param ud user data
+ * @return
+ */
+bool ucl_inherit_handler (const unsigned char *data, size_t len,
+ const ucl_object_t *args, const ucl_object_t *ctx, void* ud);
size_t ucl_strlcpy (char *dst, const char *src, size_t siz);
size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz);
diff --git a/contrib/libucl/ucl_parser.c b/contrib/libucl/ucl_parser.c
index 8f177938c..03935d9d0 100644
--- a/contrib/libucl/ucl_parser.c
+++ b/contrib/libucl/ucl_parser.c
@@ -1226,6 +1226,12 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk,
*/
unsigned priold = ucl_object_get_priority (tobj),
prinew = ucl_object_get_priority (nobj);
+
+ /* Special case for inherited objects */
+ if (tobj->flags & UCL_OBJECT_INHERITED) {
+ prinew = priold + 1;
+ }
+
if (priold == prinew) {
ucl_parser_append_elt (parser, container, tobj, nobj);
}
@@ -2066,12 +2072,29 @@ ucl_state_machine (struct ucl_parser *parser)
macro_start, macro_len);
parser->state = parser->prev_state;
if (macro_escaped == NULL) {
- ret = macro->handler (macro_start, macro_len, macro_args,
- macro->ud);
+ if (macro->is_context) {
+ ret = macro->h.context_handler (macro_start, macro_len,
+ macro_args,
+ parser->top_obj,
+ macro->ud);
+ }
+ else {
+ ret = macro->h.handler (macro_start, macro_len, macro_args,
+ macro->ud);
+ }
}
else {
- ret = macro->handler (macro_escaped, macro_len, macro_args,
+ if (macro->is_context) {
+ ret = macro->h.context_handler (macro_escaped, macro_len,
+ macro_args,
+ parser->top_obj,
+ macro->ud);
+ }
+ else {
+ ret = macro->h.handler (macro_escaped, macro_len, macro_args,
macro->ud);
+ }
+
UCL_FREE (macro_len + 1, macro_escaped);
}
@@ -2116,6 +2139,7 @@ ucl_parser_new (int flags)
ucl_parser_register_macro (new, "includes", ucl_includes_handler, new);
ucl_parser_register_macro (new, "priority", ucl_priority_handler, new);
ucl_parser_register_macro (new, "load", ucl_load_handler, new);
+ ucl_parser_register_context_macro (new, "inherit", ucl_inherit_handler, new);
new->flags = flags;
new->includepaths = NULL;
@@ -2147,14 +2171,39 @@ ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
if (macro == NULL || handler == NULL) {
return;
}
+
+ new = UCL_ALLOC (sizeof (struct ucl_macro));
+ if (new == NULL) {
+ return;
+ }
+
+ memset (new, 0, sizeof (struct ucl_macro));
+ new->h.handler = handler;
+ new->name = strdup (macro);
+ new->ud = ud;
+ HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
+}
+
+void
+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;
+ }
+
new = UCL_ALLOC (sizeof (struct ucl_macro));
if (new == NULL) {
return;
}
+
memset (new, 0, sizeof (struct ucl_macro));
- new->handler = handler;
+ new->h.context_handler = handler;
new->name = strdup (macro);
new->ud = ud;
+ new->is_context = true;
HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
}
diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c
index bdac1d214..7833e1f1c 100644
--- a/contrib/libucl/ucl_util.c
+++ b/contrib/libucl/ucl_util.c
@@ -1579,6 +1579,56 @@ ucl_load_handler (const unsigned char *data, size_t len,
}
bool
+ucl_inherit_handler (const unsigned char *data, size_t len,
+ const ucl_object_t *args, const ucl_object_t *ctx, void* ud)
+{
+ const ucl_object_t *parent, *cur;
+ ucl_object_t *target, *copy;
+ ucl_object_iter_t it = NULL;
+ bool replace = false;
+ struct ucl_parser *parser = ud;
+
+ parent = ucl_object_find_keyl (ctx, data, len);
+
+ /* Some sanity checks */
+ if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) {
+ ucl_create_err (&parser->err, "Unable to find inherited object %*.s",
+ (int)len, data);
+ return false;
+ }
+
+ if (parser->stack == NULL || parser->stack->obj == NULL ||
+ ucl_object_type (parser->stack->obj) != UCL_OBJECT) {
+ ucl_create_err (&parser->err, "Invalid inherit context");
+ return false;
+ }
+
+ target = parser->stack->obj;
+
+ if (args && (cur = ucl_object_find_key (args, "replace")) != NULL) {
+ replace = ucl_object_toboolean (cur);
+ }
+
+ while ((cur = ucl_iterate_object (parent, &it, true))) {
+ /* We do not replace existing keys */
+ if (!replace && ucl_object_find_keyl (target, cur->key, cur->keylen)) {
+ continue;
+ }
+
+ copy = ucl_object_copy (cur);
+
+ if (!replace) {
+ copy->flags |= UCL_OBJECT_INHERITED;
+ }
+
+ ucl_object_insert_key (target, copy, copy->key,
+ copy->keylen, false);
+ }
+
+ return true;
+}
+
+bool
ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
{
char realbuf[PATH_MAX], *curdir;