From 1be9010b73e9bbf60559fcc65ece061c67172339 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 4 Dec 2013 13:42:02 +0000 Subject: [PATCH] Sync with libucl. --- src/ucl/src/ucl_emitter.c | 49 ++++++-- src/ucl/src/ucl_hash.c | 3 + src/ucl/src/ucl_internal.h | 13 ++- src/ucl/src/ucl_parser.c | 225 ++++++++++++++++++++++++++++++------- src/ucl/src/ucl_util.c | 66 ++++++++--- src/ucl/src/xxhash.c | 2 +- 6 files changed, 284 insertions(+), 74 deletions(-) diff --git a/src/ucl/src/ucl_emitter.c b/src/ucl/src/ucl_emitter.c index c7d14dc8a..d0e62436d 100644 --- a/src/ucl/src/ucl_emitter.c +++ b/src/ucl/src/ucl_emitter.c @@ -38,6 +38,7 @@ static void ucl_elt_write_rcl (ucl_object_t *obj, UT_string *buf, unsigned int t bool start_tabs, bool is_top, bool expand_array); static void ucl_elt_write_yaml (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bool start_tabs, bool compact, bool expand_array); +static void ucl_elt_array_write_yaml (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bool start_tabs, bool is_top); /** * Add tabulation to the output buffer @@ -256,6 +257,12 @@ ucl_elt_write_json (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bool s } ucl_elt_string_write_json (obj->value.sv, obj->len, buf); break; + case UCL_NULL: + if (start_tabs) { + ucl_add_tabs (buf, tabs, compact); + } + utstring_printf (buf, "null"); + break; case UCL_OBJECT: ucl_elt_obj_write_json (obj, buf, tabs, start_tabs, compact); break; @@ -440,6 +447,12 @@ ucl_elt_write_rcl (ucl_object_t *obj, UT_string *buf, unsigned int tabs, } ucl_elt_string_write_json (obj->value.sv, obj->len, buf); break; + case UCL_NULL: + if (start_tabs) { + ucl_add_tabs (buf, tabs, false); + } + utstring_printf (buf, "null"); + break; case UCL_OBJECT: ucl_elt_obj_write_rcl (obj, buf, tabs, start_tabs, is_top); break; @@ -471,6 +484,19 @@ ucl_object_emit_rcl (ucl_object_t *obj) } +static void +ucl_obj_write_yaml (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bool start_tabs) +{ + bool is_array = (obj->next != NULL); + + if (is_array) { + ucl_elt_array_write_yaml (obj, buf, tabs, start_tabs, false); + } + else { + ucl_elt_write_yaml(obj, buf, tabs, start_tabs, false, true); + } +} + /** * Write a single object to the buffer * @param obj object to write @@ -486,25 +512,20 @@ ucl_elt_obj_write_yaml (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bo ucl_add_tabs (buf, tabs, is_top); } if (!is_top) { - utstring_append_len (buf, ": {\n", 4); + utstring_append_len (buf, "{\n", 2); } while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { ucl_add_tabs (buf, tabs + 1, is_top); - if (cur->flags & UCL_OBJECT_NEED_KEY_ESCAPE) { + if (cur->keylen > 0) { ucl_elt_string_write_json (cur->key, cur->keylen, buf); } else { - utstring_append_len (buf, cur->key, cur->keylen); - } - if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY) { - utstring_append_len (buf, " : ", 3); - } - else { - utstring_append_c (buf, ' '); + utstring_append_len (buf, "null", 4); } - ucl_elt_write_yaml (cur, buf, is_top ? tabs : tabs + 1, false, false, true); - if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY) { + utstring_append_len(buf, ": ", 2); + ucl_obj_write_yaml (cur, buf, is_top ? tabs : tabs + 1, false); + if (ucl_hash_iter_has_next(it)) { if (!is_top) { utstring_append_len (buf, ",\n", 2); } @@ -586,6 +607,12 @@ ucl_elt_write_yaml (ucl_object_t *obj, UT_string *buf, unsigned int tabs, } ucl_elt_string_write_json (obj->value.sv, obj->len, buf); break; + case UCL_NULL: + if (start_tabs) { + ucl_add_tabs (buf, tabs, false); + } + utstring_printf (buf, "null"); + break; case UCL_OBJECT: ucl_elt_obj_write_yaml (obj, buf, tabs, start_tabs, is_top); break; diff --git a/src/ucl/src/ucl_hash.c b/src/ucl/src/ucl_hash.c index d644da4f4..a3711deb8 100644 --- a/src/ucl/src/ucl_hash.c +++ b/src/ucl/src/ucl_hash.c @@ -96,6 +96,9 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen) { ucl_hash_node_t *found; + if (hashlin == NULL) { + return NULL; + } HASH_FIND (hh, hashlin->buckets, key, keylen, found); if (found) { diff --git a/src/ucl/src/ucl_internal.h b/src/ucl/src/ucl_internal.h index 21b1aa53e..78b52edbd 100644 --- a/src/ucl/src/ucl_internal.h +++ b/src/ucl/src/ucl_internal.h @@ -96,6 +96,7 @@ struct ucl_macro { struct ucl_stack { ucl_object_t *obj; struct ucl_stack *next; + int level; }; struct ucl_chunk { @@ -209,33 +210,33 @@ ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t l bool ret = false, val = false; if (len == 5) { - if (tolower (p[0]) == 'f' && strncasecmp (p, "false", 5) == 0) { + if ((p[0] == 'f' || p[0] == 'F') && strncasecmp (p, "false", 5) == 0) { ret = true; val = false; } } else if (len == 4) { - if (tolower (p[0]) == 't' && strncasecmp (p, "true", 4) == 0) { + if ((p[0] == 't' || p[0] == 'T') && strncasecmp (p, "true", 4) == 0) { ret = true; val = true; } } else if (len == 3) { - if (tolower (p[0]) == 'y' && strncasecmp (p, "yes", 3) == 0) { + if ((p[0] == 'y' || p[0] == 'Y') && strncasecmp (p, "yes", 3) == 0) { ret = true; val = true; } - if (tolower (p[0]) == 'o' && strncasecmp (p, "off", 3) == 0) { + else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "off", 3) == 0) { ret = true; val = false; } } else if (len == 2) { - if (tolower (p[0]) == 'n' && strncasecmp (p, "no", 2) == 0) { + if ((p[0] == 'n' || p[0] == 'N') && strncasecmp (p, "no", 2) == 0) { ret = true; val = false; } - else if (tolower (p[0]) == 'o' && strncasecmp (p, "on", 2) == 0) { + else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "on", 2) == 0) { ret = true; val = true; } diff --git a/src/ucl/src/ucl_parser.c b/src/ucl/src/ucl_parser.c index 2e4816874..f819edee6 100644 --- a/src/ucl/src/ucl_parser.c +++ b/src/ucl/src/ucl_parser.c @@ -90,6 +90,11 @@ ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err chunk->line, chunk->column, str, *chunk->pos); } +/** + * Skip all comments from the current pos resolving nested and multiline comments + * @param parser + * @return + */ static bool ucl_skip_comments (struct ucl_parser *parser) { @@ -233,6 +238,16 @@ ucl_lex_is_comment (const unsigned char c1, const unsigned char c2) return false; } +/** + * Check variable found + * @param parser + * @param ptr + * @param remain + * @param out_len + * @param strict + * @param found + * @return + */ static inline const char * ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t remain, size_t *out_len, bool strict, bool *found) @@ -263,6 +278,15 @@ ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t rema return ptr; } +/** + * Check for a variable in a given string + * @param parser + * @param ptr + * @param remain + * @param out_len + * @param vars_found + * @return + */ static const char * ucl_check_variable (struct ucl_parser *parser, const char *ptr, size_t remain, size_t *out_len, bool *vars_found) { @@ -309,6 +333,14 @@ ucl_check_variable (struct ucl_parser *parser, const char *ptr, size_t remain, s return ret; } +/** + * Expand a single variable + * @param parser + * @param ptr + * @param remain + * @param dest + * @return + */ static const char * ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr, size_t remain, unsigned char **dest) @@ -353,6 +385,14 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr, return ret; } +/** + * Expand variables in string + * @param parser + * @param dst + * @param src + * @param in_len + * @return + */ static ssize_t ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst, const char *src, size_t in_len) @@ -400,6 +440,18 @@ ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst, return out_len; } +/** + * Store or copy pointer to the trash stack + * @param parser parser object + * @param src src string + * @param dst destination buffer (trash stack pointer) + * @param dst_const const destination pointer (e.g. value of object) + * @param in_len input length + * @param need_unescape need to unescape source (and copy it) + * @param need_lowercase need to lowercase value (and copy) + * @param need_expand need to expand variables (and copy as well) + * @return output length (excluding \0 symbol) + */ static inline ssize_t ucl_copy_or_store_ptr (struct ucl_parser *parser, const unsigned char *src, unsigned char **dst, @@ -448,6 +500,47 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser, return ret; } +/** + * Create and append an object at the specified level + * @param parser + * @param is_array + * @param level + * @return + */ +static inline ucl_object_t * +ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_array, int level) +{ + struct ucl_stack *st; + + if (!is_array) { + if (obj == NULL) { + obj = ucl_object_typed_new (UCL_OBJECT); + } + else { + obj->type = UCL_OBJECT; + } + obj->value.ov = ucl_hash_create (); + parser->state = UCL_STATE_KEY; + } + else { + if (obj == NULL) { + obj = ucl_object_typed_new (UCL_ARRAY); + } + else { + obj->type = UCL_ARRAY; + } + parser->state = UCL_STATE_VALUE; + } + + st = UCL_ALLOC (sizeof (struct ucl_stack)); + st->obj = obj; + st->level = level; + LL_PREPEND (parser->stack, st); + parser->cur_obj = obj; + + return obj; +} + int ucl_maybe_parse_number (ucl_object_t *obj, const char *start, const char *end, const char **pos, bool allow_double, bool number_bytes) @@ -781,12 +874,13 @@ ucl_lex_json_string (struct ucl_parser *parser, * @return true if a key has been parsed */ static bool -ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk) +ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_key, bool *end_of_object) { - const unsigned char *p, *c = NULL, *end; + const unsigned char *p, *c = NULL, *end, *t; const char *key; bool got_quote = false, got_eq = false, got_semicolon = false, - need_unescape = false, ucl_escape = false, var_expand = false; + need_unescape = false, ucl_escape = false, var_expand = false, + got_content = false, got_sep = false; ucl_object_t *nobj, *tobj; ucl_hash_t *container; ssize_t keylen; @@ -811,17 +905,27 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk) } p = chunk->pos; } + else if (ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + ucl_chunk_skipc (chunk, p); + } else if (ucl_test_character (*p, UCL_CHARACTER_KEY_START)) { /* The first symbol */ c = p; ucl_chunk_skipc (chunk, p); + got_content = true; } else if (*p == '"') { /* JSON style key */ c = p + 1; got_quote = true; + got_content = true; ucl_chunk_skipc (chunk, p); } + else if (*p == '}') { + /* We have actually end of an object */ + *end_of_object = true; + return true; + } else { /* Invalid identifier */ ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", &parser->err); @@ -832,6 +936,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk) /* Parse the body of a key */ if (!got_quote) { if (ucl_test_character (*p, UCL_CHARACTER_KEY)) { + got_content = true; ucl_chunk_skipc (chunk, p); } else if (ucl_test_character (*p, UCL_CHARACTER_KEY_SEP)) { @@ -856,11 +961,14 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk) } } - if (p >= chunk->end) { + if (p >= chunk->end && got_content) { ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err); return false; } - + else if (!got_content) { + return true; + } + *end_of_object = false; /* We are now at the end of the key, need to parse the rest */ while (p < chunk->end) { if (ucl_test_character (*p, UCL_CHARACTER_WHITESPACE)) { @@ -899,11 +1007,41 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk) } } - if (p >= chunk->end) { + if (p >= chunk->end && got_content) { ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err); return false; } + got_sep = got_semicolon || got_eq; + + if (!got_sep) { + /* + * Maybe we have more keys nested, so search for termination character. + * Possible choices: + * 1) key1 key2 ... keyN [:=] value <- we treat that as error + * 2) key1 ... keyN {} or [] <- we treat that as nested objects + * 3) key1 value[;,\n] <- we treat that as linear object + */ + t = p; + *next_key = false; + while (ucl_test_character (*t, UCL_CHARACTER_WHITESPACE)) { + t ++; + } + /* Check first non-space character after a key */ + if (*t != '{' && *t != '[') { + while (t < chunk->end) { + if (*t == ',' || *t == ';' || *t == '\n' || *t == '\r') { + break; + } + else if (*t == '{' || *t == '[') { + *next_key = true; + break; + } + t ++; + } + } + } + /* Create a new object */ nobj = ucl_object_new (); keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY], @@ -1064,7 +1202,6 @@ static bool ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) { const unsigned char *p, *c; - struct ucl_stack *st; ucl_object_t *obj = NULL, *t; unsigned int stripped_spaces; int str_len; @@ -1107,27 +1244,14 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) break; case '{': /* We have a new object */ - obj->type = UCL_OBJECT; - obj->value.ov = ucl_hash_create (); - parser->state = UCL_STATE_KEY; - st = UCL_ALLOC (sizeof (struct ucl_stack)); - st->obj = obj; - LL_PREPEND (parser->stack, st); - parser->cur_obj = obj; + obj = ucl_add_parser_stack (obj, parser, false, parser->stack->level); ucl_chunk_skipc (chunk, p); return true; break; case '[': /* We have a new array */ - obj = parser->cur_obj; - obj->type = UCL_ARRAY; - - parser->state = UCL_STATE_VALUE; - st = UCL_ALLOC (sizeof (struct ucl_stack)); - st->obj = obj; - LL_PREPEND (parser->stack, st); - parser->cur_obj = obj; + obj = ucl_add_parser_stack (obj, parser, true, parser->stack->level); ucl_chunk_skipc (chunk, p); return true; @@ -1206,8 +1330,11 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) ucl_set_err (chunk, 0, "string value must not be empty", &parser->err); return false; } - - if (!ucl_maybe_parse_boolean (obj, c, str_len)) { + else if (str_len == 4 && memcmp (c, "null", 4) == 0) { + obj->len = 0; + obj->type = UCL_NULL; + } + else if (!ucl_maybe_parse_boolean (obj, c, str_len)) { obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], &obj->value.sv, str_len, false, false, var_expand)) == -1) { @@ -1238,6 +1365,7 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk) const unsigned char *p; bool got_sep = false; struct ucl_stack *st; + int last_level; p = chunk->pos; @@ -1258,16 +1386,24 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk) else if (ucl_test_character (*p, UCL_CHARACTER_VALUE_END)) { if (*p == '}' || *p == ']') { if (parser->stack == NULL) { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected } detected", &parser->err); + ucl_set_err (chunk, UCL_ESYNTAX, "end of array or object detected without corresponding start", &parser->err); return false; } if ((*p == '}' && parser->stack->obj->type == UCL_OBJECT) || (*p == ']' && parser->stack->obj->type == UCL_ARRAY)) { - /* Pop object from a stack */ + /* Pop all nested objects from a stack */ st = parser->stack; + last_level = st->level; parser->stack = st->next; UCL_FREE (sizeof (struct ucl_stack), st); + + while (parser->stack != NULL && last_level > 0 && parser->stack->level == last_level) { + st = parser->stack; + parser->stack = st->next; + last_level = st->level; + UCL_FREE (sizeof (struct ucl_stack), st); + } } else { ucl_set_err (chunk, UCL_ESYNTAX, "unexpected terminating symbol detected", &parser->err); @@ -1391,11 +1527,17 @@ ucl_state_machine (struct ucl_parser *parser) { ucl_object_t *obj; struct ucl_chunk *chunk = parser->chunks; - struct ucl_stack *st; const unsigned char *p, *c = NULL, *macro_start = NULL; unsigned char *macro_escaped; size_t macro_len = 0; struct ucl_macro *macro = NULL; + bool next_key = false, end_of_object = false; + + if (parser->top_obj == NULL) { + obj = ucl_add_parser_stack (NULL, parser, false, 0); + parser->top_obj = obj; + parser->state = UCL_STATE_INIT; + } p = chunk->pos; while (chunk->pos < chunk->end) { @@ -1406,6 +1548,7 @@ ucl_state_machine (struct ucl_parser *parser) * if we got [ or { correspondingly or can just treat new data as * a key of newly created object */ + obj = parser->top_obj; if (!ucl_skip_comments (parser)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; @@ -1413,25 +1556,20 @@ ucl_state_machine (struct ucl_parser *parser) } else { p = chunk->pos; - obj = ucl_object_new (); if (*p == '[') { parser->state = UCL_STATE_VALUE; obj->type = UCL_ARRAY; + ucl_hash_destroy (obj->value.ov, NULL); + obj->value.av = NULL; ucl_chunk_skipc (chunk, p); } else { parser->state = UCL_STATE_KEY; obj->type = UCL_OBJECT; - obj->value.ov = ucl_hash_create (); if (*p == '{') { ucl_chunk_skipc (chunk, p); } - }; - parser->cur_obj = obj; - parser->top_obj = obj; - st = UCL_ALLOC (sizeof (struct ucl_stack)); - st->obj = obj; - LL_PREPEND (parser->stack, st); + } } break; case UCL_STATE_KEY: @@ -1444,13 +1582,24 @@ ucl_state_machine (struct ucl_parser *parser) parser->state = UCL_STATE_AFTER_VALUE; continue; } - if (!ucl_parse_key (parser, chunk)) { + if (!ucl_parse_key (parser, chunk, &next_key, &end_of_object)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; return false; } - if (parser->state != UCL_STATE_MACRO_NAME) { - parser->state = UCL_STATE_VALUE; + if (end_of_object) { + p = chunk->pos; + parser->state = UCL_STATE_AFTER_VALUE; + continue; + } + else if (parser->state != UCL_STATE_MACRO_NAME) { + if (next_key && parser->stack->obj->type == UCL_OBJECT) { + /* Parse more keys and nest objects accordingly */ + obj = ucl_add_parser_stack (parser->cur_obj, parser, false, parser->stack->level + 1); + } + else { + parser->state = UCL_STATE_VALUE; + } } else { c = chunk->pos; diff --git a/src/ucl/src/ucl_util.c b/src/ucl/src/ucl_util.c index 0df611961..cf9cf99b0 100644 --- a/src/ucl/src/ucl_util.c +++ b/src/ucl/src/ucl_util.c @@ -224,7 +224,7 @@ ucl_copy_value_trash (ucl_object_t *obj) ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser) { - if (parser->state != UCL_STATE_INIT && parser->state != UCL_STATE_ERROR) { + if (parser->state != UCL_STATE_ERROR) { return ucl_object_ref (parser->top_obj); } @@ -288,7 +288,7 @@ ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) return false; #else # if (OPENSSL_VERSION_NUMBER < 0x10000000L) - ucl_create_err (err, "cannot check signatures, openssl version is unsupported"); + ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported"); return EXIT_FAILURE; # else struct ucl_pubkey *nkey; @@ -444,19 +444,26 @@ ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *bufl filename, strerror (errno)); return false; } - if ((fd = open (filename, O_RDONLY)) == -1) { - ucl_create_err (err, "cannot open file %s: %s", - filename, strerror (errno)); - return false; + if (st.st_size == 0) { + /* Do not map empty files */ + *buf = ""; + *buflen = 0; } - if ((*buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + else { + if ((fd = open (filename, O_RDONLY)) == -1) { + ucl_create_err (err, "cannot open file %s: %s", + filename, strerror (errno)); + return false; + } + if ((*buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + close (fd); + ucl_create_err (err, "cannot mmap file %s: %s", + filename, strerror (errno)); + return false; + } + *buflen = st.st_size; close (fd); - ucl_create_err (err, "cannot mmap file %s: %s", - filename, strerror (errno)); - return false; } - *buflen = st.st_size; - close (fd); return true; } @@ -548,10 +555,14 @@ ucl_include_url (const unsigned char *data, size_t len, ucl_create_err (&parser->err, "cannot verify url %s: %s", urlbuf, ERR_error_string (ERR_get_error (), NULL)); - munmap (sigbuf, siglen); + if (siglen > 0) { + munmap (sigbuf, siglen); + } return false; } - munmap (sigbuf, siglen); + if (siglen > 0) { + munmap (sigbuf, siglen); + } #endif } @@ -612,10 +623,14 @@ ucl_include_file (const unsigned char *data, size_t len, ucl_create_err (&parser->err, "cannot verify file %s: %s", filebuf, ERR_error_string (ERR_get_error (), NULL)); - munmap (sigbuf, siglen); + if (siglen > 0) { + munmap (sigbuf, siglen); + } return false; } - munmap (sigbuf, siglen); + if (siglen > 0) { + munmap (sigbuf, siglen); + } #endif } @@ -628,7 +643,9 @@ ucl_include_file (const unsigned char *data, size_t len, UCL_FREE (sizeof (struct ucl_chunk), chunk); } } - munmap (buf, buflen); + if (buflen > 0) { + munmap (buf, buflen); + } return res; } @@ -688,7 +705,9 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename) ret = ucl_parser_add_chunk (parser, buf, len); - munmap (buf, len); + if (len > 0) { + munmap (buf, len); + } return ret; } @@ -883,6 +902,17 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, top->type = UCL_OBJECT; } + if (top->type != UCL_OBJECT) { + /* It is possible to convert NULL type to an object */ + if (top->type == UCL_NULL) { + top->type = UCL_OBJECT; + } + else { + /* Refuse converting of other object types */ + return top; + } + } + if (top->value.ov == NULL) { top->value.ov = ucl_hash_create (); } diff --git a/src/ucl/src/xxhash.c b/src/ucl/src/xxhash.c index bb4c639aa..5869503be 100644 --- a/src/ucl/src/xxhash.c +++ b/src/ucl/src/xxhash.c @@ -273,7 +273,7 @@ U32 XXH32(const void* input, int len, U32 seed) XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; # if !defined(XXH_USE_UNALIGNED_ACCESS) - if ((((size_t)input) & 3)) // Input is aligned, let's leverage the speed advantage + if (!(((size_t)input) & 3)) // Input is aligned, let's leverage the speed advantage { if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); -- 2.39.5