Browse Source

Cherry-pick several commits that obviously address some sort of security issues

Christoph Biedl 7 years ago
parent
commit
c88f1dc4b9
22 changed files with 1202 additions and 0 deletions
  1. 160 0
      debian/patches/cherry-pick.FILE5_30-01-g64e45647.more-cast-stuff.patch
  2. 16 0
      debian/patches/cherry-pick.FILE5_30-11-gb1b4efea.pr-598-off-by-one.patch
  3. 44 0
      debian/patches/cherry-pick.FILE5_30-12-g77a7041f.prevent-reading-beyond-our-buffer-when-compacting-whitespace-oss-fuzz.patch
  4. 16 0
      debian/patches/cherry-pick.FILE5_30-14-ga0b25417.use-the-correct-buffer-size-found-by-oss-fuzz.patch
  5. 39 0
      debian/patches/cherry-pick.FILE5_30-18-g4e4e7609.pr-599-out-of-bounds-read-in-cdf-files.patch
  6. 91 0
      debian/patches/cherry-pick.FILE5_30-19-g7605984c.although-i-can-t-reproduce-it-oss-fuzz-complains-about-is-tar.patch
  7. 26 0
      debian/patches/cherry-pick.FILE5_30-22-ged0542b8.better-fix-for-previous.patch
  8. 238 0
      debian/patches/cherry-pick.FILE5_30-28-g393555f2.try-to-clean-this-up-the-vector-code-is-still-fishy.patch
  9. 65 0
      debian/patches/cherry-pick.FILE5_30-29-g76c2d4ae.several-fixes-in-cdf-parser.patch
  10. 18 0
      debian/patches/cherry-pick.FILE5_30-30-gc703aa9f.free-memory-on-error.patch
  11. 125 0
      debian/patches/cherry-pick.FILE5_30-34-g22067c96.simplify-the-property-info-copy-function-and-check-for-bounds.patch
  12. 15 0
      debian/patches/cherry-pick.FILE5_30-38-gfd42e119.if-we-could-not-read-a-field-set-it-to-0-found-by-oss-fuzz.patch
  13. 16 0
      debian/patches/cherry-pick.FILE5_30-39-geb973428.limit-memory-usage-more-to-satisfy-oss-fuzz.patch
  14. 18 0
      debian/patches/cherry-pick.FILE5_30-41-g393dafa4.work-around-glibc-regex-msan-bug-regexec-returns-0-but-does-initialize-pmatch.patch
  15. 27 0
      debian/patches/cherry-pick.FILE5_30-42-gf0bcdd07.dont-try-to-read-past-the-end-of-the-properties-found-by-oss-fuzz.patch
  16. 27 0
      debian/patches/cherry-pick.FILE5_30-43-g19ccebaf.dont-copy-the-string-past-its-length-oss-fuzz.patch
  17. 28 0
      debian/patches/cherry-pick.FILE5_30-46-g1fa18af6.check-read-bounds-for-vector-before-reading.patch
  18. 27 0
      debian/patches/cherry-pick.FILE5_30-47-gdc067431.fix-continuation-level-handling.patch
  19. 16 0
      debian/patches/cherry-pick.FILE5_30-48-gaee11eef.fix-out-of-bounds-read-found-by-oss-fuzz.patch
  20. 146 0
      debian/patches/cherry-pick.FILE5_30-49-gbf90083a.fix-memory-handling.patch
  21. 23 0
      debian/patches/cherry-pick.FILE5_30-52-gd8233d09.check-one-more-read-found-by-oss-fuzz.patch
  22. 21 0
      debian/patches/series

+ 160 - 0
debian/patches/cherry-pick.FILE5_30-01-g64e45647.more-cast-stuff.patch

