|
|
bd3afb |
diff -ru mercurial-2.6.2/mercurial/mpatch.c mercurial-2.6.2_patched/mercurial/mpatch.c
|
|
|
bd3afb |
--- mercurial-2.6.2/mercurial/mpatch.c 2013-06-02 00:10:16.000000000 +0200
|
|
|
bd3afb |
+++ mercurial-2.6.2_patched/mercurial/mpatch.c 2019-05-07 16:51:13.631774481 +0200
|
|
|
bd3afb |
@@ -74,6 +74,35 @@
|
|
|
bd3afb |
return a->tail - a->head;
|
|
|
bd3afb |
}
|
|
|
bd3afb |
|
|
|
bd3afb |
+/* add helper to add src and *dest iff it won't overflow */
|
|
|
bd3afb |
+static inline int safeadd(int src, int *dest)
|
|
|
bd3afb |
+{
|
|
|
bd3afb |
+ if ((src > 0) == (*dest > 0)) {
|
|
|
bd3afb |
+ if (*dest > 0) {
|
|
|
bd3afb |
+ if (src > (INT_MAX - *dest)) {
|
|
|
bd3afb |
+ return 0;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ } else {
|
|
|
bd3afb |
+ if (src < (INT_MIN - *dest)) {
|
|
|
bd3afb |
+ return 0;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ *dest += src;
|
|
|
bd3afb |
+ return 1;
|
|
|
bd3afb |
+}
|
|
|
bd3afb |
+
|
|
|
bd3afb |
+/* subtract src from dest and store result in dest */
|
|
|
bd3afb |
+static inline int safesub(int src, int *dest)
|
|
|
bd3afb |
+{
|
|
|
bd3afb |
+ if (((src > 0) && (*dest < INT_MIN + src)) ||
|
|
|
bd3afb |
+ ((src < 0) && (*dest > INT_MAX + src))) {
|
|
|
bd3afb |
+ return 0;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ *dest -= src;
|
|
|
bd3afb |
+ return 1;
|
|
|
bd3afb |
+}
|
|
|
bd3afb |
+
|
|
|
bd3afb |
/* move hunks in source that are less cut to dest, compensating
|
|
|
bd3afb |
for changes in offset. the last hunk may be split if necessary.
|
|
|
bd3afb |
*/
|
|
|
bd3afb |
@@ -83,18 +112,37 @@
|
|
|
bd3afb |
int postend, c, l;
|
|
|
bd3afb |
|
|
|
bd3afb |
while (s != src->tail) {
|
|
|
bd3afb |
- if (s->start + offset >= cut)
|
|
|
bd3afb |
+ int soffset = s->start;
|
|
|
bd3afb |
+ if (!safeadd(offset, &soffset))
|
|
|
bd3afb |
+ break; /* add would overflow, oh well */
|
|
|
bd3afb |
+ if (soffset >= cut)
|
|
|
bd3afb |
break; /* we've gone far enough */
|
|
|
bd3afb |
|
|
|
bd3afb |
- postend = offset + s->start + s->len;
|
|
|
bd3afb |
+ postend = offset;
|
|
|
bd3afb |
+ if (!safeadd(s->start, &postend) ||
|
|
|
bd3afb |
+ !safeadd(s->len, &postend)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
if (postend <= cut) {
|
|
|
bd3afb |
/* save this hunk */
|
|
|
bd3afb |
- offset += s->start + s->len - s->end;
|
|
|
bd3afb |
+ int tmp = s->start;
|
|
|
bd3afb |
+ if (!safesub(s->end, &tmp)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ if (!safeadd(s->len, &tmp)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ if (!safeadd(tmp, &offset)) {
|
|
|
bd3afb |
+ break; /* add would overflow, oh well */
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
*d++ = *s++;
|
|
|
bd3afb |
}
|
|
|
bd3afb |
else {
|
|
|
bd3afb |
/* break up this hunk */
|
|
|
bd3afb |
- c = cut - offset;
|
|
|
bd3afb |
+ c = cut;
|
|
|
bd3afb |
+ if (!safesub(offset, &c)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
if (s->end < c)
|
|
|
bd3afb |
c = s->end;
|
|
|
bd3afb |
l = cut - offset - s->start;
|
|
|
bd3afb |
@@ -128,16 +176,40 @@
|
|
|
bd3afb |
int postend, c, l;
|
|
|
bd3afb |
|
|
|
bd3afb |
while (s != src->tail) {
|
|
|
bd3afb |
- if (s->start + offset >= cut)
|
|
|
bd3afb |
+ int cmpcut = s->start;
|
|
|
bd3afb |
+ if (!safeadd(offset, &cmpcut)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ if (cmpcut >= cut)
|
|
|
bd3afb |
break;
|
|
|
bd3afb |
|
|
|
bd3afb |
- postend = offset + s->start + s->len;
|
|
|
bd3afb |
+ postend = offset;
|
|
|
bd3afb |
+ if (!safeadd(s->start, &postend)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ if (!safeadd(s->len, &postend)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
if (postend <= cut) {
|
|
|
bd3afb |
- offset += s->start + s->len - s->end;
|
|
|
bd3afb |
+ /* do the subtraction first to avoid UB integer overflow
|
|
|
bd3afb |
+ */
|
|
|
bd3afb |
+ int tmp = s->start;
|
|
|
bd3afb |
+ if (!safesub(s->end, &tmp)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ if (!safeadd(s->len, &tmp)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
+ if (!safeadd(tmp, &offset)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
s++;
|
|
|
bd3afb |
}
|
|
|
bd3afb |
else {
|
|
|
bd3afb |
- c = cut - offset;
|
|
|
bd3afb |
+ c = cut;
|
|
|
bd3afb |
+ if (!safesub(offset, &c)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
if (s->end < c)
|
|
|
bd3afb |
c = s->end;
|
|
|
bd3afb |
l = cut - offset - s->start;
|
|
|
bd3afb |
@@ -179,8 +251,18 @@
|
|
|
bd3afb |
|
|
|
bd3afb |
/* insert new hunk */
|
|
|
bd3afb |
ct = c->tail;
|
|
|
bd3afb |
- ct->start = bh->start - offset;
|
|
|
bd3afb |
- ct->end = bh->end - post;
|
|
|
bd3afb |
+ ct->start = bh->start;
|
|
|
bd3afb |
+ ct->end = bh->end;
|
|
|
bd3afb |
+ if (!safesub(offset, &(ct->start)) ||
|
|
|
bd3afb |
+ !safesub(post, &(ct->end))) {
|
|
|
bd3afb |
+ /* It was already possible to exit
|
|
|
bd3afb |
+ * this function with a return value
|
|
|
bd3afb |
+ * of NULL before the safesub()s were
|
|
|
bd3afb |
+ * added, so this should be fine. */
|
|
|
bd3afb |
+ lfree(c);
|
|
|
bd3afb |
+ c = NULL;
|
|
|
bd3afb |
+ goto done;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
ct->len = bh->len;
|
|
|
bd3afb |
ct->data = bh->data;
|
|
|
bd3afb |
c->tail++;
|
|
|
bd3afb |
@@ -191,7 +273,7 @@
|
|
|
bd3afb |
memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
|
|
|
bd3afb |
c->tail += lsize(a);
|
|
|
bd3afb |
}
|
|
|
bd3afb |
-
|
|
|
bd3afb |
+done:
|
|
|
bd3afb |
lfree(a);
|
|
|
bd3afb |
lfree(b);
|
|
|
bd3afb |
return c;
|
|
|
bd3afb |
@@ -215,13 +297,17 @@
|
|
|
bd3afb |
lt->start = getbe32(bin);
|
|
|
bd3afb |
lt->end = getbe32(bin + 4);
|
|
|
bd3afb |
lt->len = getbe32(bin + 8);
|
|
|
bd3afb |
- if (lt->start > lt->end)
|
|
|
bd3afb |
- break; /* sanity check */
|
|
|
bd3afb |
- bin = data + lt->len;
|
|
|
bd3afb |
- if (bin < data)
|
|
|
bd3afb |
+ if (lt->start < 0 || lt->start > lt->end || lt->len < 0)
|
|
|
bd3afb |
+ break; /* sanity check */
|
|
|
bd3afb |
+ bin = data;
|
|
|
bd3afb |
+ if (!safeadd(lt->len, &bin)) {
|
|
|
bd3afb |
break; /* big data + big (bogus) len can wrap around */
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
lt->data = data;
|
|
|
bd3afb |
- data = bin + 12;
|
|
|
bd3afb |
+ data = bin;
|
|
|
bd3afb |
+ if (!safeadd(12, &data)) {
|
|
|
bd3afb |
+ break;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
lt++;
|
|
|
bd3afb |
}
|
|
|
bd3afb |
|
|
|
bd3afb |
@@ -266,7 +352,8 @@
|
|
|
bd3afb |
char *p = buf;
|
|
|
bd3afb |
|
|
|
bd3afb |
while (f != l->tail) {
|
|
|
bd3afb |
- if (f->start < last || f->end > len) {
|
|
|
bd3afb |
+ if (f->start < last || f->start > len || f->end > len ||
|
|
|
bd3afb |
+ last < 0) {
|
|
|
bd3afb |
if (!PyErr_Occurred())
|
|
|
bd3afb |
PyErr_SetString(mpatch_Error,
|
|
|
bd3afb |
"invalid patch");
|
|
|
bd3afb |
@@ -279,6 +366,12 @@
|
|
|
bd3afb |
p += f->len;
|
|
|
bd3afb |
f++;
|
|
|
bd3afb |
}
|
|
|
bd3afb |
+ if (last < 0) {
|
|
|
bd3afb |
+ if (!PyErr_Occurred())
|
|
|
bd3afb |
+ PyErr_SetString(mpatch_Error,
|
|
|
bd3afb |
+ "invalid patch");
|
|
|
bd3afb |
+ return 0;
|
|
|
bd3afb |
+ }
|
|
|
bd3afb |
memcpy(p, orig + last, len - last);
|
|
|
bd3afb |
return 1;
|
|
|
bd3afb |
}
|