comparison mercurial/mpatch.c @ 128:d6afb6dbf9f2

Add safety checking to mpatch
author mpm@selenic.com
date Sat, 21 May 2005 13:14:58 -0800
parents 7ed96baa7caa
children 97d83e7fbf2f
comparison
equal deleted inserted replaced
127:44538462d3c8 128:d6afb6dbf9f2
37 struct frag *base, *head, *tail; 37 struct frag *base, *head, *tail;
38 }; 38 };
39 39
40 static struct flist *lalloc(int size) 40 static struct flist *lalloc(int size)
41 { 41 {
42 struct flist *a; 42 struct flist *a = NULL;
43 43
44 a = malloc(sizeof(struct flist)); 44 a = malloc(sizeof(struct flist));
45 a->head = a->tail = a->base = malloc(sizeof(struct frag) * size); 45 if (a) {
46 a->base = malloc(sizeof(struct frag) * size);
47 if (!a->base)
48 free(a);
49 else
50 a->head = a->tail = a->base;
51 }
46 return a; 52 return a;
47 } 53 }
48 54
49 static void lfree(struct flist *a) 55 static void lfree(struct flist *a)
50 { 56 {
51 free(a->base); 57 if (a) {
52 free(a); 58 free(a->base);
59 free(a);
60 }
53 } 61 }
54 62
55 static int lsize(struct flist *a) 63 static int lsize(struct flist *a)
56 { 64 {
57 return a->tail - a->head; 65 return a->tail - a->head;
142 150
143 /* combine hunk lists a and b, while adjusting b for offset changes in a/ 151 /* combine hunk lists a and b, while adjusting b for offset changes in a/
144 this deletes a and b and returns the resultant list. */ 152 this deletes a and b and returns the resultant list. */
145 static struct flist *combine(struct flist *a, struct flist *b) 153 static struct flist *combine(struct flist *a, struct flist *b)
146 { 154 {
147 struct flist *c; 155 struct flist *c = NULL;
148 struct frag *bh = b->head, *ct; 156 struct frag *bh, *ct;
149 int offset = 0, post; 157 int offset = 0, post;
150 158
151 c = lalloc((lsize(a) + lsize(b)) * 2); 159 if (a && b)
152 160 c = lalloc((lsize(a) + lsize(b)) * 2);
153 while (bh != b->tail) { 161
154 /* save old hunks */ 162 if (c) {
155 offset = gather(c, a, bh->start, offset); 163
156 164 for (bh = b->head; bh != b->tail; bh++) {
157 /* discard replaced hunks */ 165 /* save old hunks */
158 post = discard(a, bh->end, offset); 166 offset = gather(c, a, bh->start, offset);
159 167
160 /* insert new hunk */ 168 /* discard replaced hunks */
161 ct = c->tail; 169 post = discard(a, bh->end, offset);
162 ct->start = bh->start - offset; 170
163 ct->end = bh->end - post; 171 /* insert new hunk */
164 ct->len = bh->len; 172 ct = c->tail;
165 ct->data = bh->data; 173 ct->start = bh->start - offset;
166 c->tail++; 174 ct->end = bh->end - post;
167 bh++; 175 ct->len = bh->len;
168 offset = post; 176 ct->data = bh->data;
169 } 177 c->tail++;
170 178 offset = post;
171 /* hold on to tail from a */ 179 }
172 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a)); 180
173 c->tail += lsize(a); 181 /* hold on to tail from a */
182 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
183 c->tail += lsize(a);
184 }
185
174 lfree(a); 186 lfree(a);
175 lfree(b); 187 lfree(b);
176 return c; 188 return c;
177 } 189 }
178 190
240 int len; 252 int len;
241 253
242 if (start + 1 == end) { 254 if (start + 1 == end) {
243 /* trivial case, output a decoded list */ 255 /* trivial case, output a decoded list */
244 PyObject *tmp = PyList_GetItem(bins, start); 256 PyObject *tmp = PyList_GetItem(bins, start);
257 if (!tmp)
258 return NULL;
245 return decode(PyString_AsString(tmp), PyString_Size(tmp)); 259 return decode(PyString_AsString(tmp), PyString_Size(tmp));
246 } 260 }
247 261
248 /* divide and conquer, memory management is elsewhere */ 262 /* divide and conquer, memory management is elsewhere */
249 len = (end - start) / 2; 263 len = (end - start) / 2;
257 PyObject *text, *bins, *result; 271 PyObject *text, *bins, *result;
258 struct flist *patch; 272 struct flist *patch;
259 char *in, *out; 273 char *in, *out;
260 int len, outlen; 274 int len, outlen;
261 275
262 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins)) 276 if (!PyArg_ParseTuple(args, "SO:mpatch", &text, &bins))
263 return NULL; 277 return NULL;
264 278
265 len = PyList_Size(bins); 279 len = PyList_Size(bins);
266 if (!len) { 280 if (!len) {
267 /* nothing to do */ 281 /* nothing to do */
268 Py_INCREF(text); 282 Py_INCREF(text);
269 return text; 283 return text;
270 } 284 }
271 285
272 patch = fold(bins, 0, len); 286 patch = fold(bins, 0, len);
287 if (!patch)
288 return PyErr_NoMemory();
289
273 outlen = calcsize(PyString_Size(text), patch); 290 outlen = calcsize(PyString_Size(text), patch);
274 result = PyString_FromStringAndSize(NULL, outlen); 291 result = PyString_FromStringAndSize(NULL, outlen);
275 in = PyString_AsString(text); 292 if (result) {
276 out = PyString_AsString(result); 293 in = PyString_AsString(text);
277 apply(out, in, PyString_Size(text), patch); 294 out = PyString_AsString(result);
295 apply(out, in, PyString_Size(text), patch);
296 }
297
278 lfree(patch); 298 lfree(patch);
279
280 return result; 299 return result;
281 } 300 }
282 301
283 static PyMethodDef methods[] = { 302 static PyMethodDef methods[] = {
284 {"patches", patches, METH_VARARGS, "apply a series of patches\n"}, 303 {"patches", patches, METH_VARARGS, "apply a series of patches\n"},