Add safety checking to mpatch

This commit is contained in:
mpm@selenic.com 2005-05-21 13:14:58 -08:00
parent a264d87bbd
commit e7e047fdee

View File

@ -39,17 +39,25 @@ struct flist {
static struct flist *lalloc(int size) static struct flist *lalloc(int size)
{ {
struct flist *a; struct flist *a = NULL;
a = malloc(sizeof(struct flist)); a = malloc(sizeof(struct flist));
a->head = a->tail = a->base = malloc(sizeof(struct frag) * size); if (a) {
a->base = malloc(sizeof(struct frag) * size);
if (!a->base)
free(a);
else
a->head = a->tail = a->base;
}
return a; return a;
} }
static void lfree(struct flist *a) static void lfree(struct flist *a)
{ {
free(a->base); if (a) {
free(a); free(a->base);
free(a);
}
} }
static int lsize(struct flist *a) static int lsize(struct flist *a)
@ -144,33 +152,37 @@ static int discard(struct flist *src, int cut, int offset)
this deletes a and b and returns the resultant list. */ this deletes a and b and returns the resultant list. */
static struct flist *combine(struct flist *a, struct flist *b) static struct flist *combine(struct flist *a, struct flist *b)
{ {
struct flist *c; struct flist *c = NULL;
struct frag *bh = b->head, *ct; struct frag *bh, *ct;
int offset = 0, post; int offset = 0, post;
c = lalloc((lsize(a) + lsize(b)) * 2); if (a && b)
c = lalloc((lsize(a) + lsize(b)) * 2);
while (bh != b->tail) { if (c) {
/* save old hunks */
offset = gather(c, a, bh->start, offset);
/* discard replaced hunks */ for (bh = b->head; bh != b->tail; bh++) {
post = discard(a, bh->end, offset); /* save old hunks */
offset = gather(c, a, bh->start, offset);
/* insert new hunk */ /* discard replaced hunks */
ct = c->tail; post = discard(a, bh->end, offset);
ct->start = bh->start - offset;
ct->end = bh->end - post; /* insert new hunk */
ct->len = bh->len; ct = c->tail;
ct->data = bh->data; ct->start = bh->start - offset;
c->tail++; ct->end = bh->end - post;
bh++; ct->len = bh->len;
offset = post; ct->data = bh->data;
c->tail++;
offset = post;
}
/* hold on to tail from a */
memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
c->tail += lsize(a);
} }
/* hold on to tail from a */
memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
c->tail += lsize(a);
lfree(a); lfree(a);
lfree(b); lfree(b);
return c; return c;
@ -242,6 +254,8 @@ static struct flist *fold(PyObject *bins, int start, int end)
if (start + 1 == end) { if (start + 1 == end) {
/* trivial case, output a decoded list */ /* trivial case, output a decoded list */
PyObject *tmp = PyList_GetItem(bins, start); PyObject *tmp = PyList_GetItem(bins, start);
if (!tmp)
return NULL;
return decode(PyString_AsString(tmp), PyString_Size(tmp)); return decode(PyString_AsString(tmp), PyString_Size(tmp));
} }
@ -259,7 +273,7 @@ patches(PyObject *self, PyObject *args)
char *in, *out; char *in, *out;
int len, outlen; int len, outlen;
if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins)) if (!PyArg_ParseTuple(args, "SO:mpatch", &text, &bins))
return NULL; return NULL;
len = PyList_Size(bins); len = PyList_Size(bins);
@ -270,13 +284,18 @@ patches(PyObject *self, PyObject *args)
} }
patch = fold(bins, 0, len); patch = fold(bins, 0, len);
if (!patch)
return PyErr_NoMemory();
outlen = calcsize(PyString_Size(text), patch); outlen = calcsize(PyString_Size(text), patch);
result = PyString_FromStringAndSize(NULL, outlen); result = PyString_FromStringAndSize(NULL, outlen);
in = PyString_AsString(text); if (result) {
out = PyString_AsString(result); in = PyString_AsString(text);
apply(out, in, PyString_Size(text), patch); out = PyString_AsString(result);
lfree(patch); apply(out, in, PyString_Size(text), patch);
}
lfree(patch);
return result; return result;
} }