| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 | Subject: Try to clean this up; the vector code is still fishyOrigin: FILE5_30-28-g393555f2Upstream-Author: Christos Zoulas <christos@zoulas.com>Date: Mon Mar 27 20:58:11 2017 +0000    [ Also contains the spello fix FILE5_30-10-ga25f230f -CB ]--- a/src/cdf.c+++ b/src/cdf.c@@ -818,6 +818,66 @@ 	return 0; } +#define CDF_SHLEN_LIMIT (UINT32_MAX / 8)+#define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(cdf_property_info_t)))++static const void *+cdf_offset(const void *p, size_t l)+{+	return CAST(const void *, CAST(const uint8_t *, p) + l);+}++static const uint8_t *+cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, +    const uint8_t *p, const uint8_t *e, size_t i)+{+	size_t tail = (i << 1) + 1;+	size_t ofs;+	const uint8_t *q;++	if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t),+	    __LINE__) == -1)+		return NULL;+	ofs = CDF_GETUINT32(p, tail);+	q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p), +	    ofs - 2 * sizeof(uint32_t)));++	if (q < p) {+		DPRINTF(("Wrapped around %p < %p\n", q, p));+		return NULL;+	}++	if (q >= e) {+		DPRINTF(("Ran off the end %p >= %p\n", q, e));+		return NULL;+	}+	return q;+}++static cdf_property_info_t *+cdf_grow_info(cdf_property_info_t **info, size_t *maxcount, size_t incr)+{+	cdf_property_info_t *inp;+	size_t newcount = *maxcount + incr;++	if (newcount > CDF_PROP_LIMIT)+		goto out;+	+	inp = CAST(cdf_property_info_t *,+	    realloc(*info, newcount * sizeof(*inp)));+	if (inp == NULL)+		goto out;++	*info = inp;+	*maxcount = newcount;+	return inp;+out:+	free(*info);+	*maxcount = 0;+	*info = NULL;+	return NULL;+}+ int cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,     uint32_t offs, cdf_property_info_t **info, size_t *count, size_t *maxcount)@@ -831,70 +891,40 @@ 	int64_t s64; 	uint64_t u64; 	cdf_timestamp_t tp;-	size_t i, o, o4, nelements, j;+	size_t i, o4, nelements, j, slen; 	cdf_property_info_t *inp;  	if (offs > UINT32_MAX / 4) { 		errno = EFTYPE; 		goto out; 	}-	shp = CAST(const cdf_section_header_t *, (const void *)-	    ((const char *)sst->sst_tab + offs));+	shp = CAST(const cdf_section_header_t *,+	    cdf_offset(sst->sst_tab, offs)); 	if (cdf_check_stream_offset(sst, h, shp, sizeof(*shp), __LINE__) == -1) 		goto out; 	sh.sh_len = CDF_TOLE4(shp->sh_len);-#define CDF_SHLEN_LIMIT (UINT32_MAX / 8) 	if (sh.sh_len > CDF_SHLEN_LIMIT) { 		errno = EFTYPE; 		goto out; 	} 	sh.sh_properties = CDF_TOLE4(shp->sh_properties);-#define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(*inp))) 	if (sh.sh_properties > CDF_PROP_LIMIT) 		goto out; 	DPRINTF(("section len: %u properties %u\n", sh.sh_len, 	    sh.sh_properties));-	if (*maxcount) {-		if (*maxcount > CDF_PROP_LIMIT)-			goto out;-		*maxcount += sh.sh_properties;-		inp = CAST(cdf_property_info_t *,-		    realloc(*info, *maxcount * sizeof(*inp)));-	} else {-		*maxcount = sh.sh_properties;-		inp = CAST(cdf_property_info_t *,-		    malloc(*maxcount * sizeof(*inp)));-	}+	inp = cdf_grow_info(info, maxcount, sh.sh_properties); 	if (inp == NULL)-		goto out1;-	*info = inp;+		goto out; 	inp += *count; 	*count += sh.sh_properties;-	p = CAST(const uint8_t *, (const void *)-	    ((const char *)(const void *)sst->sst_tab +-	    offs + sizeof(sh)));-	e = CAST(const uint8_t *, (const void *)-	    (((const char *)(const void *)shp) + sh.sh_len));+	p = CAST(const uint8_t *, cdf_offset(sst->sst_tab, offs + sizeof(sh)));+	e = CAST(const uint8_t *, cdf_offset(shp, sh.sh_len)); 	if (cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1) 		goto out;+ 	for (i = 0; i < sh.sh_properties; i++) {-		size_t tail = (i << 1) + 1;-		size_t ofs;-		if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t),-		    __LINE__) == -1)-			goto out;-		ofs = CDF_GETUINT32(p, tail);-		q = (const uint8_t *)(const void *)-		    ((const char *)(const void *)p + ofs-		    - 2 * sizeof(uint32_t));-		if (q < p) {-			DPRINTF(("Wrapped around %p < %p\n", q, p));-			goto out;-		}-		if (q >= e) {-			DPRINTF(("Ran of the end %p >= %p\n", q, e));+		if ((q = cdf_get_property_info_pos(sst, h, p, e, i)) == NULL) 			goto out;-		} 		inp[i].pi_id = CDF_GETUINT32(p, i << 1); 		inp[i].pi_type = CDF_GETUINT32(q, 0); 		DPRINTF(("%" SIZE_T_FORMAT "u) id=%x type=%x offs=0x%tx,0x%x\n",@@ -905,12 +935,12 @@ 				DPRINTF(("CDF_VECTOR with nelements == 0\n")); 				goto out; 			}-			o = 2;+			slen = 2; 		} else { 			nelements = 1;-			o = 1;+			slen = 1; 		}-		o4 = o * sizeof(uint32_t);+		o4 = slen * sizeof(uint32_t); 		if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED)) 			goto unknown; 		switch (inp[i].pi_type & CDF_TYPEMASK) {@@ -966,16 +996,10 @@ 		case CDF_LENGTH32_WSTRING: 			if (nelements > 1) { 				size_t nelem = inp - *info;-				if (*maxcount > CDF_PROP_LIMIT-				    || nelements > CDF_PROP_LIMIT)-					goto out;-				*maxcount += nelements;-				inp = CAST(cdf_property_info_t *,-				    realloc(*info, *maxcount * sizeof(*inp)));+				inp = cdf_grow_info(info, maxcount, nelements); 				if (inp == NULL)-					goto out1;-				*info = inp;-				inp = *info + nelem;+					goto out;+				inp += nelem; 			} 			DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n", 			    nelements));@@ -984,28 +1008,28 @@ 			{ 				uint32_t l; -				if (q + o + sizeof(uint32_t) >= e)+				if (q + slen + sizeof(uint32_t) >= e) 					goto out; -				l = CDF_GETUINT32(q, o);+				l = CDF_GETUINT32(q, slen); 				o4 += sizeof(uint32_t);-				if (q + o4 + l >= e)+				if (o4 + l > CAST(size_t, e - q)) 					goto out;  				inp[i].pi_str.s_len = l; 				inp[i].pi_str.s_buf = CAST(const char *, 				    CAST(const void *, &q[o4])); -				DPRINTF(("l = %d, r = %" SIZE_T_FORMAT-				    "u, s = %s\n", l,-				    CDF_ROUND(l, sizeof(l)),+				DPRINTF(("o=%zu l=%d(%" SIZE_T_FORMAT+				    "u), t=%td s=%s\n", o4, l,+				    CDF_ROUND(l, sizeof(l)), e - q, 				    inp[i].pi_str.s_buf));  				if (l & 1) 					l++; -				o += l >> 1;-				o4 = o * sizeof(uint32_t);+				slen += l >> 1;+				o4 = slen * sizeof(uint32_t); 			} 			i--; 			break;@@ -1029,8 +1053,6 @@ 	return 0; out: 	errno = EFTYPE;-out1:-	free(*info); 	return -1; } 
 |