summaryrefslogtreecommitdiffstats
path: root/src/xplist.c
diff options
context:
space:
mode:
authorGravatar Sami Kortelainen2026-02-22 03:39:54 +0100
committerGravatar Nikias Bassen2026-02-22 03:39:54 +0100
commitf5e74fc1e007b8f625d91e40c160785580de8f60 (patch)
treece9da2c80c13a0718605019c098e2a3b775b814a /src/xplist.c
parent3bdee70a9c1490ea011c6fb65193b2c7e242d26d (diff)
downloadlibplist-f5e74fc1e007b8f625d91e40c160785580de8f60.tar.gz
libplist-f5e74fc1e007b8f625d91e40c160785580de8f60.tar.bz2
xplist: Convert nested {CF$UID:<int>} dicts to PLIST_UID safely
Convert single-entry { "CF$UID" : <integer> } 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 <sami.kortelainen@piceasoft.com> Co-authored-by: Nikias Bassen <nikias@gmx.li>
Diffstat (limited to 'src/xplist.c')
-rw-r--r--src/xplist.c20
1 files changed, 20 insertions, 0 deletions
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" : <integer> } 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;