# HG changeset patch # User Thomas Arendsen Hein # Date 1169935626 -3600 # Node ID 11dc22eb8e8d01df171cc30cd566c30c9ed1a95f # Parent 3f1b0c0fb4fdbe6827c6deecd1c06f67f7d2f0c1 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) diff -r 3f1b0c0fb4fd -r 11dc22eb8e8d mercurial/mpatch.c --- 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;