diff options
| author | 2021-12-22 03:17:26 +0100 | |
|---|---|---|
| committer | 2021-12-22 03:17:26 +0100 | |
| commit | 70f4a422e01910cdb783aac81f13c11223c3acbd (patch) | |
| tree | 1279c0edd8b84b91d6a9bc757ea5dc8232f4d78f /src/bplist.c | |
| parent | 810e1a5936867a9f2c9f07df3a33a9d02fc03466 (diff) | |
| download | libplist-70f4a422e01910cdb783aac81f13c11223c3acbd.tar.gz libplist-70f4a422e01910cdb783aac81f13c11223c3acbd.tar.bz2 | |
Add a return value to plist_to_* and plist_from_* functions
This way it can be easier determined why an import/export operation failed
instead of just having a NULL result.
Diffstat (limited to 'src/bplist.c')
| -rw-r--r-- | src/bplist.c | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/src/bplist.c b/src/bplist.c index a6e6ded..57ec151 100644 --- a/src/bplist.c +++ b/src/bplist.c | |||
| @@ -774,7 +774,7 @@ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node | |||
| 774 | return plist; | 774 | return plist; |
| 775 | } | 775 | } |
| 776 | 776 | ||
| 777 | PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) | 777 | PLIST_API plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) |
| 778 | { | 778 | { |
| 779 | bplist_trailer_t *trailer = NULL; | 779 | bplist_trailer_t *trailer = NULL; |
| 780 | uint8_t offset_size = 0; | 780 | uint8_t offset_size = 0; |
| @@ -786,20 +786,28 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * | |||
| 786 | const char *start_data = NULL; | 786 | const char *start_data = NULL; |
| 787 | const char *end_data = NULL; | 787 | const char *end_data = NULL; |
| 788 | 788 | ||
| 789 | if (!plist) { | ||
| 790 | return PLIST_ERR_INVALID_ARG; | ||
| 791 | } | ||
| 792 | *plist = NULL; | ||
| 793 | if (!plist_bin || length == 0) { | ||
| 794 | return PLIST_ERR_INVALID_ARG; | ||
| 795 | } | ||
| 796 | |||
| 789 | //first check we have enough data | 797 | //first check we have enough data |
| 790 | if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + sizeof(bplist_trailer_t))) { | 798 | if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + sizeof(bplist_trailer_t))) { |
| 791 | PLIST_BIN_ERR("plist data is to small to hold a binary plist\n"); | 799 | PLIST_BIN_ERR("plist data is to small to hold a binary plist\n"); |
| 792 | return; | 800 | return PLIST_ERR_PARSE; |
| 793 | } | 801 | } |
| 794 | //check that plist_bin in actually a plist | 802 | //check that plist_bin in actually a plist |
| 795 | if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) { | 803 | if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) { |
| 796 | PLIST_BIN_ERR("bplist magic mismatch\n"); | 804 | PLIST_BIN_ERR("bplist magic mismatch\n"); |
| 797 | return; | 805 | return PLIST_ERR_PARSE; |
| 798 | } | 806 | } |
| 799 | //check for known version | 807 | //check for known version |
| 800 | if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) { | 808 | if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) { |
| 801 | PLIST_BIN_ERR("unsupported binary plist version '%.2s\n", plist_bin+BPLIST_MAGIC_SIZE); | 809 | PLIST_BIN_ERR("unsupported binary plist version '%.2s\n", plist_bin+BPLIST_MAGIC_SIZE); |
| 802 | return; | 810 | return PLIST_ERR_PARSE; |
| 803 | } | 811 | } |
| 804 | 812 | ||
| 805 | start_data = plist_bin + BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE; | 813 | start_data = plist_bin + BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE; |
| @@ -816,37 +824,37 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * | |||
| 816 | 824 | ||
| 817 | if (num_objects == 0) { | 825 | if (num_objects == 0) { |
| 818 | PLIST_BIN_ERR("number of objects must be larger than 0\n"); | 826 | PLIST_BIN_ERR("number of objects must be larger than 0\n"); |
| 819 | return; | 827 | return PLIST_ERR_PARSE; |
| 820 | } | 828 | } |
| 821 | 829 | ||
| 822 | if (offset_size == 0) { | 830 | if (offset_size == 0) { |
| 823 | PLIST_BIN_ERR("offset size in trailer must be larger than 0\n"); | 831 | PLIST_BIN_ERR("offset size in trailer must be larger than 0\n"); |
| 824 | return; | 832 | return PLIST_ERR_PARSE; |
| 825 | } | 833 | } |
| 826 | 834 | ||
| 827 | if (ref_size == 0) { | 835 | if (ref_size == 0) { |
| 828 | PLIST_BIN_ERR("object reference size in trailer must be larger than 0\n"); | 836 | PLIST_BIN_ERR("object reference size in trailer must be larger than 0\n"); |
| 829 | return; | 837 | return PLIST_ERR_PARSE; |
| 830 | } | 838 | } |
| 831 | 839 | ||
| 832 | if (root_object >= num_objects) { | 840 | if (root_object >= num_objects) { |
| 833 | PLIST_BIN_ERR("root object index (%" PRIu64 ") must be smaller than number of objects (%" PRIu64 ")\n", root_object, num_objects); | 841 | PLIST_BIN_ERR("root object index (%" PRIu64 ") must be smaller than number of objects (%" PRIu64 ")\n", root_object, num_objects); |
| 834 | return; | 842 | return PLIST_ERR_PARSE; |
| 835 | } | 843 | } |
| 836 | 844 | ||
| 837 | if (offset_table < start_data || offset_table >= end_data) { | 845 | if (offset_table < start_data || offset_table >= end_data) { |
| 838 | PLIST_BIN_ERR("offset table offset points outside of valid range\n"); | 846 | PLIST_BIN_ERR("offset table offset points outside of valid range\n"); |
| 839 | return; | 847 | return PLIST_ERR_PARSE; |
| 840 | } | 848 | } |
| 841 | 849 | ||
| 842 | if (uint64_mul_overflow(num_objects, offset_size, &offset_table_size)) { | 850 | if (uint64_mul_overflow(num_objects, offset_size, &offset_table_size)) { |
| 843 | PLIST_BIN_ERR("integer overflow when calculating offset table size\n"); | 851 | PLIST_BIN_ERR("integer overflow when calculating offset table size\n"); |
| 844 | return; | 852 | return PLIST_ERR_PARSE; |
| 845 | } | 853 | } |
| 846 | 854 | ||
| 847 | if (offset_table_size > (uint64_t)(end_data - offset_table)) { | 855 | if (offset_table_size > (uint64_t)(end_data - offset_table)) { |
| 848 | PLIST_BIN_ERR("offset table points outside of valid range\n"); | 856 | PLIST_BIN_ERR("offset table points outside of valid range\n"); |
| 849 | return; | 857 | return PLIST_ERR_PARSE; |
| 850 | } | 858 | } |
| 851 | 859 | ||
| 852 | struct bplist_data bplist; | 860 | struct bplist_data bplist; |
| @@ -861,12 +869,18 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * | |||
| 861 | 869 | ||
| 862 | if (!bplist.used_indexes) { | 870 | if (!bplist.used_indexes) { |
| 863 | PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n"); | 871 | PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n"); |
| 864 | return; | 872 | return PLIST_ERR_NO_MEM; |
| 865 | } | 873 | } |
| 866 | 874 | ||
| 867 | *plist = parse_bin_node_at_index(&bplist, root_object); | 875 | *plist = parse_bin_node_at_index(&bplist, root_object); |
| 868 | 876 | ||
| 869 | ptr_array_free(bplist.used_indexes); | 877 | ptr_array_free(bplist.used_indexes); |
| 878 | |||
| 879 | if (!*plist) { | ||
| 880 | return PLIST_ERR_PARSE; | ||
| 881 | } | ||
| 882 | |||
| 883 | return PLIST_ERR_SUCCESS; | ||
| 870 | } | 884 | } |
| 871 | 885 | ||
| 872 | static unsigned int plist_data_hash(const void* key) | 886 | static unsigned int plist_data_hash(const void* key) |
| @@ -1163,7 +1177,7 @@ static int is_ascii_string(char* s, int len) | |||
| 1163 | return ret; | 1177 | return ret; |
| 1164 | } | 1178 | } |
| 1165 | 1179 | ||
| 1166 | PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | 1180 | PLIST_API plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) |
| 1167 | { | 1181 | { |
| 1168 | ptrarray_t* objects = NULL; | 1182 | ptrarray_t* objects = NULL; |
| 1169 | hashtable_t* ref_table = NULL; | 1183 | hashtable_t* ref_table = NULL; |
| @@ -1181,13 +1195,21 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 1181 | uint64_t objects_len = 0; | 1195 | uint64_t objects_len = 0; |
| 1182 | 1196 | ||
| 1183 | //check for valid input | 1197 | //check for valid input |
| 1184 | if (!plist || !plist_bin || *plist_bin || !length) | 1198 | if (!plist || !plist_bin || !length) { |
| 1185 | return; | 1199 | return PLIST_ERR_INVALID_ARG; |
| 1200 | } | ||
| 1186 | 1201 | ||
| 1187 | //list of objects | 1202 | //list of objects |
| 1188 | objects = ptr_array_new(4096); | 1203 | objects = ptr_array_new(4096); |
| 1204 | if (!objects) { | ||
| 1205 | return PLIST_ERR_NO_MEM; | ||
| 1206 | } | ||
| 1189 | //hashtable to write only once same nodes | 1207 | //hashtable to write only once same nodes |
| 1190 | ref_table = hash_table_new(plist_data_hash, plist_data_compare, free); | 1208 | ref_table = hash_table_new(plist_data_hash, plist_data_compare, free); |
| 1209 | if (!ref_table) { | ||
| 1210 | ptr_array_free(objects); | ||
| 1211 | return PLIST_ERR_NO_MEM; | ||
| 1212 | } | ||
| 1191 | 1213 | ||
| 1192 | //serialize plist | 1214 | //serialize plist |
| 1193 | ser_s.objects = objects; | 1215 | ser_s.objects = objects; |
| @@ -1212,6 +1234,7 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 1212 | uint8_t bsize; | 1234 | uint8_t bsize; |
| 1213 | switch (data->type) | 1235 | switch (data->type) |
| 1214 | { | 1236 | { |
| 1237 | case PLIST_NULL: | ||
| 1215 | case PLIST_BOOLEAN: | 1238 | case PLIST_BOOLEAN: |
| 1216 | req += 1; | 1239 | req += 1; |
| 1217 | break; | 1240 | break; |
| @@ -1286,6 +1309,11 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 1286 | 1309 | ||
| 1287 | //setup a dynamic bytes array to store bplist in | 1310 | //setup a dynamic bytes array to store bplist in |
| 1288 | bplist_buff = byte_array_new(req); | 1311 | bplist_buff = byte_array_new(req); |
| 1312 | if (!bplist_buff) { | ||
| 1313 | ptr_array_free(objects); | ||
| 1314 | hash_table_destroy(ref_table); | ||
| 1315 | return PLIST_ERR_NO_MEM; | ||
| 1316 | } | ||
| 1289 | 1317 | ||
| 1290 | //set magic number and version | 1318 | //set magic number and version |
| 1291 | byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); | 1319 | byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); |
| @@ -1385,4 +1413,6 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 1385 | 1413 | ||
| 1386 | bplist_buff->data = NULL; // make sure we don't free the output buffer | 1414 | bplist_buff->data = NULL; // make sure we don't free the output buffer |
| 1387 | byte_array_free(bplist_buff); | 1415 | byte_array_free(bplist_buff); |
| 1416 | |||
| 1417 | return PLIST_ERR_SUCCESS; | ||
| 1388 | } | 1418 | } |