@@ -0,0 +1,160 @@
+Subject: More cast stuff
+Origin: FILE5_30-1-g64e45647
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Feb 10 18:14:01 2017 +0000
+
+--- a/src/apprentice.c
++++ b/src/apprentice.c
+@@ -549,8 +549,10 @@
+ 		break;
+ 	case MAP_TYPE_MALLOC:
+ 		for (i = 0; i < MAGIC_SETS; i++) {
+-			if ((char *)map->magic[i] >= (char *)map->p &&
+-			    (char *)map->magic[i] <= (char *)map->p + map->len)
++			void *b = map->magic[i];
++			void *p = map->p;
++			if (CAST(char *, b) >= CAST(char *, p) &&
++			    CAST(char *, b) <= CAST(char *, p) + map->len)
+ 				continue;
+ 			free(map->magic[i]);
+ 		}
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -811,7 +811,7 @@
+ 		    == 0)
+ 			break;
+ 	if (i > 0)
+-		return i;
++		return CAST(int, i);
+ 
+ 	DPRINTF(("Cannot find type %d `%s'\n", type, name));
+ 	errno = ESRCH;
+@@ -1068,7 +1068,7 @@
+ {
+ 	size_t ss = cdf_check_stream(sst, h);
+ 	const char *b = CAST(const char *, sst->sst_tab);
+-	const char *eb = b + ss * sst->sst_len;
++	const char *nb, *eb = b + ss * sst->sst_len;
+ 	size_t nr, i, j, k;
+ 	cdf_catalog_entry_t *ce;
+ 	uint16_t reclen;
+@@ -1113,7 +1113,9 @@
+ 			cep->ce_namlen = rlen;
+ 
+ 		np = CAST(const uint16_t *, CAST(const void *, (b + 16)));
+-		if (RCAST(const char *, np + cep->ce_namlen) > eb) {
++		nb = CAST(const char *, CAST(const void *,
++		    (np + cep->ce_namlen)));
++		if (nb > eb) {
+ 			cep->ce_namlen = 0;
+ 			break;
+ 		}
+--- a/src/compress.c
++++ b/src/compress.c
+@@ -94,7 +94,7 @@
+ zlibcmp(const unsigned char *buf)
+ {
+ 	unsigned short x = 1;
+-	unsigned char *s = (unsigned char *)&x;
++	unsigned char *s = CCAST(unsigned char *, &x);
+ 
+ 	if ((buf[0] & 0xf) != 8 || (buf[0] & 0x80) != 0)
+ 		return 0;
+@@ -498,7 +498,7 @@
+ 	z.next_in = CCAST(Bytef *, old);
+ 	z.avail_in = CAST(uint32_t, *n);
+ 	z.next_out = *newch;
+-	z.avail_out = bytes_max;
++	z.avail_out = CAST(unsigned int, bytes_max);
+ 	z.zalloc = Z_NULL;
+ 	z.zfree = Z_NULL;
+ 	z.opaque = Z_NULL;
+@@ -633,7 +633,7 @@
+ 		while (isspace((unsigned char)*p))
+ 			p++;
+ 		n = strlen(p);
+-		memmove(ubuf, p, n + 1);
++		memmove(ubuf, p, CAST(size_t, n + 1));
+ 	}
+ 	DPRINTF("Filter error after[[[%s]]]\n", (char *)ubuf);
+ 	if (islower(*ubuf))
+@@ -689,7 +689,7 @@
+ 		}
+ 		
+ 		for (i = 0; i < __arraycount(fdp); i++)
+-			copydesc(i, fdp[i]);
++			copydesc(CAST(int, i), fdp[i]);
+ 
+ 		(void)execvp(compr[method].argv[0],
+ 		    (char *const *)(intptr_t)compr[method].argv);
+--- a/src/der.c
++++ b/src/der.c
+@@ -201,7 +201,7 @@
+ 
+ 	if (*p + len >= l)
+ 		return DER_BAD;
+-	return len;
++	return CAST(uint32_t, len);
+ }
+ 
+ static const char *
+@@ -260,12 +260,12 @@
+ #endif
+ 	if (m->cont_level != 0) {
+ 		if (offs + tlen > nbytes)
+-			return DER_BAD;
+-		ms->c.li[m->cont_level - 1].off = offs + tlen;
++			return -1;
++		ms->c.li[m->cont_level - 1].off = CAST(int, offs + tlen);
+ 		DPRINTF(("cont_level[%u] = %u\n", m->cont_level - 1,
+ 		    ms->c.li[m->cont_level - 1].off));
+ 	}
+-	return offs;
++	return CAST(int32_t, offs);
+ }
+ 
+ int
+--- a/src/print.c
++++ b/src/print.c
+@@ -238,7 +238,7 @@
+ 
+ 	if (flags & FILE_T_WINDOWS) {
+ 		struct timespec ts;
+-		cdf_timestamp_to_timespec(&ts, v);
++		cdf_timestamp_to_timespec(&ts, CAST(cdf_timestamp_t, v));
+ 		t = ts.tv_sec;
+ 	} else {
+ 		// XXX: perhaps detect and print something if overflow
+--- a/src/readelf.c
++++ b/src/readelf.c
+@@ -890,7 +890,7 @@
+ 
+ 	offset = get_offset_from_virtaddr(ms, swap, clazz, fd, ph_off, ph_num,
+ 	    fsize, virtaddr);
+-	if ((buflen = pread(fd, buf, buflen, offset)) <= 0) {
++	if ((buflen = pread(fd, buf, CAST(size_t, buflen), offset)) <= 0) {
+ 		file_badread(ms);
+ 		return 0;
+ 	}
+--- a/src/softmagic.c
++++ b/src/softmagic.c
+@@ -1017,9 +1017,8 @@
+ mconvert(struct magic_set *ms, struct magic *m, int flip)
+ {
+ 	union VALUETYPE *p = &ms->ms_value;
+-	uint8_t type;
+ 
+-	switch (type = cvt_flip(m->type, flip)) {
++	switch (cvt_flip(m->type, flip)) {
+ 	case FILE_BYTE:
+ 		if (cvt_8(p, m) == -1)
+ 			goto out;
+@@ -1184,7 +1183,7 @@
+ 		case FILE_DER:
+ 		case FILE_SEARCH:
+ 			if (offset > nbytes)
+-				offset = nbytes;
++				offset = CAST(uint32_t, nbytes);
+ 			ms->search.s = RCAST(const char *, s) + offset;
+ 			ms->search.s_len = nbytes - offset;
+ 			ms->search.offset = offset;

+ 16 - 0
debian/patches/cherry-pick.FILE5_30-11-gb1b4efea.pr-598-off-by-one.patch

@@ -0,0 +1,16 @@
+Subject: PR/598: Off-by-one
+Origin: FILE5_30-11-gb1b4efea
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Tue Mar 7 22:36:10 2017 +0000
+
+--- a/src/softmagic.c
++++ b/src/softmagic.c
+@@ -1842,7 +1842,7 @@
+ 		v = 0;
+ 
+ 		for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
+-			if (slen + idx >= ms->search.s_len)
++			if (slen + idx > ms->search.s_len)
+ 				return 0;
+ 
+ 			v = file_strncmp(m->value.s, ms->search.s + idx, slen,

+ 44 - 0
debian/patches/cherry-pick.FILE5_30-12-g77a7041f.prevent-reading-beyond-our-buffer-when-compacting-whitespace-oss-fuzz.patch

@@ -0,0 +1,44 @@
+Subject: Prevent reading beyond our buffer when compacting whitespace (oss-fuzz)
+Origin: FILE5_30-12-g77a7041f
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Wed Mar 8 20:45:35 2017 +0000
+
+--- a/src/softmagic.c
++++ b/src/softmagic.c
+@@ -1632,6 +1632,7 @@
+ 	 */
+ 	const unsigned char *a = (const unsigned char *)s1;
+ 	const unsigned char *b = (const unsigned char *)s2;
++	const unsigned char *eb = b + len;
+ 	uint64_t v;
+ 
+ 	/*
+@@ -1646,6 +1647,10 @@
+ 	}
+ 	else { /* combine the others */
+ 		while (len-- > 0) {
++			if (b >= eb) {
++				v = 1;
++				break;
++			}
+ 			if ((flags & STRING_IGNORE_LOWERCASE) &&
+ 			    islower(*a)) {
+ 				if ((v = tolower(*b++) - *a++) != '\0')
+@@ -1661,7 +1666,7 @@
+ 				a++;
+ 				if (isspace(*b++)) {
+ 					if (!isspace(*a))
+-						while (isspace(*b))
++						while (b < eb && isspace(*b))
+ 							b++;
+ 				}
+ 				else {
+@@ -1672,7 +1677,7 @@
+ 			else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) &&
+ 			    isspace(*a)) {
+ 				a++;
+-				while (isspace(*b))
++				while (b < eb && isspace(*b))
+ 					b++;
+ 			}
+ 			else {

+ 16 - 0
debian/patches/cherry-pick.FILE5_30-14-ga0b25417.use-the-correct-buffer-size-found-by-oss-fuzz.patch

@@ -0,0 +1,16 @@
+Subject: Use the correct buffer size; found by oss-fuzz
+Origin: FILE5_30-14-ga0b25417
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Thu Mar 9 16:57:53 2017 +0000
+
+--- a/src/readcdf.c
++++ b/src/readcdf.c
+@@ -603,7 +603,7 @@
+ 	if ((i = cdf_read_user_stream(&info, &h, &sat, &ssat, &sst, &dir,
+ 	    "FileHeader", &scn)) != -1) {
+ #define HWP5_SIGNATURE "HWP Document File"
+-		if (scn.sst_dirlen >= sizeof(HWP5_SIGNATURE) - 1
++		if (scn.sst_len * scn.sst_ss >= sizeof(HWP5_SIGNATURE) - 1
+ 		    && memcmp(scn.sst_tab, HWP5_SIGNATURE,
+ 		    sizeof(HWP5_SIGNATURE) - 1) == 0) {
+ 		    if (NOTMIME(ms)) {

+ 39 - 0
debian/patches/cherry-pick.FILE5_30-18-g4e4e7609.pr-599-out-of-bounds-read-in-cdf-files.patch

@@ -0,0 +1,39 @@
+Subject: PR/599: Out of bounds read in cdf files
+Origin: FILE5_30-18-g4e4e7609
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Mar 17 19:50:22 2017 +0000
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -982,19 +982,26 @@
+ 			for (j = 0; j < nelements && i < sh.sh_properties;
+ 			    j++, i++)
+ 			{
+-				uint32_t l = CDF_GETUINT32(q, o);
++				uint32_t l;
++
++				o4 += sizeof(uint32_t);
++				if (q + o >= e || q + o4 >= e)
++					goto out;
++
++				l = CDF_GETUINT32(q, o);
+ 				inp[i].pi_str.s_len = l;
+-				inp[i].pi_str.s_buf = (const char *)
+-				    (const void *)(&q[o4 + sizeof(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)),
+ 				    inp[i].pi_str.s_buf));
++
+ 				if (l & 1)
+ 					l++;
++
+ 				o += l >> 1;
+-				if (q + o >= e)
+-					goto out;
+ 				o4 = o * sizeof(uint32_t);
+ 			}
+ 			i--;

+ 91 - 0
debian/patches/cherry-pick.FILE5_30-19-g7605984c.although-i-can-t-reproduce-it-oss-fuzz-complains-about-is-tar.patch

@@ -0,0 +1,91 @@
+Subject: Although I can't reproduce it, oss-fuzz complains about is_tar
+Origin: FILE5_30-19-g7605984c
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Mar 17 20:45:01 2017 +0000
+
+    Although I can't reproduce it, oss-fuzz complains about is_tar. So rewrite
+    it to make it more obvious what's going on.
+
+--- a/src/is_tar.c
++++ b/src/is_tar.c
+@@ -51,7 +51,7 @@
+ #define	isodigit(c)	( ((c) >= '0') && ((c) <= '7') )
+ 
+ private int is_tar(const unsigned char *, size_t);
+-private int from_oct(int, const char *);	/* Decode octal number */
++private int from_oct(const char *, size_t);	/* Decode octal number */
+ 
+ static const char tartype[][32] = {
+ 	"tar archive",
+@@ -93,31 +93,35 @@
+ is_tar(const unsigned char *buf, size_t nbytes)
+ {
+ 	const union record *header = (const union record *)(const void *)buf;
+-	int	i;
+-	int	sum, recsum;
+-	const unsigned char	*p;
++	size_t i;
++	int sum, recsum;
++	const unsigned char *p, *ep;
+ 
+-	if (nbytes < sizeof(union record))
++	if (nbytes < sizeof(*header))
+ 		return 0;
+ 
+-	recsum = from_oct(8,  header->header.chksum);
++	recsum = from_oct(header->header.chksum, sizeof(header->header.chksum));
+ 
+ 	sum = 0;
+ 	p = header->charptr;
+-	for (i = sizeof(union record); --i >= 0;)
++	ep = header->charptr + sizeof(*header);
++	while (p < ep)
+ 		sum += *p++;
+ 
+ 	/* Adjust checksum to count the "chksum" field as blanks. */
+-	for (i = sizeof(header->header.chksum); --i >= 0;)
++	for (i = 0; i < sizeof(header->header.chksum); i++)
+ 		sum -= header->header.chksum[i];
+-	sum += ' ' * sizeof header->header.chksum;
++	sum += ' ' * sizeof(header->header.chksum);
+ 
+ 	if (sum != recsum)
+ 		return 0;	/* Not a tar archive */
+ 
+-	if (strcmp(header->header.magic, GNUTMAGIC) == 0)
++	if (strncmp(header->header.magic, GNUTMAGIC,
++	    sizeof(header->header.magic)) == 0)
+ 		return 3;		/* GNU Unix Standard tar archive */
+-	if (strcmp(header->header.magic, TMAGIC) == 0)
++
++	if (strncmp(header->header.magic, TMAGIC,
++	    sizeof(header->header.magic)) == 0)
+ 		return 2;		/* Unix Standard tar archive */
+ 
+ 	return 1;			/* Old fashioned tar archive */
+@@ -130,19 +134,22 @@
+  * Result is -1 if the field is invalid (all blank, or non-octal).
+  */
+ private int
+-from_oct(int digs, const char *where)
++from_oct(const char *where, size_t digs)
+ {
+ 	int	value;
+ 
++	if (digs == 0)
++		return -1;
++
+ 	while (isspace((unsigned char)*where)) {	/* Skip spaces */
+ 		where++;
+-		if (--digs <= 0)
++		if (digs-- == 0)
+ 			return -1;		/* All blank field */
+ 	}
+ 	value = 0;
+ 	while (digs > 0 && isodigit(*where)) {	/* Scan til non-octal */
+ 		value = (value << 3) | (*where++ - '0');
+-		--digs;
++		digs--;
+ 	}
+ 
+ 	if (digs > 0 && *where && !isspace((unsigned char)*where))

+ 26 - 0
debian/patches/cherry-pick.FILE5_30-22-ged0542b8.better-fix-for-previous.patch

@@ -0,0 +1,26 @@
+Subject: Better fix for previous
+Origin: FILE5_30-22-ged0542b8
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Mar 17 23:56:16 2017 +0000
+
+    [ refers to FILE5_30-19-g7605984c -CB ]
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -984,11 +984,14 @@
+ 			{
+ 				uint32_t l;
+ 
+-				o4 += sizeof(uint32_t);
+-				if (q + o >= e || q + o4 >= e)
++				if (q + o + sizeof(uint32_t) >= e)
+ 					goto out;
+ 
+ 				l = CDF_GETUINT32(q, o);
++				o4 += sizeof(uint32_t);
++				if (q + o4 + l >= e)
++					goto out;
++
+ 				inp[i].pi_str.s_len = l;
+ 				inp[i].pi_str.s_buf = CAST(const char *,
+ 				    CAST(const void *, &q[o4]));

+ 238 - 0
debian/patches/cherry-pick.FILE5_30-28-g393555f2.try-to-clean-this-up-the-vector-code-is-still-fishy.patch

@@ -0,0 +1,238 @@
+Subject: Try to clean this up; the vector code is still fishy
+Origin: FILE5_30-28-g393555f2
+Upstream-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;
+ }
+ 

+ 65 - 0
debian/patches/cherry-pick.FILE5_30-29-g76c2d4ae.several-fixes-in-cdf-parser.patch

@@ -0,0 +1,65 @@
+Subject: [ Several fixes in the cdf parser ]
+Origin: FILE5_30-29-g76c2d4ae
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Mon Mar 27 21:34:32 2017 +0000
+
+    - Check the stream offset for sh.sh_len to fit within the stream
+    - Fix wrong test (use o4 instead of slen for offset).
+    - Use left variable to keep track of how many bytes are left.
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -891,7 +891,7 @@
+ 	int64_t s64;
+ 	uint64_t u64;
+ 	cdf_timestamp_t tp;
+-	size_t i, o4, nelements, j, slen;
++	size_t i, o4, nelements, j, slen, left;
+ 	cdf_property_info_t *inp;
+ 
+ 	if (offs > UINT32_MAX / 4) {
+@@ -907,6 +907,10 @@
+ 		errno = EFTYPE;
+ 		goto out;
+ 	}
++
++	if (cdf_check_stream_offset(sst, h, shp, sh.sh_len, __LINE__) == -1)
++		goto out;
++
+ 	sh.sh_properties = CDF_TOLE4(shp->sh_properties);
+ 	if (sh.sh_properties > CDF_PROP_LIMIT)
+ 		goto out;
+@@ -940,6 +944,7 @@
+ 			nelements = 1;
+ 			slen = 1;
+ 		}
++		left = CAST(size_t, e - q);
+ 		o4 = slen * sizeof(uint32_t);
+ 		if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED))
+ 			goto unknown;
+@@ -1008,12 +1013,12 @@
+ 			{
+ 				uint32_t l;
+ 
+-				if (q + slen + sizeof(uint32_t) >= e)
++				if (o4 + sizeof(uint32_t) > left)
+ 					goto out;
+ 
+ 				l = CDF_GETUINT32(q, slen);
+ 				o4 += sizeof(uint32_t);
+-				if (o4 + l > CAST(size_t, e - q))
++				if (o4 + l > left)
+ 					goto out;
+ 
+ 				inp[i].pi_str.s_len = l;
+@@ -1021,8 +1026,8 @@
+ 				    CAST(const void *, &q[o4]));
+ 
+ 				DPRINTF(("o=%zu l=%d(%" SIZE_T_FORMAT
+-				    "u), t=%td s=%s\n", o4, l,
+-				    CDF_ROUND(l, sizeof(l)), e - q,
++				    "u), t=%zu s=%s\n", o4, l,
++				    CDF_ROUND(l, sizeof(l)), left,
+ 				    inp[i].pi_str.s_buf));
+ 
+ 				if (l & 1)

+ 18 - 0
debian/patches/cherry-pick.FILE5_30-30-gc703aa9f.free-memory-on-error.patch

@@ -0,0 +1,18 @@
+Subject: Free memory on error
+Origin: FILE5_30-30-gc703aa9f
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Tue Mar 28 15:13:07 2017 +0000
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -1057,6 +1057,10 @@
+ 	}
+ 	return 0;
+ out:
++	free(*info);
++	*info = NULL;
++	*count = 0;
++	*maxcount = 0;
+ 	errno = EFTYPE;
+ 	return -1;
+ }

+ 125 - 0
debian/patches/cherry-pick.FILE5_30-34-g22067c96.simplify-the-property-info-copy-function-and-check-for-bounds.patch

@@ -0,0 +1,125 @@
+Subject: Simplify the property info copy function and check for bounds
+Origin: FILE5_30-34-g22067c96
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Wed Mar 29 19:45:22 2017 +0000
+
+    Found by oss-fuzz.
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -878,6 +878,34 @@
+ 	return NULL;
+ }
+ 
++static int
++cdf_copy_info(cdf_property_info_t *inp, const void *p, const void *e,
++    size_t len)
++{
++	if (inp->pi_type & CDF_VECTOR)
++		return 0;
++
++	if ((size_t)(CAST(const char *, e) - CAST(const char *, p)) < len)
++		return 0;
++
++	(void)memcpy(&inp->pi_val, p, len);
++
++	switch (len) {
++	case 2:
++		inp->pi_u16 = CDF_TOLE2(inp->pi_u16);
++		break;
++	case 4:
++		inp->pi_u32 = CDF_TOLE4(inp->pi_u32);
++		break;
++	case 8:
++		inp->pi_u64 = CDF_TOLE8(inp->pi_u64);
++		break;
++	default:
++		abort();
++	}
++	return 1;
++}
++
+ 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)
+@@ -885,12 +913,6 @@
+ 	const cdf_section_header_t *shp;
+ 	cdf_section_header_t sh;
+ 	const uint8_t *p, *q, *e;
+-	int16_t s16;
+-	int32_t s32;
+-	uint32_t u32;
+-	int64_t s64;
+-	uint64_t u64;
+-	cdf_timestamp_t tp;
+ 	size_t i, o4, nelements, j, slen, left;
+ 	cdf_property_info_t *inp;
+ 
+@@ -953,49 +975,22 @@
+ 		case CDF_EMPTY:
+ 			break;
+ 		case CDF_SIGNED16:
+-			if (inp[i].pi_type & CDF_VECTOR)
++			if (!cdf_copy_info(&inp[i], &q[o4], e, sizeof(int16_t)))
+ 				goto unknown;
+-			(void)memcpy(&s16, &q[o4], sizeof(s16));
+-			inp[i].pi_s16 = CDF_TOLE2(s16);
+ 			break;
+ 		case CDF_SIGNED32:
+-			if (inp[i].pi_type & CDF_VECTOR)
+-				goto unknown;
+-			(void)memcpy(&s32, &q[o4], sizeof(s32));
+-			inp[i].pi_s32 = CDF_TOLE4((uint32_t)s32);
+-			break;
+ 		case CDF_BOOL:
+ 		case CDF_UNSIGNED32:
+-			if (inp[i].pi_type & CDF_VECTOR)
++		case CDF_FLOAT:
++			if (!cdf_copy_info(&inp[i], &q[o4], e, sizeof(int32_t)))
+ 				goto unknown;
+-			(void)memcpy(&u32, &q[o4], sizeof(u32));
+-			inp[i].pi_u32 = CDF_TOLE4(u32);
+ 			break;
+ 		case CDF_SIGNED64:
+-			if (inp[i].pi_type & CDF_VECTOR)
+-				goto unknown;
+-			(void)memcpy(&s64, &q[o4], sizeof(s64));
+-			inp[i].pi_s64 = CDF_TOLE8((uint64_t)s64);
+-			break;
+ 		case CDF_UNSIGNED64:
+-			if (inp[i].pi_type & CDF_VECTOR)
+-				goto unknown;
+-			(void)memcpy(&u64, &q[o4], sizeof(u64));
+-			inp[i].pi_u64 = CDF_TOLE8((uint64_t)u64);
+-			break;
+-		case CDF_FLOAT:
+-			if (inp[i].pi_type & CDF_VECTOR)
+-				goto unknown;
+-			(void)memcpy(&u32, &q[o4], sizeof(u32));
+-			u32 = CDF_TOLE4(u32);
+-			memcpy(&inp[i].pi_f, &u32, sizeof(inp[i].pi_f));
+-			break;
+ 		case CDF_DOUBLE:
+-			if (inp[i].pi_type & CDF_VECTOR)
++		case CDF_FILETIME:
++			if (!cdf_copy_info(&inp[i], &q[o4], e, sizeof(int64_t)))
+ 				goto unknown;
+-			(void)memcpy(&u64, &q[o4], sizeof(u64));
+-			u64 = CDF_TOLE8((uint64_t)u64);
+-			memcpy(&inp[i].pi_d, &u64, sizeof(inp[i].pi_d));
+ 			break;
+ 		case CDF_LENGTH32_STRING:
+ 		case CDF_LENGTH32_WSTRING:
+@@ -1038,12 +1033,6 @@
+ 			}
+ 			i--;
+ 			break;
+-		case CDF_FILETIME:
+-			if (inp[i].pi_type & CDF_VECTOR)
+-				goto unknown;
+-			(void)memcpy(&tp, &q[o4], sizeof(tp));
+-			inp[i].pi_tp = CDF_TOLE8((uint64_t)tp);
+-			break;
+ 		case CDF_CLIPBOARD:
+ 			if (inp[i].pi_type & CDF_VECTOR)
+ 				goto unknown;

+ 15 - 0
debian/patches/cherry-pick.FILE5_30-38-gfd42e119.if-we-could-not-read-a-field-set-it-to-0-found-by-oss-fuzz.patch

@@ -0,0 +1,15 @@
+Subject: If we could not read a field, set it to 0; found by oss-fuzz
+Origin: FILE5_30-38-gfd42e119
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Thu Apr 6 19:20:35 2017 +0000
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -1039,6 +1039,7 @@
+ 			break;
+ 		default:
+ 		unknown:
++			memset(&inp[i].pi_val, 0, sizeof(inp[i].pi_val));
+ 			DPRINTF(("Don't know how to deal with %x\n",
+ 			    inp[i].pi_type));
+ 			break;

+ 16 - 0
debian/patches/cherry-pick.FILE5_30-39-geb973428.limit-memory-usage-more-to-satisfy-oss-fuzz.patch

@@ -0,0 +1,16 @@
+Subject: Limit memory usage more to satisfy oss-fuzz
+Origin: FILE5_30-39-geb973428
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Apr 7 15:07:31 2017 +0000
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -408,7 +408,7 @@
+ 		if (h->h_master_sat[i] == CDF_SECID_FREE)
+ 			break;
+ 
+-#define CDF_SEC_LIMIT (UINT32_MAX / (4 * ss))
++#define CDF_SEC_LIMIT (UINT32_MAX / (8 * ss))
+ 	if ((nsatpersec > 0 &&
+ 	    h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec) ||
+ 	    i > CDF_SEC_LIMIT) {

+ 18 - 0
debian/patches/cherry-pick.FILE5_30-41-g393dafa4.work-around-glibc-regex-msan-bug-regexec-returns-0-but-does-initialize-pmatch.patch

@@ -0,0 +1,18 @@
+Subject: Work around glibc/regex/msan bug regexec returns 0 but does initialize pmatch
+Origin: FILE5_30-41-g393dafa4
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Apr 7 20:10:24 2017 +0000
+
+    Found by oss-fuzz.
+
+--- a/src/funcs.c
++++ b/src/funcs.c
+@@ -509,6 +509,8 @@
+     regmatch_t* pmatch, int eflags)
+ {
+ 	assert(rx->rc == 0);
++	/* XXX: force initialization because glibc does not always do this */
++	memset(pmatch, 0, nmatch * sizeof(*pmatch));
+ 	return regexec(&rx->rx, str, nmatch, pmatch, eflags);
+ }
+ 

+ 27 - 0
debian/patches/cherry-pick.FILE5_30-42-gf0bcdd07.dont-try-to-read-past-the-end-of-the-properties-found-by-oss-fuzz.patch

@@ -0,0 +1,27 @@
+Subject: Don't try to read past the end of the properties, found by oss-fuzz
+Origin: FILE5_30-42-gf0bcdd07
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Sat Apr 8 20:38:46 2017 +0000
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -835,6 +835,10 @@
+ 	size_t ofs;
+ 	const uint8_t *q;
+ 
++	if (p >= e) {
++		DPRINTF(("Past end %p < %p\n", e, p));
++		return NULL;
++	}
+ 	if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t),
+ 	    __LINE__) == -1)
+ 		return NULL;
+@@ -945,7 +949,7 @@
+ 	*count += sh.sh_properties;
+ 	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)
++	if (p >= e || cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1)
+ 		goto out;
+ 
+ 	for (i = 0; i < sh.sh_properties; i++) {

+ 27 - 0
debian/patches/cherry-pick.FILE5_30-43-g19ccebaf.dont-copy-the-string-past-its-length-oss-fuzz.patch

@@ -0,0 +1,27 @@
+Subject: Don't copy the string past its length (oss-fuzz)
+Origin: FILE5_30-43-g19ccebaf
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Sat Apr 8 20:58:03 2017 +0000
+
+--- a/src/readcdf.c
++++ b/src/readcdf.c
+@@ -152,7 +152,7 @@
+         struct timespec ts;
+         char buf[64];
+         const char *str = NULL;
+-        const char *s;
++        const char *s, *e;
+         int len;
+ 
+         if (!NOTMIME(ms) && root_storage)
+@@ -199,7 +199,9 @@
+                                 if (info[i].pi_type == CDF_LENGTH32_WSTRING)
+                                     k++;
+                                 s = info[i].pi_str.s_buf;
+-                                for (j = 0; j < sizeof(vbuf) && len--; s += k) {
++				e = info[i].pi_str.s_buf + len;
++                                for (j = 0; s < e && j < sizeof(vbuf)
++				    && len--; s += k) {
+                                         if (*s == '\0')
+                                                 break;
+                                         if (isprint((unsigned char)*s))

+ 28 - 0
debian/patches/cherry-pick.FILE5_30-46-g1fa18af6.check-read-bounds-for-vector-before-reading.patch

@@ -0,0 +1,28 @@
+Subject: Check read bounds for vector before reading. Found by oss-fuzz
+Origin: FILE5_30-46-g1fa18af6
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Wed Apr 12 14:57:22 2017 +0000
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -959,7 +959,12 @@
+ 		inp[i].pi_type = CDF_GETUINT32(q, 0);
+ 		DPRINTF(("%" SIZE_T_FORMAT "u) id=%x type=%x offs=0x%tx,0x%x\n",
+ 		    i, inp[i].pi_id, inp[i].pi_type, q - p, offs));
++		left = CAST(size_t, e - q);
+ 		if (inp[i].pi_type & CDF_VECTOR) {
++			if (left < sizeof(uint32_t)) {
++				DPRINTF(("missing CDF_VECTOR length\n"));
++				goto out;
++			}
+ 			nelements = CDF_GETUINT32(q, 1);
+ 			if (nelements == 0) {
+ 				DPRINTF(("CDF_VECTOR with nelements == 0\n"));
+@@ -970,7 +975,6 @@
+ 			nelements = 1;
+ 			slen = 1;
+ 		}
+-		left = CAST(size_t, e - q);
+ 		o4 = slen * sizeof(uint32_t);
+ 		if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED))
+ 			goto unknown;

+ 27 - 0
debian/patches/cherry-pick.FILE5_30-47-gdc067431.fix-continuation-level-handling.patch

@@ -0,0 +1,27 @@
+Subject: [ Fix continuation level handling ]
+Origin: FILE5_30-47-gdc067431
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Apr 21 16:54:57 2017 +0000
+
+    - if we failed to get the offset at the current continuation level, reduce it
+    - reset continuation level on flush
+    Found by oss-fuzz
+
+--- a/src/softmagic.c
++++ b/src/softmagic.c
+@@ -192,6 +192,7 @@
+ 			while (magindex < nmagic - 1 &&
+ 			    magic[magindex + 1].cont_level != 0)
+ 				magindex++;
++			cont_level = 0;
+ 			continue; /* Skip to next top-level test*/
+ 		}
+ 
+@@ -370,6 +371,7 @@
+ 				case -1:
+ 				case 0:
+ 					flush = 1;
++					cont_level--;
+ 					break;
+ 				default:
+ 					break;

+ 16 - 0
debian/patches/cherry-pick.FILE5_30-48-gaee11eef.fix-out-of-bounds-read-found-by-oss-fuzz.patch

@@ -0,0 +1,16 @@
+Subject: Fix out of bounds read; found by oss-fuzz
+Origin: FILE5_30-48-gaee11eef
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Sat Apr 22 20:02:34 2017 +0000
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -961,7 +961,7 @@
+ 		    i, inp[i].pi_id, inp[i].pi_type, q - p, offs));
+ 		left = CAST(size_t, e - q);
+ 		if (inp[i].pi_type & CDF_VECTOR) {
+-			if (left < sizeof(uint32_t)) {
++			if (left < sizeof(uint32_t) * 2) {
+ 				DPRINTF(("missing CDF_VECTOR length\n"));
+ 				goto out;
+ 			}

+ 146 - 0
debian/patches/cherry-pick.FILE5_30-49-gbf90083a.fix-memory-handling.patch

@@ -0,0 +1,146 @@
+Subject: [ Fix memory handling ]
+Origin: FILE5_30-49-gbf90083a
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Mon Apr 24 18:57:35 2017 +0000
+
+    - centralize allocation so we can easily find out where things are done
+    - limit property list memory limit further for oss-fuzz.
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -80,6 +80,28 @@
+ 			    CDF_TOLE8(CAST(uint64_t, x))))
+ #define CDF_GETUINT32(x, y)	cdf_getuint32(x, y)
+ 
++#define CDF_MALLOC(n) cdf_malloc(__FILE__, __LINE__, (n))
++#define CDF_REALLOC(p, n) cdf_realloc(__FILE__, __LINE__, (p), (n))
++#define CDF_CALLOC(n, u) cdf_calloc(__FILE__, __LINE__, (n), (u))
++
++
++static void *
++cdf_malloc(const char *file, size_t line, size_t n) {
++	DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n));
++	return malloc(n);
++}
++
++static void *
++cdf_realloc(const char *file, size_t line, void *p, size_t n) {
++	DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n));
++	return realloc(p, n);
++}
++
++static void *
++cdf_calloc(const char *file, size_t line, size_t n, size_t u) {
++	DPRINTF(("%s,%zu: %s %zu %zu\n", file, line, __func__, n, u));
++	return calloc(n, u);
++}
+ 
+ /*
+  * swap a short
+@@ -421,7 +443,7 @@
+ 	sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i;
+ 	DPRINTF(("sat_len = %" SIZE_T_FORMAT "u ss = %" SIZE_T_FORMAT "u\n",
+ 	    sat->sat_len, ss));
+-	if ((sat->sat_tab = CAST(cdf_secid_t *, calloc(sat->sat_len, ss)))
++	if ((sat->sat_tab = CAST(cdf_secid_t *, CDF_CALLOC(sat->sat_len, ss)))
+ 	    == NULL)
+ 		return -1;
+ 
+@@ -435,7 +457,7 @@
+ 		}
+ 	}
+ 
+-	if ((msa = CAST(cdf_secid_t *, calloc(1, ss))) == NULL)
++	if ((msa = CAST(cdf_secid_t *, CDF_CALLOC(1, ss))) == NULL)
+ 		goto out1;
+ 
+ 	mid = h->h_secid_first_sector_in_master_sat;
+@@ -536,7 +558,7 @@
+ 	if (scn->sst_len == (size_t)-1)
+ 		goto out;
+ 
+-	scn->sst_tab = calloc(scn->sst_len, ss);
++	scn->sst_tab = CDF_CALLOC(scn->sst_len, ss);
+ 	if (scn->sst_tab == NULL)
+ 		return cdf_zero_stream(scn);
+ 
+@@ -582,7 +604,7 @@
+ 	if (scn->sst_len == (size_t)-1)
+ 		goto out;
+ 
+-	scn->sst_tab = calloc(scn->sst_len, ss);
++	scn->sst_tab = CDF_CALLOC(scn->sst_len, ss);
+ 	if (scn->sst_tab == NULL)
+ 		return cdf_zero_stream(scn);
+ 
+@@ -640,11 +662,11 @@
+ 
+ 	dir->dir_len = ns * nd;
+ 	dir->dir_tab = CAST(cdf_directory_t *,
+-	    calloc(dir->dir_len, sizeof(dir->dir_tab[0])));
++	    CDF_CALLOC(dir->dir_len, sizeof(dir->dir_tab[0])));
+ 	if (dir->dir_tab == NULL)
+ 		return -1;
+ 
+-	if ((buf = CAST(char *, malloc(ss))) == NULL) {
++	if ((buf = CAST(char *, CDF_MALLOC(ss))) == NULL) {
+ 		free(dir->dir_tab);
+ 		return -1;
+ 	}
+@@ -690,7 +712,7 @@
+ 	if (ssat->sat_len == (size_t)-1)
+ 		goto out;
+ 
+-	ssat->sat_tab = CAST(cdf_secid_t *, calloc(ssat->sat_len, ss));
++	ssat->sat_tab = CAST(cdf_secid_t *, CDF_CALLOC(ssat->sat_len, ss));
+ 	if (ssat->sat_tab == NULL)
+ 		goto out1;
+ 
+@@ -819,7 +841,7 @@
+ }
+ 
+ #define CDF_SHLEN_LIMIT (UINT32_MAX / 8)
+-#define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(cdf_property_info_t)))
++#define CDF_PROP_LIMIT (UINT32_MAX / (8 * sizeof(cdf_property_info_t)))
+ 
+ static const void *
+ cdf_offset(const void *p, size_t l)
+@@ -864,11 +886,13 @@
+ 	cdf_property_info_t *inp;
+ 	size_t newcount = *maxcount + incr;
+ 
+-	if (newcount > CDF_PROP_LIMIT)
++	if (newcount > CDF_PROP_LIMIT) {
++		DPRINTF(("exceeded property limit %zu > %zu\n", 
++		    newcount, CDF_PROP_LIMIT));
+ 		goto out;
+-	
++	}
+ 	inp = CAST(cdf_property_info_t *,
+-	    realloc(*info, newcount * sizeof(*inp)));
++	    CDF_REALLOC(*info, newcount * sizeof(*inp)));
+ 	if (inp == NULL)
+ 		goto out;
+ 
+@@ -938,10 +962,10 @@
+ 		goto out;
+ 
+ 	sh.sh_properties = CDF_TOLE4(shp->sh_properties);
+-	if (sh.sh_properties > CDF_PROP_LIMIT)
+-		goto out;
+ 	DPRINTF(("section len: %u properties %u\n", sh.sh_len,
+ 	    sh.sh_properties));
++	if (sh.sh_properties > CDF_PROP_LIMIT)
++		goto out;
+ 	inp = cdf_grow_info(info, maxcount, sh.sh_properties);
+ 	if (inp == NULL)
+ 		goto out;
+@@ -1126,7 +1150,7 @@
+ 		return -1;
+ 	nr--;
+ 	*cat = CAST(cdf_catalog_t *,
+-	    malloc(sizeof(cdf_catalog_t) + nr * sizeof(*ce)));
++	    CDF_MALLOC(sizeof(cdf_catalog_t) + nr * sizeof(*ce)));
+ 	if (*cat == NULL)
+ 		return -1;
+ 	ce = (*cat)->cat_e;

+ 23 - 0
debian/patches/cherry-pick.FILE5_30-52-gd8233d09.check-one-more-read-found-by-oss-fuzz.patch

@@ -0,0 +1,23 @@
+Subject: Check one more read (found by oss-fuzz)
+Origin: FILE5_30-52-gd8233d09
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Apr 28 15:03:47 2017 +0000
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -980,10 +980,14 @@
+ 		if ((q = cdf_get_property_info_pos(sst, h, p, e, i)) == NULL)
+ 			goto out;
+ 		inp[i].pi_id = CDF_GETUINT32(p, i << 1);
++		left = CAST(size_t, e - q);
++		if (left < sizeof(uint32_t)) {
++			DPRINTF(("short info (no type)_\n"));
++			goto out;
++		}
+ 		inp[i].pi_type = CDF_GETUINT32(q, 0);
+ 		DPRINTF(("%" SIZE_T_FORMAT "u) id=%x type=%x offs=0x%tx,0x%x\n",
+ 		    i, inp[i].pi_id, inp[i].pi_type, q - p, offs));
+-		left = CAST(size_t, e - q);
+ 		if (inp[i].pi_type & CDF_VECTOR) {
+ 			if (left < sizeof(uint32_t) * 2) {
+ 				DPRINTF(("missing CDF_VECTOR length\n"));

+ 21 - 0
debian/patches/series

@@ -3,6 +3,27 @@ revert.FILE5_29-39-g0e78a704.pr-591-print-if-the-file-has-debug-info.patch
 revert.FILE5_29-46-g53b8d4b0.add-ips-magic.patch
 
 # cherry-picked commits. Keep in upstream's chronological order
+cherry-pick.FILE5_30-01-g64e45647.more-cast-stuff.patch
+cherry-pick.FILE5_30-11-gb1b4efea.pr-598-off-by-one.patch
+cherry-pick.FILE5_30-12-g77a7041f.prevent-reading-beyond-our-buffer-when-compacting-whitespace-oss-fuzz.patch
+cherry-pick.FILE5_30-14-ga0b25417.use-the-correct-buffer-size-found-by-oss-fuzz.patch
+cherry-pick.FILE5_30-18-g4e4e7609.pr-599-out-of-bounds-read-in-cdf-files.patch
+cherry-pick.FILE5_30-19-g7605984c.although-i-can-t-reproduce-it-oss-fuzz-complains-about-is-tar.patch
+cherry-pick.FILE5_30-22-ged0542b8.better-fix-for-previous.patch
+cherry-pick.FILE5_30-28-g393555f2.try-to-clean-this-up-the-vector-code-is-still-fishy.patch
+cherry-pick.FILE5_30-29-g76c2d4ae.several-fixes-in-cdf-parser.patch
+cherry-pick.FILE5_30-30-gc703aa9f.free-memory-on-error.patch
+cherry-pick.FILE5_30-34-g22067c96.simplify-the-property-info-copy-function-and-check-for-bounds.patch
+cherry-pick.FILE5_30-38-gfd42e119.if-we-could-not-read-a-field-set-it-to-0-found-by-oss-fuzz.patch
+cherry-pick.FILE5_30-39-geb973428.limit-memory-usage-more-to-satisfy-oss-fuzz.patch
+cherry-pick.FILE5_30-41-g393dafa4.work-around-glibc-regex-msan-bug-regexec-returns-0-but-does-initialize-pmatch.patch
+cherry-pick.FILE5_30-42-gf0bcdd07.dont-try-to-read-past-the-end-of-the-properties-found-by-oss-fuzz.patch
+cherry-pick.FILE5_30-43-g19ccebaf.dont-copy-the-string-past-its-length-oss-fuzz.patch
+cherry-pick.FILE5_30-46-g1fa18af6.check-read-bounds-for-vector-before-reading.patch
+cherry-pick.FILE5_30-47-gdc067431.fix-continuation-level-handling.patch
+cherry-pick.FILE5_30-48-gaee11eef.fix-out-of-bounds-read-found-by-oss-fuzz.patch
+cherry-pick.FILE5_30-49-gbf90083a.fix-memory-handling.patch
+cherry-pick.FILE5_30-52-gd8233d09.check-one-more-read-found-by-oss-fuzz.patch
 
 # local modifications
 local.support-local-definitions-in-etc-magic.patch