Mercurial > hg
changeset 4358:11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
- fix off by 11 when checking if there are more hunks (found by Maris Fogels)
- bail out if start is greater than end
- check if new hunk starts after start/end/len block of current hunk as
the pointer can wrap around on very large values, reproducible with
import mpatch; mpatch.patchedsize(12, 'x'*12)
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Sat, 27 Jan 2007 23:07:06 +0100 |
parents | 3f1b0c0fb4fd |
children | 80d3f6f0d8e5 4759da3e4dc8 |
files | mercurial/mpatch.c |
diffstat | 1 files changed, 18 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/mpatch.c Tue Apr 24 10:44:13 2007 -0700 +++ b/mercurial/mpatch.c Sat Jan 27 23:07:06 2007 +0100 @@ -221,7 +221,7 @@ { struct flist *l; struct frag *lt; - char *end = bin + len; + char *data = bin + 12, *end = bin + len; char decode[12]; /* for dealing with alignment issues */ /* assume worst case size, we won't have many of these lists */ @@ -231,13 +231,18 @@ lt = l->tail; - while (bin < end) { + while (data <= end) { memcpy(decode, bin, 12); lt->start = ntohl(*(uint32_t *)decode); lt->end = ntohl(*(uint32_t *)(decode + 4)); lt->len = ntohl(*(uint32_t *)(decode + 8)); - lt->data = bin + 12; - bin += 12 + lt->len; + if (lt->start > lt->end) + break; /* sanity check */ + bin = data + lt->len; + if (bin < data) + break; /* big data + big (bogus) len can wrap around */ + lt->data = data; + data = bin + 12; lt++; } @@ -367,20 +372,26 @@ { long orig, start, end, len, outlen = 0, last = 0; int patchlen; - char *bin, *binend; + char *bin, *binend, *data; char decode[12]; /* for dealing with alignment issues */ if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen)) return NULL; binend = bin + patchlen; + data = bin + 12; - while (bin < binend) { + while (data <= binend) { memcpy(decode, bin, 12); start = ntohl(*(uint32_t *)decode); end = ntohl(*(uint32_t *)(decode + 4)); len = ntohl(*(uint32_t *)(decode + 8)); - bin += 12 + len; + if (start > end) + break; /* sanity check */ + bin = data + len; + if (bin < data) + break; /* big data + big (bogus) len can wrap around */ + data = bin + 12; outlen += start - last; last = end; outlen += len;