diff options
| author | 2026-01-23 16:20:55 +0100 | |
|---|---|---|
| committer | 2026-01-23 16:20:55 +0100 | |
| commit | d0e6ef114aef98c410e59e30cc203489ddf3ba52 (patch) | |
| tree | e57f45829095954df8b39d8baa7cbbef4dc42f46 | |
| parent | 1d628bc5b051ba941389a13aa94983d5d273618b (diff) | |
| download | libplist-d0e6ef114aef98c410e59e30cc203489ddf3ba52.tar.gz libplist-d0e6ef114aef98c410e59e30cc203489ddf3ba52.tar.bz2 | |
plist: Improve plist_dict_get_item() to safely iterate key/value pairs
Use explicit key/value stepping, zero-initialize hash lookup key,
and perform length-checked comparisons on NUL-terminated key strings.
| -rw-r--r-- | src/plist.c | 56 |
1 files changed, 32 insertions, 24 deletions
diff --git a/src/plist.c b/src/plist.c index 781f795..a9199ee 100644 --- a/src/plist.c +++ b/src/plist.c @@ -900,31 +900,39 @@ plist_t plist_dict_item_get_key(plist_t node) plist_t plist_dict_get_item(plist_t node, const char* key) { plist_t ret = NULL; - - if (node && PLIST_DICT == plist_get_node_type(node)) - { - plist_data_t data = plist_get_data(node); - hashtable_t *ht = (hashtable_t*)data->hashtable; - if (ht) { - struct plist_data_s sdata; - sdata.strval = (char*)key; - sdata.length = strlen(key); - ret = (plist_t)hash_table_lookup(ht, &sdata); - } else { - plist_t current = NULL; - for (current = (plist_t)node_first_child((node_t)node); - current; - current = (plist_t)node_next_sibling(node_next_sibling((node_t)current))) - { - data = plist_get_data(current); - assert( PLIST_KEY == plist_get_node_type(current) ); - - if (data && !strcmp(key, data->strval)) - { - ret = (plist_t)node_next_sibling((node_t)current); - break; - } + if (!PLIST_IS_DICT(node) || !key) { + PLIST_ERR("invalid argument passed to %s (node=%p, key=%p)\n", __func__, node, key); + return NULL; + } + plist_data_t data = plist_get_data(node); + assert(data); + if (!data) { + PLIST_ERR("%s: invalid node\n", __func__); + return NULL; + } + size_t keylen = strlen(key); + hashtable_t *ht = (hashtable_t*)data->hashtable; + if (ht) { + struct plist_data_s sdata = { 0 }; + sdata.strval = (char*)key; + sdata.length = keylen; + return (plist_t)hash_table_lookup(ht, &sdata); + } else { + plist_t k = NULL; + for (k = (plist_t)node_first_child((node_t)node); k; ) { + plist_t v = (plist_t)node_next_sibling(k); + if (!v) break; + data = plist_get_data(k); + assert(PLIST_IS_KEY(k)); + if (!PLIST_IS_KEY(k) || !data || !data->strval) { + PLIST_ERR("invalid key node at %p\n", k); + break; + } + if (data->length == keylen && !memcmp(key, data->strval, keylen+1)) { + ret = v; + break; } + k = node_next_sibling(v); } } return ret; |
