summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2026-01-23 16:20:55 +0100
committerGravatar Nikias Bassen2026-01-23 16:20:55 +0100
commitd0e6ef114aef98c410e59e30cc203489ddf3ba52 (patch)
treee57f45829095954df8b39d8baa7cbbef4dc42f46
parent1d628bc5b051ba941389a13aa94983d5d273618b (diff)
downloadlibplist-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.c56
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)
900plist_t plist_dict_get_item(plist_t node, const char* key) 900plist_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;