summaryrefslogtreecommitdiffstats
path: root/src/bplist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bplist.c')
-rw-r--r--src/bplist.c20
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
188static 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 }