From f5e74fc1e007b8f625d91e40c160785580de8f60 Mon Sep 17 00:00:00 2001 From: Sami Kortelainen Date: Sun, 22 Feb 2026 03:39:54 +0100 Subject: xplist: Convert nested {CF$UID:} dicts to PLIST_UID safely Convert single-entry { "CF$UID" : } dictionaries to PLIST_UID nodes when closing a dict in the XML parser. Refactor node cleanup logic: - Split plist_free_data() into internal _plist_free_data() - Introduce plist_free_children() to release child nodes separately - Update plist_set_element_val() to free children before changing container node types - Ensure PLIST_DICT hashtables do not free values (assert + force free_func = NULL) This avoids in-place container mutation issues and ensures child nodes and container metadata are released correctly before changing node type. Co-authored-by: Sami Kortelainen Co-authored-by: Nikias Bassen --- src/xplist.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/xplist.c') diff --git a/src/xplist.c b/src/xplist.c index 73e2b9f..a445dc5 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -1562,6 +1562,26 @@ handle_closing: ctx->err = PLIST_ERR_PARSE; goto err_out; } + + /* When closing a dictionary, convert a single-entry + { "CF$UID" : } dictionary into a PLIST_UID node. + Perform the conversion before moving to the parent node. */ + if (!strcmp(node_path->type, XPLIST_DICT) && parent && plist_get_node_type(parent) == PLIST_DICT) { + if (plist_dict_get_size(parent) == 1) { + plist_t uid = plist_dict_get_item(parent, "CF$UID"); + if (uid) { + uint64_t val = 0; + if (plist_get_node_type(uid) != PLIST_INT) { + ctx->err = PLIST_ERR_PARSE; + PLIST_XML_ERR("Invalid node type for CF$UID dict entry (must be PLIST_INT)\n"); + goto err_out; + } + plist_get_uint_val(uid, &val); + plist_set_uid_val(parent, val); + } + } + } + if (depth > 0) depth--; struct node_path_item *path_item = node_path; node_path = (struct node_path_item*)node_path->prev; -- cgit v1.1-32-gdbae