diff options
Diffstat (limited to 'src/bplist.c')
| -rw-r--r-- | src/bplist.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/src/bplist.c b/src/bplist.c index a2dc957..254c0ff 100644 --- a/src/bplist.c +++ b/src/bplist.c | |||
| @@ -239,6 +239,7 @@ struct bplist_data { | |||
| 239 | const char* offset_table; | 239 | const char* offset_table; |
| 240 | uint32_t level; | 240 | uint32_t level; |
| 241 | ptrarray_t* used_indexes; | 241 | ptrarray_t* used_indexes; |
| 242 | plist_err_t err; | ||
| 242 | }; | 243 | }; |
| 243 | 244 | ||
| 244 | #ifdef DEBUG | 245 | #ifdef DEBUG |
| @@ -787,6 +788,7 @@ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node | |||
| 787 | 788 | ||
| 788 | if (node_index >= bplist->num_objects) { | 789 | if (node_index >= bplist->num_objects) { |
| 789 | PLIST_BIN_ERR("node index (%u) must be smaller than the number of objects (%" PRIu64 ")\n", node_index, bplist->num_objects); | 790 | PLIST_BIN_ERR("node index (%u) must be smaller than the number of objects (%" PRIu64 ")\n", node_index, bplist->num_objects); |
| 791 | bplist->err = PLIST_ERR_PARSE; | ||
| 790 | return NULL; | 792 | return NULL; |
| 791 | } | 793 | } |
| 792 | 794 | ||
| @@ -794,6 +796,7 @@ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node | |||
| 794 | if (idx_ptr < bplist->offset_table || | 796 | if (idx_ptr < bplist->offset_table || |
| 795 | idx_ptr >= bplist->offset_table + bplist->num_objects * bplist->offset_size) { | 797 | idx_ptr >= bplist->offset_table + bplist->num_objects * bplist->offset_size) { |
| 796 | PLIST_BIN_ERR("node index %u points outside of valid range\n", node_index); | 798 | PLIST_BIN_ERR("node index %u points outside of valid range\n", node_index); |
| 799 | bplist->err = PLIST_ERR_PARSE; | ||
| 797 | return NULL; | 800 | return NULL; |
| 798 | } | 801 | } |
| 799 | 802 | ||
| @@ -801,6 +804,14 @@ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node | |||
| 801 | /* make sure the node offset is in a sane range */ | 804 | /* make sure the node offset is in a sane range */ |
| 802 | if ((ptr < bplist->data+BPLIST_MAGIC_SIZE+BPLIST_VERSION_SIZE) || (ptr >= bplist->offset_table)) { | 805 | if ((ptr < bplist->data+BPLIST_MAGIC_SIZE+BPLIST_VERSION_SIZE) || (ptr >= bplist->offset_table)) { |
| 803 | PLIST_BIN_ERR("offset for node index %u points outside of valid range\n", node_index); | 806 | PLIST_BIN_ERR("offset for node index %u points outside of valid range\n", node_index); |
| 807 | bplist->err = PLIST_ERR_PARSE; | ||
| 808 | return NULL; | ||
| 809 | } | ||
| 810 | |||
| 811 | /* check nesting depth */ | ||
| 812 | if (bplist->level > PLIST_MAX_NESTING_DEPTH) { | ||
| 813 | PLIST_BIN_ERR("maximum nesting depth (%u) exceeded\n",(unsigned)PLIST_MAX_NESTING_DEPTH); | ||
| 814 | bplist->err = PLIST_ERR_MAX_NESTING; | ||
| 804 | return NULL; | 815 | return NULL; |
| 805 | } | 816 | } |
| 806 | 817 | ||
| @@ -820,6 +831,7 @@ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node | |||
| 820 | void *node_level = ptr_array_index(bplist->used_indexes, bplist->level); | 831 | void *node_level = ptr_array_index(bplist->used_indexes, bplist->level); |
| 821 | if (node_i == node_level) { | 832 | if (node_i == node_level) { |
| 822 | PLIST_BIN_ERR("recursion detected in binary plist\n"); | 833 | PLIST_BIN_ERR("recursion detected in binary plist\n"); |
| 834 | bplist->err = PLIST_ERR_PARSE; | ||
| 823 | return NULL; | 835 | return NULL; |
| 824 | } | 836 | } |
| 825 | } | 837 | } |
| @@ -931,6 +943,7 @@ plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * pli | |||
| 931 | bplist.offset_table = offset_table; | 943 | bplist.offset_table = offset_table; |
| 932 | bplist.level = 0; | 944 | bplist.level = 0; |
| 933 | bplist.used_indexes = ptr_array_new(16); | 945 | bplist.used_indexes = ptr_array_new(16); |
| 946 | bplist.err = PLIST_ERR_SUCCESS; | ||
| 934 | 947 | ||
| 935 | if (!bplist.used_indexes) { | 948 | if (!bplist.used_indexes) { |
| 936 | PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n"); | 949 | PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n"); |
| @@ -942,7 +955,7 @@ plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * pli | |||
| 942 | ptr_array_free(bplist.used_indexes); | 955 | ptr_array_free(bplist.used_indexes); |
| 943 | 956 | ||
| 944 | if (!*plist) { | 957 | if (!*plist) { |
| 945 | return PLIST_ERR_PARSE; | 958 | return (bplist.err != PLIST_ERR_SUCCESS) ? bplist.err : PLIST_ERR_PARSE; |
| 946 | } | 959 | } |
| 947 | 960 | ||
| 948 | return PLIST_ERR_SUCCESS; | 961 | return PLIST_ERR_SUCCESS; |
| @@ -1002,11 +1015,16 @@ struct serialize_s | |||
| 1002 | hashtable_t* in_stack; | 1015 | hashtable_t* in_stack; |
| 1003 | }; | 1016 | }; |
| 1004 | 1017 | ||
| 1005 | static plist_err_t serialize_plist(node_t node, void* data) | 1018 | static plist_err_t serialize_plist(node_t node, void* data, uint32_t depth) |
| 1006 | { | 1019 | { |
| 1007 | uint64_t *index_val = NULL; | 1020 | uint64_t *index_val = NULL; |
| 1008 | struct serialize_s *ser = (struct serialize_s *) data; | 1021 | struct serialize_s *ser = (struct serialize_s *) data; |
| 1009 | 1022 | ||
| 1023 | if (depth > PLIST_MAX_NESTING_DEPTH) { | ||
| 1024 | PLIST_BIN_WRITE_ERR("maximum nesting depth (%u) exceeded\n", (unsigned)PLIST_MAX_NESTING_DEPTH); | ||
| 1025 | return PLIST_ERR_MAX_NESTING; | ||
| 1026 | } | ||
| 1027 | |||
| 1010 | // circular reference check: is node on current recursion stack? | 1028 | // circular reference check: is node on current recursion stack? |
| 1011 | if (hash_table_lookup(ser->in_stack, node)) { | 1029 | if (hash_table_lookup(ser->in_stack, node)) { |
| 1012 | PLIST_BIN_WRITE_ERR("circular reference detected\n"); | 1030 | PLIST_BIN_WRITE_ERR("circular reference detected\n"); |
| @@ -1036,7 +1054,7 @@ static plist_err_t serialize_plist(node_t node, void* data) | |||
| 1036 | node_t ch; | 1054 | node_t ch; |
| 1037 | plist_err_t err = PLIST_ERR_SUCCESS; | 1055 | plist_err_t err = PLIST_ERR_SUCCESS; |
| 1038 | for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { | 1056 | for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { |
| 1039 | err = serialize_plist(ch, data); | 1057 | err = serialize_plist(ch, data, depth+1); |
| 1040 | if (err != PLIST_ERR_SUCCESS) { | 1058 | if (err != PLIST_ERR_SUCCESS) { |
| 1041 | break; | 1059 | break; |
| 1042 | } | 1060 | } |
| @@ -1313,7 +1331,7 @@ plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 1313 | ser_s.objects = objects; | 1331 | ser_s.objects = objects; |
| 1314 | ser_s.ref_table = ref_table; | 1332 | ser_s.ref_table = ref_table; |
| 1315 | ser_s.in_stack = in_stack; | 1333 | ser_s.in_stack = in_stack; |
| 1316 | plist_err_t err = serialize_plist((node_t)plist, &ser_s); | 1334 | plist_err_t err = serialize_plist((node_t)plist, &ser_s, 0); |
| 1317 | if (err != PLIST_ERR_SUCCESS) { | 1335 | if (err != PLIST_ERR_SUCCESS) { |
| 1318 | ptr_array_free(objects); | 1336 | ptr_array_free(objects); |
| 1319 | hash_table_destroy(ref_table); | 1337 | hash_table_destroy(ref_table); |
