--- a/mercurial/mpatch.c Tue Feb 14 17:13:18 2006 -0800
+++ b/mercurial/mpatch.c Wed Feb 15 04:37:47 2006 +0100
@@ -43,6 +43,7 @@
#endif
static char mpatch_doc[] = "Efficient binary patching.";
+static PyObject *mpatch_Error;
struct frag {
int start, end, len;
@@ -65,8 +66,11 @@
a = NULL;
} else
a->head = a->tail = a->base;
+ return a;
}
- return a;
+ if (!PyErr_Occurred())
+ PyErr_NoMemory();
+ return NULL;
}
static void lfree(struct flist *a)
@@ -215,6 +219,9 @@
/* assume worst case size, we won't have many of these lists */
l = lalloc(len / 12);
+ if (!l)
+ return NULL;
+
lt = l->tail;
while (bin < end) {
@@ -227,6 +234,13 @@
lt++;
}
+ if (bin != end) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(mpatch_Error, "patch cannot be decoded");
+ lfree(l);
+ return NULL;
+ }
+
l->tail = lt;
return l;
}
@@ -238,6 +252,12 @@
struct frag *f = l->head;
while (f != l->tail) {
+ if (f->start < last || f->end > len) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(mpatch_Error,
+ "invalid patch");
+ return -1;
+ }
outlen += f->start - last;
last = f->end;
outlen += f->len;
@@ -248,13 +268,19 @@
return outlen;
}
-static void apply(char *buf, char *orig, int len, struct flist *l)
+static int apply(char *buf, char *orig, int len, struct flist *l)
{
struct frag *f = l->head;
int last = 0;
char *p = buf;
while (f != l->tail) {
+ if (f->start < last || f->end > len) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(mpatch_Error,
+ "invalid patch");
+ return 0;
+ }
memcpy(p, orig + last, f->start - last);
p += f->start - last;
memcpy(p, f->data, f->len);
@@ -263,6 +289,7 @@
f++;
}
memcpy(p, orig + last, len - last);
+ return 1;
}
/* recursively generate a patch of all bins between start and end */
@@ -304,16 +331,25 @@
patch = fold(bins, 0, len);
if (!patch)
- return PyErr_NoMemory();
+ return NULL;
outlen = calcsize(PyString_Size(text), patch);
+ if (outlen < 0) {
+ result = NULL;
+ goto cleanup;
+ }
result = PyString_FromStringAndSize(NULL, outlen);
- if (result) {
- in = PyString_AsString(text);
- out = PyString_AsString(result);
- apply(out, in, PyString_Size(text), patch);
+ if (!result) {
+ result = NULL;
+ goto cleanup;
}
-
+ in = PyString_AsString(text);
+ out = PyString_AsString(result);
+ if (!apply(out, in, PyString_Size(text), patch)) {
+ Py_DECREF(result);
+ result = NULL;
+ }
+cleanup:
lfree(patch);
return result;
}
@@ -327,5 +363,6 @@
initmpatch(void)
{
Py_InitModule3("mpatch", methods, mpatch_doc);
+ mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL);
}