From 392345779760e9c6f5425d2478eb0efd2271ef33 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 25 Apr 2024 15:27:24 +0100 Subject: [PATCH] [Fix] Backport fixes from libucl --- contrib/libucl/ucl_msgpack.c | 62 ++++++++++++++++++++++++++++-------- contrib/libucl/ucl_util.c | 50 +++++++++++++++++++++++------ 2 files changed, 88 insertions(+), 24 deletions(-) diff --git a/contrib/libucl/ucl_msgpack.c b/contrib/libucl/ucl_msgpack.c index 1fcdcc875..9190cc4c6 100644 --- a/contrib/libucl/ucl_msgpack.c +++ b/contrib/libucl/ucl_msgpack.c @@ -438,7 +438,7 @@ static ssize_t ucl_msgpack_parse_ignore (struct ucl_parser *parser, /* * Search tree packed in array */ -static struct ucl_msgpack_parser { +struct ucl_msgpack_parser { uint8_t prefix; /* Prefix byte */ uint8_t prefixlen; /* Length of prefix in bits */ uint8_t fmt; /* The desired format */ @@ -1019,6 +1019,8 @@ ucl_msgpack_consume (struct ucl_parser *parser) } else { /* Length is not embedded */ + remain --; + if (remain < obj_parser->len) { ucl_create_err (&parser->err, "not enough data remain to " "read object's length: %u remain, %u needed", @@ -1028,7 +1030,6 @@ ucl_msgpack_consume (struct ucl_parser *parser) } p ++; - remain --; switch (obj_parser->len) { case 1: @@ -1044,8 +1045,10 @@ ucl_msgpack_consume (struct ucl_parser *parser) len = FROM_BE64 (*(uint64_t *)p); break; default: - assert (0); - break; + ucl_create_err (&parser->err, "invalid length of the length field: %u", + (unsigned)obj_parser->len); + + return false; } p += obj_parser->len; @@ -1131,7 +1134,9 @@ ucl_msgpack_consume (struct ucl_parser *parser) */ container = parser->stack; - if (container == NULL) { + if (parser->stack == NULL) { + ucl_create_err (&parser->err, + "read assoc value when no container represented"); return false; } @@ -1141,9 +1146,14 @@ ucl_msgpack_consume (struct ucl_parser *parser) /* Insert value to the container and check if we have finished array */ - if (!ucl_msgpack_insert_object (parser, NULL, 0, + if (parser->cur_obj) { + if (!ucl_msgpack_insert_object(parser, NULL, 0, parser->cur_obj)) { - return false; + return false; + } + } + else { + /* We have parsed ext, ignore it */ } if (ucl_msgpack_is_container_finished (container)) { @@ -1191,6 +1201,8 @@ ucl_msgpack_consume (struct ucl_parser *parser) container = parser->stack; if (container == NULL) { + ucl_create_err (&parser->err, + "read assoc value when no container represented"); return false; } @@ -1200,9 +1212,12 @@ ucl_msgpack_consume (struct ucl_parser *parser) assert (key != NULL && keylen > 0); - if (!ucl_msgpack_insert_object (parser, key, keylen, + if (parser->cur_obj) { + if (!ucl_msgpack_insert_object(parser, key, keylen, parser->cur_obj)) { - return false; + + return false; + } } key = NULL; @@ -1237,7 +1252,9 @@ ucl_msgpack_consume (struct ucl_parser *parser) case start_assoc: /* Empty container at the end */ if (len != 0) { - ucl_create_err (&parser->err, "invalid non-empty container at the end"); + ucl_create_err (&parser->err, + "invalid non-empty container at the end; len=%zu", + (uintmax_t)len); return false; } @@ -1245,6 +1262,12 @@ ucl_msgpack_consume (struct ucl_parser *parser) parser->cur_obj = ucl_object_new_full ( state == start_array ? UCL_ARRAY : UCL_OBJECT, parser->chunks->priority); + + if (parser->stack == NULL) { + ucl_create_err (&parser->err, + "read assoc value when no container represented"); + return false; + } /* Insert to the previous level container */ if (!ucl_msgpack_insert_object (parser, key, keylen, parser->cur_obj)) { @@ -1271,7 +1294,9 @@ ucl_msgpack_consume (struct ucl_parser *parser) container = parser->stack; - if (container == NULL) { + if (parser->stack == NULL) { + ucl_create_err (&parser->err, + "read assoc value when no container represented"); return false; } @@ -1281,9 +1306,11 @@ ucl_msgpack_consume (struct ucl_parser *parser) /* Insert value to the container and check if we have finished array */ - if (!ucl_msgpack_insert_object (parser, NULL, 0, + if (parser->cur_obj) { + if (!ucl_msgpack_insert_object(parser, NULL, 0, parser->cur_obj)) { - return false; + return false; + } } break; case finish_array_value: @@ -1301,7 +1328,12 @@ ucl_msgpack_consume (struct ucl_parser *parser) /* Rewind to the top level container */ ucl_msgpack_get_next_container (parser); - assert (parser->stack == NULL); + + if (parser->stack != NULL) { + ucl_create_err (&parser->err, "incomplete container"); + + return false; + } return true; } @@ -1611,5 +1643,7 @@ ucl_msgpack_parse_ignore (struct ucl_parser *parser, return -1; } + parser->cur_obj = NULL; + return len; } diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c index 3f2483c10..b00f2779e 100644 --- a/contrib/libucl/ucl_util.c +++ b/contrib/libucl/ucl_util.c @@ -67,7 +67,7 @@ typedef kvec_t(ucl_object_t *) ucl_array_t; #include #endif -#if defined(_MSC_VER) +#if defined(_WIN32) #include #include #include @@ -866,6 +866,8 @@ ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen, *buf = cbdata.buf; *buflen = cbdata.buflen; + curl_easy_cleanup (curl); + return true; #else ucl_create_err (err, "URL support is disabled"); @@ -1020,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; } @@ -1095,6 +1100,11 @@ ucl_include_file_single (const unsigned char *data, size_t len, ucl_hash_t *container = NULL; struct ucl_stack *st = NULL; + if (parser->state == UCL_STATE_ERROR) { + /* Return immediately if we are in the error state... */ + return false; + } + snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data); if (ucl_realpath (filebuf, realbuf) == NULL) { if (params->soft_fail) { @@ -1131,6 +1141,8 @@ ucl_include_file_single (const unsigned char *data, size_t len, return false; } + ucl_parser_clear_error (parser); + return true; } @@ -1850,6 +1862,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); } @@ -3078,13 +3094,13 @@ ucl_object_type (const ucl_object_t *obj) ucl_object_t* ucl_object_fromstring (const char *str) { - return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE); + return ucl_object_fromstring_common (str, 0, UCL_STRING_RAW); } ucl_object_t * ucl_object_fromlstring (const char *str, size_t len) { - return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE); + return ucl_object_fromstring_common (str, len, UCL_STRING_RAW); } ucl_object_t * @@ -3375,10 +3391,20 @@ ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) head = elt; } else { - elt->prev = head->prev; - head->prev->next = elt; - head->prev = elt; - elt->next = NULL; + if (head->type == UCL_USERDATA) { + /* Userdata objects are VERY special! */ + struct ucl_object_userdata *ud = (struct ucl_object_userdata *)head; + elt->prev = ud->obj.prev; + ud->obj.prev->next = elt; + ud->obj.prev = elt; + elt->next = NULL; + } + else { + elt->prev = head->prev; + head->prev->next = elt; + head->prev = elt; + elt->next = NULL; + } } return head; @@ -3588,11 +3614,15 @@ ucl_object_copy_internal (const ucl_object_t *other, bool allow_array) ucl_object_t *new; ucl_object_iter_t it = NULL; const ucl_object_t *cur; + size_t sz = sizeof(*new); - new = malloc (sizeof (*new)); + if (other->type == UCL_USERDATA) { + sz = sizeof (struct ucl_object_userdata); + } + new = malloc (sz); if (new != NULL) { - memcpy (new, other, sizeof (*new)); + memcpy (new, other, sz); if (other->flags & UCL_OBJECT_EPHEMERAL) { /* Copied object is always non ephemeral */ new->flags &= ~UCL_OBJECT_EPHEMERAL; @@ -3949,4 +3979,4 @@ const char * ucl_parser_get_cur_file (struct ucl_parser *parser) { return parser->cur_file; -} \ No newline at end of file +} -- 2.39.5