Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
libucl: update to latest version
Baptiste Daroussin committed 3 years ago
commit 25b89d713a7804f3d14dbc18c52cf3ff660d1bb8
parent 9c99c79
11 files changed +395 -172
modified external/libucl/CMakeLists.txt
@@ -1,9 +1,9 @@
PROJECT(libucl C)
-
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR)
+
CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0 FATAL_ERROR)

SET(LIBUCL_VERSION_MAJOR 0)
-
SET(LIBUCL_VERSION_MINOR 5)
-
SET(LIBUCL_VERSION_PATCH 0)
+
SET(LIBUCL_VERSION_MINOR 8)
+
SET(LIBUCL_VERSION_PATCH 3)

SET(LIBUCL_VERSION
        "${LIBUCL_VERSION_MAJOR}.${LIBUCL_VERSION_MINOR}.${LIBUCL_VERSION_PATCH}")
@@ -237,12 +237,13 @@ ADD_LIBRARY(ucl ${LIB_TYPE} ${UCLSRC})
ADD_LIBRARY(ucl::ucl ALIAS ucl)
SET_TARGET_PROPERTIES(ucl PROPERTIES VERSION ${LIBUCL_VERSION} SOVERSION ${LIBUCL_VERSION_MAJOR})
TARGET_INCLUDE_DIRECTORIES(ucl
-
	PUBLIC
-
	  include
-
	PRIVATE
-
	  src
-
	  uthash
-
	  klib)
+
        PUBLIC
+
          $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+
          $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+
        PRIVATE
+
          ${CMAKE_CURRENT_SOURCE_DIR}/src
+
          ${CMAKE_CURRENT_SOURCE_DIR}/uthash
+
          ${CMAKE_CURRENT_SOURCE_DIR}/klib)
