diff options
| author | 2026-01-23 16:20:55 +0100 | |
|---|---|---|
| committer | 2026-01-23 16:20:55 +0100 | |
| commit | d0e6ef114aef98c410e59e30cc203489ddf3ba52 (patch) | |
| tree | e57f45829095954df8b39d8baa7cbbef4dc42f46 /src/plist.c | |
| 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.
Diffstat (limited to 'src/plist.c')
| -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) | |||
| 900 | plist_t plist_dict_get_item(plist_t node, const char* key) | 900 | plist_t plist_dict_get_item(plist_t node, const char* key) |
| 901 | { | 901 | { |
| 902 | plist_t ret = NULL; | 902 | plist_t ret = NULL; |
| 903 | 903 | if (!PLIST_IS_DICT(node) || !key) { | |
| 904 | if (node && PLIST_DICT == plist_get_node_type(node)) | 904 | PLIST_ERR("invalid argument passed to %s (node=%p, key=%p)\n", __func__, node, key); |
| 905 | { | 905 | return NULL; |
| 906 | plist_data_t data = plist_get_data(node); | 906 | } |
| 907 | hashtable_t *ht = (hashtable_t*)data->hashtable; | 907 | plist_data_t data = plist_get_data(node); |
| 908 | if (ht) { | 908 | assert(data); |
| 909 | struct plist_data_s sdata; | 909 | if (!data) { |
| 910 | sdata.strval = (char*)key; | 910 | PLIST_ERR("%s: invalid node\n", __func__); |
| 911 | sdata.length = strlen(key); | 911 | return NULL; |
| 912 | ret = (plist_t)hash_table_lookup(ht, &sdata); | 912 | } |
| 913 | } else { | 913 | size_t keylen = strlen(key); |
| 914 | plist_t current = NULL; | 914 | hashtable_t *ht = (hashtable_t*)data->hashtable; |
| 915 | for (current = (plist_t)node_first_child((node_t)node); | 915 | if (ht) { |
| 916 | current; | 916 | struct plist_data_s sdata = { 0 }; |
| 917 | current = (plist_t)node_next_sibling(node_next_sibling((node_t)current))) | 917 | sdata.strval = (char*)key; |
| 918 | { | 918 | sdata.length = keylen; |
| 919 | data = plist_get_data(current); | 919 | return (plist_t)hash_table_lookup(ht, &sdata); |
| 920 | assert( PLIST_KEY == plist_get_node_type(current) ); | 920 | } else { |
| 921 | 921 | plist_t k = NULL; | |
| 922 | if (data && !strcmp(key, data->strval)) | 922 | for (k = (plist_t)node_first_child((node_t)node); k; ) { |
| 923 | { | 923 | plist_t v = (plist_t)node_next_sibling(k); |
| 924 | ret = (plist_t)node_next_sibling((node_t)current); | 924 | if (!v) break; |
| 925 | break; | 925 | data = plist_get_data(k); |
| 926 | } | 926 | assert(PLIST_IS_KEY(k)); |
| 927 | if (!PLIST_IS_KEY(k) || !data || !data->strval) { | ||
| 928 | PLIST_ERR("invalid key node at %p\n", k); | ||
| 929 | break; | ||
| 930 | } | ||
| 931 | if (data->length == keylen && !memcmp(key, data->strval, keylen+1)) { | ||
| 932 | ret = v; | ||
| 933 | break; | ||
| 927 | } | 934 | } |
| 935 | k = node_next_sibling(v); | ||
| 928 | } | 936 | } |
| 929 | } | 937 | } |
| 930 | return ret; | 938 | return ret; |
