diff options
Diffstat (limited to 'src/bplist.c')
| -rw-r--r-- | src/bplist.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/src/bplist.c b/src/bplist.c index eede7a7..8e0dcd1 100644 --- a/src/bplist.c +++ b/src/bplist.c | |||
| @@ -178,6 +178,19 @@ union plist_uint_ptr | |||
| 178 | #define float_bswap32(x) (x) | 178 | #define float_bswap32(x) (x) |
| 179 | #endif | 179 | #endif |
| 180 | 180 | ||
| 181 | #ifndef __has_builtin | ||
| 182 | #define __has_builtin(x) 0 | ||
| 183 | #endif | ||
| 184 | |||
| 185 | #if __has_builtin(__builtin_umulll_overflow) || __GNUC__ >= 5 | ||
| 186 | #define uint64_mul_overflow(a, b, r) __builtin_umulll_overflow(a, b, r) | ||
| 187 | #else | ||
| 188 | static int uint64_mul_overflow(uint64_t a, uint64_t b, uint64_t *res) | ||
| 189 | { | ||
| 190 | *res = a * b; | ||
| 191 | return (a > UINT64_MAX / b); | ||
| 192 | } | ||
| 193 | #endif | ||
| 181 | 194 | ||
| 182 | #define NODE_IS_ROOT(x) (((node_t*)x)->isRoot) | 195 | #define NODE_IS_ROOT(x) (((node_t*)x)->isRoot) |
| 183 | 196 | ||
| @@ -773,6 +786,7 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * | |||
| 773 | uint64_t num_objects = 0; | 786 | uint64_t num_objects = 0; |
| 774 | uint64_t root_object = 0; | 787 | uint64_t root_object = 0; |
| 775 | const char *offset_table = NULL; | 788 | const char *offset_table = NULL; |
| 789 | uint64_t offset_table_size = 0; | ||
| 776 | const char *start_data = NULL; | 790 | const char *start_data = NULL; |
| 777 | const char *end_data = NULL; | 791 | const char *end_data = NULL; |
| 778 | 792 | ||
| @@ -829,12 +843,12 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * | |||
| 829 | return; | 843 | return; |
| 830 | } | 844 | } |
| 831 | 845 | ||
| 832 | if (num_objects * offset_size < num_objects) { | 846 | if (uint64_mul_overflow(num_objects, offset_size, &offset_table_size)) { |
| 833 | PLIST_BIN_ERR("integer overflow when calculating offset table size (too many objects)\n"); | 847 | PLIST_BIN_ERR("integer overflow when calculating offset table size\n"); |
| 834 | return; | 848 | return; |
| 835 | } | 849 | } |
| 836 | 850 | ||
| 837 | if ((uint64_t)offset_table + num_objects * offset_size > (uint64_t)end_data) { | 851 | if ((offset_table + offset_table_size < offset_table) || (offset_table + offset_table_size > end_data)) { |
| 838 | PLIST_BIN_ERR("offset table points outside of valid range\n"); | 852 | PLIST_BIN_ERR("offset table points outside of valid range\n"); |
| 839 | return; | 853 | return; |
| 840 | } | 854 | } |