TARGET_COMPILE_DEFINITIONS(ucl
    PRIVATE
    ${UCL_COMPILE_DEFS}
@@ -305,10 +306,16 @@ ENDIF(UNIX)
SET_TARGET_PROPERTIES(ucl PROPERTIES
	PUBLIC_HEADER "${UCLHDR}")

-
INSTALL(TARGETS ucl DESTINATION ${CMAKE_INSTALL_LIBDIR}
+
INSTALL(TARGETS ucl EXPORT uclConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}
		PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

IF(ENABLE_UTILS MATCHES "ON")
    ADD_SUBDIRECTORY(utils)
ENDIF()

+
install(EXPORT uclConfig
+
	FILE ucl-config.cmake
+
	NAMESPACE ucl::
+
	DESTINATION "share/ucl"
+
)
+

modified external/libucl/ChangeLog.md
@@ -100,4 +100,126 @@
- Performance improvements in Lua API
- Allow to pass opaque objects in Lua API for transparent C passthrough
- Various bugs fixed
-
- Couple of memory leaks plugged

\ No newline at end of file
+
- Couple of memory leaks plugged
+

+
### Libucl 0.8.2
+

+
* .include: also validate priority to be within range
+
* Add -W into list of warnings
+
* Add ability to add file preprocessors
+
* Add ability to pass both the parser and userdata into a macro handler
+
* Add missing tests for .gitignore
+
* Add more safe guards when trying to insert objects
+
* Add some documentation/example about the .priority macro
+
* Add tests for single quotes
+
* Added CMake compile definitions
+
* Added CMake support to build utils
+
* Added a fuzzer for OSS-fuzz integration
+
* Added a return statement if the string is 0
+
* Added default CMake "build" directory to gitignore
+
* Added fuzzer for msgpack
+
* Adding another fix
+
* Adjust example.
+
* Allow to test msgpack inputs
+
* Another sync
+
* Assume gcov absense as a non-fatal error
+
* Avoid read when a chunk is ended
+
* CMake: Install headers and library.
+
* Check for NULL inputs in ucl_object_compare()
+
* Cleanup CURL handle after use
+
* Cleanup CURL handle after use
+
* Convert ucl_hash_insert() from returning int to returning bool.
+
* Convert ucl_hash_reserve() from returning int to bool.
+
* Do not try to emit single quoted strings in json mode
+
* Document single quotes
+
* Document ucl_object_iter_chk_excpn().
+
* Document usage of ucl_object_iter_chk_excpn().
+
* Don't double-escape Lua strings
+
* Excercise ucl_object_iter_chk_excpn().
+
* Fix '\v' encoding
+
* Fix 68d87c362b0d7fbb45f395bfae616a28439e0bbc by setting error to 0 always. Which makes it even uglier.
+
* Fix cmake public include install
+
* Fix emitting of the bad unicode escapes
+
* Fix format strings, add printf attribute to schema functions
+
* Fix levels and objects closing
+
* Fix load macro with try=true
+
* Fix mismerge.
+
* Fix mismerge.
+
* Fix old issue with parsing numbers
+
* Fix processing of the incomplete msgpack objects
+
* Fix remain calculations
+
* Fix remain lenght calculation that led to assertion failure
+
* Fix single quotes emitting
+
* Fix spelling and markup errors.
+
* Fix typos: replace missmatch with mismatch
+
* Fix ucl++ bug where iterators stop on a null field.
+
* Fix ucl_util.c not having the prototype for ucl_hash_sort()
+
* Fix variables expansion
+
* Fix vertical tab handling
+
* Fixed Visual Studio compilation error
+
* Fixed expanding variables at runtime
+
* Fixed linker error
+
* Fixed ucl_tool's command line argument parsing
+
* Fixing error with installing using pip from git with following command: 'pip install -e git+https://github.com/vstakhov/libucl.git/#egg=ucl
+
* Forgot hash sort function
+
* Improve ENOMEM handling: handle most of errors while consuructing parser, also extend iterator routines to allow capturing such exception and checking it in the higher level code using new ucl_object_iter_chk_excpn() API.
+
* Mark + as unsafe which fixes export a key with + in config mode
+
* Modernise the CMake build system slightly.
+
* Modernize CMake file with target-based includes.
+
* Pass correct pointer to var_handler
+
* Port util objdump to Windows (Visual Studio)
+
* Port util ucl-tool to Windows
+
* Provide inline free(3) wrapper, so it's easier to plug the code into out memory usage tracking framework.
+
* Provide inline free(3) wrapper, so it's easier to plug the code into out memory usage tracking framework.
+
* Provide priority validation for the .priority macro
+
* Put space between "exit" and ().
+
* Put space between name of teh function and ().
+
* Python build fixes
+
* Read data in chunks
+
* Remove leak in the test
+
* Remove one more bit of unused logic
+
* Remove one more stupid assertion
+
* Remove unnecessary (and ignored) `const` from return types.
+
* Remove unnecessary std::move from return statement.
+
* Remove unused CMake logic and ad -Wno-pointer-sign.
+
* Removed dependency from rspamd CMake file
+
* Removed null-terminator for input data
+
* Rename ENOMEM-safe version of kv_xxx macros from kv_xxx into kv_xxx_safe and put back old version as well (with a big warning in the header file) for a compat purposes.
+
* Renamed util binaries to match autotools
+
* Replace *neat* and *tidy* implementation of kv_xxx() macros using error handling labels with a much *uglier* implementation using "error code pointer". One man's "ugly" is other man's "pretty", I suppose.
+
* Replaced spaces by tabs to match coding style
+
* Rework hash table structure to provide pointers and order safety
+
* Save chunk in the parser stack
+
* Save filename in chunk
+
* Split level and flags, add obrace flag, fix msgpack flags
+
* Squelch incompatible pointer type warning
+
* Support single quoted strings
+
* Suppress the [-Wunused-parameter] warning.
+
* Sync changes from Rspamd
+
* Sync changes from rspamd
+
* Sync with Rspamd
+
* Understand nan and inf
+
* Use safe iterator - avoid leaking memory.
+
* docs: fix simple typo, tectual -> textual
+
* fix: Changed OpenSSL check inside configure.am
+
* fix: Incorrect pointer arithmetics in ucl_expand_single_variable
+
* fix: ucl_expand_single_variable doesn't call free
+
* lua: Return early when init fails
+
* make use of the undocumented flag UCL_PARSER_NO_IMPLICIT_ARRAYS, so that multiple keys are treated as arrays, and special code doesn't have to be added to the Python module to handle it.
+
* mypy/stubgen: add typeinterfaces for ucl python module
+
* o `ucl_object_iterate2()` -> `ucl_object_iterate_with_error()`;
+
* python: update package to 0.8.1
+
* `ucl_check_variable`: fix out_len on unterminated variable
+
* `ucl_chunk_skipc`: avoid out-of-bounds read
+
* `ucl_expand_single_variable`: better bounds check
+
* `ucl_expand_variable`: fix out-of-bounds read
+
* `ucl_inherit_handler`: fix format string for non-null-terminated strings
+
* `ucl_lc_cmp` is not used outside ucl_hash.c
+
* `ucl_lex_json_string`: fix out-of-bounds read
+
* `ucl_maybe_parse_number`: if there is trailing content, it is not a number
+
* `ucl_object_copy_internal`: null terminate keys
+
* `ucl_object_copy_internal`: use memcpy instead of strdup
+
* `ucl_object_free` is deprecated
+
* `ucl_parse_value`: fix out-of-bounds read
+
* `ucl_strnstr`: fix out-of-bounds read
+
* update JSON example to match w/ UCL example
modified external/libucl/Makefile.am
@@ -69,7 +69,7 @@ clean-coverage-report:
	-rm -rf $(COVERAGE_REPORT_DIR)

clean-coverage: clean-coverage-report
-
	-$(LCOV) --gcov-tool $(GCOV) --zerocounters --directory $(top_builddir)
+
	-$(LCOV) --gcov-tool $(GCOV) --zerocounters --directory $(top_builddir) || true
	@if xargs --version 2>/dev/null; then \
		find $(top_builddir) -name "*.gcno" | xargs --no-run-if-empty rm; \
	else \
modified external/libucl/README.md
@@ -1,9 +1,5 @@
# LIBUCL

-
[![CircleCI](https://circleci.com/gh/vstakhov/libucl.svg?style=svg)](https://circleci.com/gh/vstakhov/libucl)
-
[![Coverity](https://scan.coverity.com/projects/4138/badge.svg)](https://scan.coverity.com/projects/4138)
-
[![Coverage Status](https://coveralls.io/repos/github/vstakhov/libucl/badge.svg?branch=master)](https://coveralls.io/github/vstakhov/libucl?branch=master)
-

**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*

- [Introduction](#introduction)
@@ -374,7 +370,8 @@ Each UCL object can be serialized to one of the four supported formats:
* `JSON` - canonic json notation (with spaces indented structure);
* `Compacted JSON` - compact json notation (without spaces or newlines);
* `Configuration` - nginx like notation;
-
* `YAML` - yaml inlined notation.
+
* `YAML` - yaml inlined notation;
+
* `messagepack` - MessagePack binary format.

## Validation

modified external/libucl/configure.ac
@@ -1,6 +1,6 @@
m4_define([maj_ver], [0])
m4_define([med_ver], [8])
-
m4_define([min_ver], [1])
+
m4_define([min_ver], [3])
m4_define([so_version], [6:0:1])
m4_define([ucl_version], [maj_ver.med_ver.min_ver])

modified external/libucl/lua/lua_ucl.c
@@ -479,7 +479,16 @@ ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_flags_t flags)
		str = lua_tolstring (L, idx, &sz);

		if (str) {
-
			obj = ucl_object_fromstring_common (str, sz, flags);
+
			/*
+
			 * ucl_object_fromstring_common has a `logic` to use strlen if sz is zero
+
			 * which is totally broken...
+
			 */
+
			if (sz > 0) {
+
				obj = ucl_object_fromstring_common(str, sz, flags);
+
			}
+
			else {
+
				obj = ucl_object_fromstring_common("", sz, flags);
+
			}
		}
		else {
			obj = ucl_object_typed_new (UCL_NULL);
modified external/libucl/src/mum.h
@@ -399,7 +399,7 @@ mum_hash64 (uint64_t key, uint64_t seed) {
   target endianness and the unroll factor.  */
static inline uint64_t
mum_hash (const void *key, size_t len, uint64_t seed) {
-
#if defined(__x86_64__) && defined(_MUM_FRESH_GCC) && _MUM_UNALIGNED_ACCESS != 0
+
#if defined(__x86_64__) && defined(_MUM_FRESH_GCC)
  static int avx2_support = 0;

  if (avx2_support > 0)
modified external/libucl/src/ucl_hash.c
@@ -32,12 +32,12 @@

struct ucl_hash_elt {
	const ucl_object_t *obj;
-
	size_t ar_idx;
+
	struct ucl_hash_elt *prev, *next;
};

struct ucl_hash_struct {
	void *hash;
-
	kvec_t(const ucl_object_t *) ar;
+
	struct ucl_hash_elt *head;
	bool caseless;
};

@@ -45,7 +45,6 @@ static uint64_t
ucl_hash_seed (void)
{
	static uint64_t seed;
-

	if (seed == 0) {
#ifdef UCL_RANDOM_FUNCTION
		seed = UCL_RANDOM_FUNCTION;
@@ -115,7 +114,7 @@ ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
	return 0;
}

-
KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt, 1,
+
KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt *, 1,
		ucl_hash_func, ucl_hash_equal)

static inline uint32_t
@@ -227,7 +226,7 @@ ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2)
	return 0;
}

-
KHASH_INIT (ucl_hash_caseless_node, const ucl_object_t *, struct ucl_hash_elt, 1,
+
KHASH_INIT (ucl_hash_caseless_node, const ucl_object_t *, struct ucl_hash_elt *, 1,
		ucl_hash_caseless_func, ucl_hash_caseless_equal)

ucl_hash_t*
@@ -238,8 +237,7 @@ ucl_hash_create (bool ignore_case)
	new = UCL_ALLOC (sizeof (ucl_hash_t));
	if (new != NULL) {
		void *h;
-
		kv_init (new->ar);
-

+
		new->head = NULL;
		new->caseless = ignore_case;
		if (ignore_case) {
			h = (void *)kh_init (ucl_hash_caseless_node);
@@ -258,7 +256,6 @@ ucl_hash_create (bool ignore_case)

void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
{
-
	const ucl_object_t *cur, *tmp;

	if (hashlin == NULL) {
		return;
@@ -269,10 +266,11 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
		khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
				hashlin->hash;
		khiter_t k;
+
		const ucl_object_t *cur, *tmp;

		for (k = kh_begin (h); k != kh_end (h); ++k) {
			if (kh_exist (h, k)) {
-
				cur = (kh_value (h, k)).obj;
+
				cur = (kh_value (h, k))->obj;
				while (cur != NULL) {
					tmp = cur->next;
					func (__DECONST (ucl_object_t *, cur));
@@ -293,7 +291,12 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
		kh_destroy (ucl_hash_node, h);
	}

-
	kv_destroy (hashlin->ar);
+
	struct ucl_hash_elt *cur, *tmp;
+

+
	DL_FOREACH_SAFE(hashlin->head, cur, tmp) {
+
		UCL_FREE(sizeof(*cur), cur);
+
	}
+

	UCL_FREE (sizeof (*hashlin), hashlin);
}

@@ -303,7 +306,7 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
{
	khiter_t k;
	int ret;
-
	struct ucl_hash_elt *elt;
+
	struct ucl_hash_elt **pelt, *elt;

	if (hashlin == NULL) {
		return false;
@@ -314,10 +317,14 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
				hashlin->hash;
		k = kh_put (ucl_hash_caseless_node, h, obj, &ret);
		if (ret > 0) {
-
			elt = &kh_value (h, k);
-
			kv_push_safe (const ucl_object_t *, hashlin->ar, obj, e0);
+
			elt = UCL_ALLOC(sizeof(*elt));
+
			pelt = &kh_value (h, k);
+
			*pelt = elt;
+
			DL_APPEND(hashlin->head, elt);
			elt->obj = obj;
-
			elt->ar_idx = kv_size (hashlin->ar) - 1;
+
		}
+
		else if (ret < 0) {
+
			goto e0;
		}
	}
	else {
@@ -325,10 +332,11 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
				hashlin->hash;
		k = kh_put (ucl_hash_node, h, obj, &ret);
		if (ret > 0) {
-
			elt = &kh_value (h, k);
-
			kv_push_safe (const ucl_object_t *, hashlin->ar, obj, e0);
+
			elt = UCL_ALLOC(sizeof(*elt));
+
			pelt = &kh_value (h, k);
+
			*pelt = elt;
+
			DL_APPEND(hashlin->head, elt);
			elt->obj = obj;
-
			elt->ar_idx = kv_size (hashlin->ar) - 1;
		} else if (ret < 0) {
			goto e0;
		}
@@ -343,7 +351,7 @@ void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
{
	khiter_t k;
	int ret;
-
	struct ucl_hash_elt elt, *pelt;
+
	struct ucl_hash_elt *elt, *nelt;

	if (hashlin == NULL) {
		return;
@@ -354,13 +362,14 @@ void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
				hashlin->hash;
		k = kh_put (ucl_hash_caseless_node, h, old, &ret);
		if (ret == 0) {
-
			elt = kh_value (h, k);
+
			elt = kh_value(h, k);
			kh_del (ucl_hash_caseless_node, h, k);
			k = kh_put (ucl_hash_caseless_node, h, new, &ret);
-
			pelt = &kh_value (h, k);
-
			pelt->obj = new;
-
			pelt->ar_idx = elt.ar_idx;
-
			kv_A (hashlin->ar, elt.ar_idx) = new;
+
			nelt = UCL_ALLOC(sizeof(*nelt));
+
			nelt->obj = new;
+
			kh_value(h, k) = nelt;
+
			DL_REPLACE_ELEM(hashlin->head, elt, nelt);
+
			UCL_FREE(sizeof(*elt), elt);
		}
	}
	else {
@@ -371,17 +380,17 @@ void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
			elt = kh_value (h, k);
			kh_del (ucl_hash_node, h, k);
			k = kh_put (ucl_hash_node, h, new, &ret);
-
			pelt = &kh_value (h, k);
-
			pelt->obj = new;
-
			pelt->ar_idx = elt.ar_idx;
-
			kv_A (hashlin->ar, elt.ar_idx) = new;
+
			nelt = UCL_ALLOC(sizeof(*nelt));
+
			nelt->obj = new;
+
			kh_value(h, k) = nelt;
+
			DL_REPLACE_ELEM(hashlin->head, elt, nelt);
+
			UCL_FREE(sizeof(*elt), elt);
		}
	}
}

struct ucl_hash_real_iter {
-
	const ucl_object_t **cur;
-
	const ucl_object_t **end;
+
	const struct ucl_hash_elt *cur;
};

#define UHI_SETERR(ep, ern) {if (ep != NULL) *ep = (ern);}
@@ -405,13 +414,13 @@ ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
			return NULL;
		}

-
		it->cur = &hashlin->ar.a[0];
-
		it->end = it->cur + hashlin->ar.n;
+
		it->cur = hashlin->head;
	}

	UHI_SETERR(ep, 0);
-
	if (it->cur < it->end) {
-
		ret = *it->cur++;
+
	if (it->cur) {
+
		ret = it->cur->obj;
+
		it->cur = it->cur->next;
	}
	else {
		UCL_FREE (sizeof (*it), it);
@@ -429,7 +438,7 @@ ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter)
{
	struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(iter);

-
	return it->cur < it->end - 1;
+
	return it->cur != NULL;
}


@@ -454,7 +463,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)

		k = kh_get (ucl_hash_caseless_node, h, &search);
		if (k != kh_end (h)) {
-
			elt = &kh_value (h, k);
+
			elt = kh_value (h, k);
			ret = elt->obj;
		}
	}
@@ -463,7 +472,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
						hashlin->hash;
		k = kh_get (ucl_hash_node, h, &search);
		if (k != kh_end (h)) {
-
			elt = &kh_value (h, k);
+
			elt = kh_value (h, k);
			ret = elt->obj;
		}
	}
@@ -476,7 +485,6 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
{
	khiter_t k;
	struct ucl_hash_elt *elt;
-
	size_t i;

	if (hashlin == NULL) {
		return;
@@ -488,16 +496,10 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)

		k = kh_get (ucl_hash_caseless_node, h, obj);
		if (k != kh_end (h)) {
-
			elt = &kh_value (h, k);
-
			i = elt->ar_idx;
-
			kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
+
			elt = kh_value (h, k);
+
			DL_DELETE(hashlin->head, elt);
			kh_del (ucl_hash_caseless_node, h, k);
-

-
			/* Update subsequent elts */
-
			for (; i < hashlin->ar.n; i ++) {
-
				elt = &kh_value (h, i);
-
				elt->ar_idx --;
-
			}
+
			UCL_FREE(sizeof(*elt), elt);
		}
	}
	else {
@@ -505,16 +507,10 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
			hashlin->hash;
		k = kh_get (ucl_hash_node, h, obj);
		if (k != kh_end (h)) {
-
			elt = &kh_value (h, k);
-
			i = elt->ar_idx;
-
			kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
+
			elt = kh_value (h, k);
+
			DL_DELETE(hashlin->head, elt);
			kh_del (ucl_hash_node, h, k);
-

-
			/* Update subsequent elts */
-
			for (; i < hashlin->ar.n; i ++) {
-
				elt = &kh_value (h, i);
-
				elt->ar_idx --;
-
			}
+
			UCL_FREE(sizeof(*elt), elt);
		}
	}
}
@@ -525,9 +521,7 @@ bool ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
		return false;
	}

-
	if (sz > hashlin->ar.m) {
-
		kv_resize_safe (const ucl_object_t *, hashlin->ar, sz, e0);
-

+
	if (sz > kh_size((khash_t(ucl_hash_node) *)hashlin->hash)) {
		if (hashlin->caseless) {
			khash_t(ucl_hash_caseless_node) *h = (khash_t(
					ucl_hash_caseless_node) *)
@@ -540,8 +534,6 @@ bool ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
		}
	}
	return true;
-
e0:
-
	return false;
}

static int
@@ -591,27 +583,27 @@ ucl_lc_cmp (const char *s, const char *d, size_t l)
static int
ucl_hash_cmp_icase (const void *a, const void *b)
{
-
	const ucl_object_t *oa = *(const ucl_object_t **)a,
-
			*ob = *(const ucl_object_t **)b;
+
	const struct ucl_hash_elt *oa = (const struct ucl_hash_elt *)a,
+
		*ob = (const struct ucl_hash_elt *)b;

-
	if (oa->keylen == ob->keylen) {
-
		return ucl_lc_cmp (oa->key, ob->key, oa->keylen);
+
	if (oa->obj->keylen == ob->obj->keylen) {
+
		return ucl_lc_cmp (oa->obj->key, ob->obj->key, oa->obj->keylen);
	}

-
	return ((int)(oa->keylen)) - ob->keylen;
+
	return ((int)(oa->obj->keylen)) - ob->obj->keylen;
}

static int
ucl_hash_cmp_case_sens (const void *a, const void *b)
{
-
	const ucl_object_t *oa = *(const ucl_object_t **)a,
-
			*ob = *(const ucl_object_t **)b;
+
	const struct ucl_hash_elt *oa = (const struct ucl_hash_elt *)a,
+
			*ob = (const struct ucl_hash_elt *)b;

-
	if (oa->keylen == ob->keylen) {
-
		return memcmp (oa->key, ob->key, oa->keylen);
+
	if (oa->obj->keylen == ob->obj->keylen) {
+
		return memcmp (oa->obj->key, ob->obj->key, oa->obj->keylen);
	}

-
	return ((int)(oa->keylen)) - ob->keylen;
+
	return ((int)(oa->obj->keylen)) - ob->obj->keylen;
}

void
@@ -619,18 +611,18 @@ ucl_hash_sort (ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl)
{

	if (fl & UCL_SORT_KEYS_ICASE) {
-
		qsort (hashlin->ar.a, hashlin->ar.n, sizeof (ucl_object_t *),
-
				ucl_hash_cmp_icase);
+
		DL_SORT(hashlin->head, ucl_hash_cmp_icase);
	}
	else {
-
		qsort (hashlin->ar.a, hashlin->ar.n, sizeof (ucl_object_t *),
-
				ucl_hash_cmp_case_sens);
+
		DL_SORT(hashlin->head, ucl_hash_cmp_case_sens);
	}

	if (fl & UCL_SORT_KEYS_RECURSIVE) {
-
		for (size_t i = 0; i < hashlin->ar.n; i ++) {
-
			if (ucl_object_type (hashlin->ar.a[i]) == UCL_OBJECT) {
-
				ucl_hash_sort (hashlin->ar.a[i]->value.ov, fl);
+
		struct ucl_hash_elt *elt;
+

+
		DL_FOREACH(hashlin->head, elt) {
+
			if (ucl_object_type (elt->obj) == UCL_OBJECT) {
+
				ucl_hash_sort (elt->obj->value.ov, fl);
			}
		}
	}
modified external/libucl/src/ucl_parser.c
@@ -47,6 +47,9 @@ struct ucl_parser_saved_state {
 */
#define ucl_chunk_skipc(chunk, p)    \
do {                                 \
+
	if (p == chunk->end) {       \
+
		break;                   \
+
	}                            \
	if (*(p) == '\n') {          \
		(chunk)->line ++;    \
		(chunk)->column = 0; \
@@ -176,7 +179,7 @@ start:
				if (!quoted) {
					if (*p == '*') {
						ucl_chunk_skipc (chunk, p);
-
						if (*p == '/') {
+
						if (chunk->remain > 0 && *p == '/') {
							comments_nested --;
							if (comments_nested == 0) {
								if (parser->flags & UCL_PARSER_SAVE_COMMENTS) {
@@ -345,7 +348,6 @@ ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t rema
		/* Call generic handler */
		if (parser->var_handler (ptr, remain, &dst, &dstlen, &need_free,
				parser->var_data)) {
-
			*out_len = dstlen;
			*found = true;
			if (need_free) {
				free (dst);
@@ -395,6 +397,9 @@ ucl_check_variable (struct ucl_parser *parser, const char *ptr,
			}
			p ++;
		}
+
		if(p == end) {
+
			(*out_len) ++;
+
		}
	}
	else if (*ptr != '$') {
		/* Not count escaped dollar sign */
@@ -418,13 +423,14 @@ ucl_check_variable (struct ucl_parser *parser, const char *ptr,
 * Expand a single variable
 * @param parser
 * @param ptr
-
 * @param remain
+
 * @param in_len
 * @param dest
+
 * @param out_len
 * @return
 */
static const char *
ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
-
		size_t remain, unsigned char **dest)
+
		size_t in_len, unsigned char **dest, size_t out_len)
{
	unsigned char *d = *dest, *dst;
	const char *p = ptr + 1, *ret;
@@ -435,7 +441,8 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
	bool strict = false;

	ret = ptr + 1;
-
	remain --;
+
	/* For the $ sign */
+
	in_len --;

	if (*p == '$') {
		*d++ = *p++;
@@ -444,39 +451,53 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
	}
	else if (*p == '{') {
		p ++;
+
		in_len --;
		strict = true;
		ret += 2;
-
		remain -= 2;
	}

	LL_FOREACH (parser->variables, var) {
-
		if (remain >= var->var_len) {
+
		if (out_len >= var->value_len && in_len >= (var->var_len + (strict ? 1 : 0))) {
			if (memcmp (p, var->var, var->var_len) == 0) {
-
				memcpy (d, var->value, var->value_len);
-
				ret += var->var_len;
-
				d += var->value_len;
-
				found = true;
-
				break;
+
				if (!strict || p[var->var_len] == '}') {
+
					memcpy (d, var->value, var->value_len);
+
					ret += var->var_len;
+
					d += var->value_len;
+
					found = true;
+
					break;
+
				}
			}
		}
	}
+

	if (!found) {
		if (strict && parser->var_handler != NULL) {
-
			if (parser->var_handler (p, remain, &dst, &dstlen, &need_free,
+
			dstlen = out_len;
+

+
			if (parser->var_handler (p, in_len, &dst, &dstlen, &need_free,
							parser->var_data)) {
-
				memcpy (d, dst, dstlen);
-
				ret += remain;
-
				d += dstlen;
-
				found = true;
-
				if (need_free) {
-
					free (dst);
+
				if (dstlen > out_len) {
+
					/* We do not have enough space! */
+
					if (need_free) {
+
						free (dst);
+
					}
+
				}
+
				else {
+
					memcpy(d, dst, dstlen);
+
					ret += in_len;
+
					d += dstlen;
+
					found = true;
+

+
					if (need_free) {
+
						free(dst);
+
					}
				}
			}
		}

-
		/* Leave variable as is */
+
		/* Leave variable as is, in this case we use dest */
		if (!found) {
-
			if (strict) {
+
			if (strict && out_len >= 2) {
				/* Copy '${' */
				memcpy (d, ptr, 2);
				d += 2;
@@ -506,7 +527,7 @@ ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst,
		const char *src, size_t in_len)
{
	const char *p, *end = src + in_len;
-
	unsigned char *d;
+
	unsigned char *d, *d_end;
	size_t out_len = 0;
	bool vars_found = false;

@@ -517,7 +538,7 @@ ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst,

	p = src;
	while (p != end) {
-
		if (*p == '$') {
+
		if (*p == '$' && p + 1 != end) {
			p = ucl_check_variable (parser, p + 1, end - p - 1, &out_len, &vars_found);
		}
		else {
@@ -538,10 +559,11 @@ ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst,
	}

	d = *dst;
+
	d_end = d + out_len;
	p = src;
-
	while (p != end) {
-
		if (*p == '$') {
-
			p = ucl_expand_single_variable (parser, p, end - p, &d);
+
	while (p != end && d != d_end) {
+
		if (*p == '$' && p + 1 != end) {
+
			p = ucl_expand_single_variable (parser, p, end - p, &d, d_end - d);
		}
		else {
			*d++ = *p++;
@@ -686,6 +708,8 @@ ucl_parser_add_container (ucl_object_t *obj, struct ucl_parser *parser,
			ucl_object_unref (obj);
		}

+
		UCL_FREE(sizeof (struct ucl_stack), st);
+

		return NULL;
	}

@@ -722,13 +746,13 @@ ucl_maybe_parse_number (ucl_object_t *obj,
	const char *p = start, *c = start;
	char *endptr;
	bool got_dot = false, got_exp = false, need_double = false,
-
			is_time = false, valid_start = false, is_hex = false,
-
			is_neg = false;
+
			is_time = false, valid_start = false, is_hex = false;
+
	int is_neg = 0;
	double dv = 0;
	int64_t lv = 0;

	if (*p == '-') {
-
		is_neg = true;
+
		is_neg = 1;
		c ++;
		p ++;
	}
@@ -744,6 +768,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
			is_hex = true;
			allow_double = false;
			c = p + 1;
+
			p ++;
		}
		else if (allow_double) {
			if (p == c) {
@@ -792,26 +817,46 @@ ucl_maybe_parse_number (ucl_object_t *obj,
				break;
			}
		}
+
		else if (!allow_double && *p == '.') {
+
			/* Unexpected dot */
+
			*pos = start;
+
			return EINVAL;
+
		}
		else {
			break;
		}
	}

-
	if (!valid_start) {
+
	if (!valid_start || p == c) {
		*pos = start;
		return EINVAL;
	}

+
	char numbuf[128];
+
	
+
	if ((size_t)(p - c + 1) >= sizeof(numbuf)) {
+
		*pos = start;
+
		return EINVAL;
+
	}
+
	
+
	if (is_neg) {
+
		numbuf[0] = '-';
+
		ucl_strlcpy (&numbuf[1], c, p - c + 1);
+
	}
+
	else {
+
		ucl_strlcpy (numbuf, c, p - c + 1);
+
	}
+
	
	errno = 0;
	if (need_double) {
-
		dv = strtod (c, &endptr);
+
		dv = strtod (numbuf, &endptr);
	}
	else {
		if (is_hex) {
-
			lv = strtoimax (c, &endptr, 16);
+
			lv = strtoimax (numbuf, &endptr, 16);
		}
		else {
-
			lv = strtoimax (c, &endptr, 10);
+
			lv = strtoimax (numbuf, &endptr, 10);
		}
	}
	if (errno == ERANGE) {
@@ -819,14 +864,21 @@ ucl_maybe_parse_number (ucl_object_t *obj,
		return ERANGE;
	}

-
	/* Now check endptr */
+
	/* Now check endptr and move it from numbuf to the real ending */
+
	if (endptr != NULL) {
+
		long shift = endptr - numbuf - is_neg;
+
		endptr = (char *)c + shift;
+
	}
+
	if (endptr >= end) {
+
		p = end;
+
		goto set_obj;
+
	}
	if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0') {
		p = endptr;
		goto set_obj;
	}

	if (endptr < end && endptr != start) {
-
		p = endptr;
		switch (*p) {
		case 'm':
		case 'M':
@@ -849,6 +901,10 @@ ucl_maybe_parse_number (ucl_object_t *obj,
						dv *= ucl_lex_num_multiplier (*p, false);
					}
					p += 2;
+
					if (end - p > 0 && !ucl_lex_is_atom_end (*p)) {
+
						*pos = start;
+
						return EINVAL;
+
					}
					goto set_obj;
				}
				else if (number_bytes || (p[1] == 'b' || p[1] == 'B')) {
@@ -859,6 +915,10 @@ ucl_maybe_parse_number (ucl_object_t *obj,
					}
					lv *= ucl_lex_num_multiplier (*p, true);
					p += 2;
+
					if (end - p > 0 && !ucl_lex_is_atom_end (*p)) {
+
						*pos = start;
+
						return EINVAL;
+
					}
					goto set_obj;
				}
				else if (ucl_lex_is_atom_end (p[1])) {
@@ -883,6 +943,10 @@ ucl_maybe_parse_number (ucl_object_t *obj,
						is_time = true;
						dv *= 60.;
						p += 3;
+
						if (end - p > 0 && !ucl_lex_is_atom_end (*p)) {
+
							*pos = start;
+
							return EINVAL;
+
						}
						goto set_obj;
					}
				}
@@ -895,6 +959,10 @@ ucl_maybe_parse_number (ucl_object_t *obj,
					lv *= ucl_lex_num_multiplier (*p, number_bytes);
				}
				p ++;
+
				if (end - p > 0 && !ucl_lex_is_atom_end (*p)) {
+
					*pos = start;
+
					return EINVAL;
+
				}
				goto set_obj;
			}
			break;
@@ -943,7 +1011,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
	}
	else if (endptr == end) {
		/* Just a number at the end of chunk */
-
		p = endptr;
+
		p = end;
		goto set_obj;
	}

@@ -959,11 +1027,11 @@ set_obj:
			else {
				obj->type = UCL_TIME;
			}
-
			obj->value.dv = is_neg ? (-dv) : dv;
+
			obj->value.dv = dv;
		}
		else {
			obj->type = UCL_INT;
-
			obj->value.iv = is_neg ? (-lv) : lv;
+
			obj->value.iv = lv;
		}
	}
	*pos = p;
@@ -1037,13 +1105,13 @@ ucl_lex_json_string (struct ucl_parser *parser,
		}
		else if (c == '\\') {
			ucl_chunk_skipc (chunk, p);
-
			c = *p;
			if (p >= chunk->end) {
				ucl_set_err (parser, UCL_ESYNTAX, "unfinished escape character",
						&parser->err);
				return false;
			}
-
			else if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) {
+
			c = *p;
+
			if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) {
				if (c == 'u') {
					ucl_chunk_skipc (chunk, p);
					for (i = 0; i < 4 && p < chunk->end; i ++) {
@@ -1812,6 +1880,11 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
					while (p < chunk->end && *p >= 'A' && *p <= 'Z') {
						p ++;
					}
+
					if(p == chunk->end) {
+
						ucl_set_err (parser, UCL_ESYNTAX,
+
								"unterminated multiline value", &parser->err);
+
						return false;
+
					}
					if (*p =='\n') {
						/* Set chunk positions and start multiline parsing */
						chunk->remain -= p - c + 1;
@@ -2889,7 +2962,9 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,

				if (!special_handler->handler (parser, data, len, &ndata, &nlen,
						special_handler->user_data)) {
+
					UCL_FREE(sizeof (struct ucl_chunk), chunk);
					ucl_create_err (&parser->err, "call for external handler failed");
+

					return false;
				}

modified external/libucl/src/ucl_schema.c
@@ -39,6 +39,7 @@
#ifdef HAVE_MATH_H
#include <math.h>
#endif
+
#include <inttypes.h>

static bool ucl_schema_validate (const ucl_object_t *schema,
		const ucl_object_t *obj, bool try_array,
@@ -244,20 +245,22 @@ ucl_schema_validate_object (const ucl_object_t *schema,
		/* Additional properties */
		if (!allow_additional || additional_schema != NULL) {
			/* Check if we have exactly the same properties in schema and object */
-
			iter = NULL;
+
			iter = ucl_object_iterate_new (obj);
			prop = ucl_object_lookup (schema, "properties");
-
			while ((elt = ucl_object_iterate (obj, &iter, true)) != NULL) {
+
			while ((elt = ucl_object_iterate_safe (iter, true)) != NULL) {
				found = ucl_object_lookup (prop, ucl_object_key (elt));
				if (found == NULL) {
					/* Try patternProperties */
-
					piter = NULL;
					pat = ucl_object_lookup (schema, "patternProperties");
-
					while ((pelt = ucl_object_iterate (pat, &piter, true)) != NULL) {
+
					piter = ucl_object_iterate_new (pat);
+
					while ((pelt = ucl_object_iterate_safe (piter, true)) != NULL) {
						found = ucl_schema_test_pattern (obj, ucl_object_key (pelt), true);
						if (found != NULL) {
							break;
						}
					}
+
					ucl_object_iterate_free (piter);
+
					piter = NULL;
				}
				if (found == NULL) {
					if (!allow_additional) {
@@ -276,6 +279,8 @@ ucl_schema_validate_object (const ucl_object_t *schema,
					}
				}
			}
+
			ucl_object_iterate_free (iter);
+
			iter = NULL;
		}
		/* Required properties */
		if (required != NULL) {
modified external/libucl/src/ucl_util.c
@@ -67,7 +67,7 @@ typedef kvec_t(ucl_object_t *) ucl_array_t;
#include <fetch.h>
#endif

-
#if defined(_MSC_VER)
+
#if defined(_WIN32)
#include <windows.h>
#include <io.h>
#include <direct.h>
@@ -889,44 +889,49 @@ ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *bufl
{
	int fd;
	struct stat st;
+
	if ((fd = open (filename, O_RDONLY)) == -1) {
+
		ucl_create_err (err, "cannot open file %s: %s",
+
				filename, strerror (errno));
+
		return false;
+
	}

-
	if (stat (filename, &st) == -1) {
+
	if (fstat (fd, &st) == -1) {
		if (must_exist || errno == EPERM) {
			ucl_create_err (err, "cannot stat file %s: %s",
					filename, strerror (errno));
		}
+
		close (fd);
+

		return false;
	}
	if (!S_ISREG (st.st_mode)) {
		if (must_exist) {
			ucl_create_err (err, "file %s is not a regular file", filename);
		}
+
		close (fd);

		return false;
	}
+

	if (st.st_size == 0) {
		/* Do not map empty files */
		*buf = NULL;
		*buflen = 0;
	}
	else {
-
		if ((fd = open (filename, O_RDONLY)) == -1) {
-
			ucl_create_err (err, "cannot open file %s: %s",
-
					filename, strerror (errno));
-
			return false;
-
		}
-
		if ((*buf = ucl_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));
+
		if ((*buf = ucl_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));
			*buf = NULL;

			return false;
		}
		*buflen = st.st_size;
-
		close (fd);
	}

+
	close (fd);
+

	return true;
}

@@ -1017,6 +1022,9 @@ ucl_include_url (const unsigned char *data, size_t len,
	snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);

	if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, params->must_exist)) {
+
		if (!params->must_exist) {
+
			ucl_parser_clear_error (parser);
+
		}
		return !params->must_exist;
	}

@@ -1128,6 +1136,8 @@ ucl_include_file_single (const unsigned char *data, size_t len,
			return false;
		}

+
		ucl_parser_clear_error (parser);
+

		return true;
	}

@@ -1138,6 +1148,10 @@ ucl_include_file_single (const unsigned char *data, size_t len,
		/* We need to check signature first */
		snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
		if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
+
			if (buf) {
+
				ucl_munmap (buf, buflen);
+
			}
+

			return false;
		}
		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
@@ -1147,8 +1161,13 @@ ucl_include_file_single (const unsigned char *data, size_t len,
			if (sigbuf) {
				ucl_munmap (sigbuf, siglen);
			}
+
			if (buf) {
+
				ucl_munmap (buf, buflen);
+
			}
+

			return false;
		}
+

		if (sigbuf) {
			ucl_munmap (sigbuf, siglen);
		}
@@ -1257,6 +1276,8 @@ ucl_include_file_single (const unsigned char *data, size_t len,
							ucl_munmap (buf, buflen);
						}

+
						ucl_object_unref (new_obj);
+

						return false;
					}
					nest_obj->prev = nest_obj;
@@ -1576,11 +1597,6 @@ ucl_include_common (const unsigned char *data, size_t len,
			else if (param->type == UCL_INT) {
				if (strncmp (param->key, "priority", param->keylen) == 0) {
					params.priority = ucl_object_toint (param);
-
					if (params.priority > UCL_PRIORITY_MAX) {
-
						ucl_create_err (&parser->err, "Invalid priority value in macro: %d",
-
							params.priority);
-
						return false;
-
					}
				}
			}
		}
@@ -1719,9 +1735,8 @@ ucl_priority_handler (const unsigned char *data, size_t len,
	if (len > 0) {
		value = malloc(len + 1);
		ucl_strlcpy(value, (const char *)data, len + 1);
-
		errno = 0;
-
		priority = strtoul(value, &leftover, 10);
-
		if (errno != 0 || *leftover != '\0' || priority > UCL_PRIORITY_MAX) {
+
		priority = strtol(value, &leftover, 10);
+
		if (*leftover != '\0') {
			ucl_create_err (&parser->err, "Invalid priority value in macro: %s",
				value);
			free(value);
@@ -1842,6 +1857,10 @@ ucl_load_handler (const unsigned char *data, size_t len,
				!try_load)) {
			free (load_file);

+
			if (try_load) {
+
				ucl_parser_clear_error (parser);
+
			}
+

			return (try_load || false);
		}

@@ -1919,7 +1938,7 @@ ucl_inherit_handler (const unsigned char *data, size_t len,

	/* Some sanity checks */
	if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) {
-
		ucl_create_err (&parser->err, "Unable to find inherited object %*.s",
+
		ucl_create_err (&parser->err, "Unable to find inherited object %.*s",
				(int)len, data);
		return false;
	}
@@ -2177,7 +2196,7 @@ ucl_strnstr (const char *s, const char *find, int len)
		mlen = strlen (find);
		do {
			do {
-
				if ((sc = *s++) == 0 || len-- == 0)
+
				if ((sc = *s++) == 0 || len-- < mlen)
					return (NULL);
			} while (sc != c);
		} while (strncmp (s, find, mlen) != 0);
@@ -2596,6 +2615,7 @@ ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
						if (!ucl_object_merge (found, cp, copy)) {
							return false;
						}
+
						ucl_object_unref (cp);
					}
					else {
						ucl_hash_replace (top->value.ov, found, cp);
@@ -2627,6 +2647,7 @@ ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
					if (!ucl_object_merge (found, cp, copy)) {
						return false;
					}
+
					ucl_object_unref (cp);
				}
				else {
					ucl_hash_replace (top->value.ov, found, cp);
@@ -3594,9 +3615,11 @@ ucl_object_copy_internal (const ucl_object_t *other, bool allow_array)

		/* deep copy of values stored */
		if (other->trash_stack[UCL_TRASH_KEY] != NULL) {
-
			new->trash_stack[UCL_TRASH_KEY] =
-
					strdup (other->trash_stack[UCL_TRASH_KEY]);
+
			new->trash_stack[UCL_TRASH_KEY] = NULL;
			if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) {
+
				new->trash_stack[UCL_TRASH_KEY] = malloc(other->keylen + 1);
+
				memcpy(new->trash_stack[UCL_TRASH_KEY], other->trash_stack[UCL_TRASH_KEY], other->keylen);
+
				new->trash_stack[UCL_TRASH_KEY][other->keylen] = '\0';
				new->key = new->trash_stack[UCL_TRASH_KEY];
			}
		}
@@ -3666,13 +3689,6 @@ ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2)
	ucl_object_iter_t iter = NULL;
	int ret = 0;

-
    // Must check for NULL or code will segfault
-
    if ((o1 == NULL) || (o2 == NULL))
-
    {
-
        // The only way this could be true is of both are NULL
-
        return (o1 == NULL) && (o2 == NULL);
-
    }
-
    
	if (o1->type != o2->type) {
		return (o1->type) - (o2->type);
	}