comparison mercurial/mpatch.c @ 1722:681c5c211b92

catch errors and throw exception with invalid binary patch data
author Benoit Boissinot <benoit.boissinot@ens-lyon.org>
date Wed, 15 Feb 2006 04:37:47 +0100
parents e530637ea060
children 299c3e26ee45
comparison
equal deleted inserted replaced
1721:801756d0ca84 1722:681c5c211b92
41 #include <sys/types.h> 41 #include <sys/types.h>
42 #include <arpa/inet.h> 42 #include <arpa/inet.h>
43 #endif 43 #endif
44 44
45 static char mpatch_doc[] = "Efficient binary patching."; 45 static char mpatch_doc[] = "Efficient binary patching.";
46 static PyObject *mpatch_Error;
46 47
47 struct frag { 48 struct frag {
48 int start, end, len; 49 int start, end, len;
49 char *data; 50 char *data;
50 }; 51 };
63 if (!a->base) { 64 if (!a->base) {
64 free(a); 65 free(a);
65 a = NULL; 66 a = NULL;
66 } else 67 } else
67 a->head = a->tail = a->base; 68 a->head = a->tail = a->base;
68 } 69 return a;
69 return a; 70 }
71 if (!PyErr_Occurred())
72 PyErr_NoMemory();
73 return NULL;
70 } 74 }
71 75
72 static void lfree(struct flist *a) 76 static void lfree(struct flist *a)
73 { 77 {
74 if (a) { 78 if (a) {
213 char *end = bin + len; 217 char *end = bin + len;
214 char decode[12]; /* for dealing with alignment issues */ 218 char decode[12]; /* for dealing with alignment issues */
215 219
216 /* assume worst case size, we won't have many of these lists */ 220 /* assume worst case size, we won't have many of these lists */
217 l = lalloc(len / 12); 221 l = lalloc(len / 12);
222 if (!l)
223 return NULL;
224
218 lt = l->tail; 225 lt = l->tail;
219 226
220 while (bin < end) { 227 while (bin < end) {
221 memcpy(decode, bin, 12); 228 memcpy(decode, bin, 12);
222 lt->start = ntohl(*(uint32_t *)decode); 229 lt->start = ntohl(*(uint32_t *)decode);
225 lt->data = bin + 12; 232 lt->data = bin + 12;
226 bin += 12 + lt->len; 233 bin += 12 + lt->len;
227 lt++; 234 lt++;
228 } 235 }
229 236
237 if (bin != end) {
238 if (!PyErr_Occurred())
239 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
240 lfree(l);
241 return NULL;
242 }
243
230 l->tail = lt; 244 l->tail = lt;
231 return l; 245 return l;
232 } 246 }
233 247
234 /* calculate the size of resultant text */ 248 /* calculate the size of resultant text */
236 { 250 {
237 int outlen = 0, last = 0; 251 int outlen = 0, last = 0;
238 struct frag *f = l->head; 252 struct frag *f = l->head;
239 253
240 while (f != l->tail) { 254 while (f != l->tail) {
255 if (f->start < last || f->end > len) {
256 if (!PyErr_Occurred())
257 PyErr_SetString(mpatch_Error,
258 "invalid patch");
259 return -1;
260 }
241 outlen += f->start - last; 261 outlen += f->start - last;
242 last = f->end; 262 last = f->end;
243 outlen += f->len; 263 outlen += f->len;
244 f++; 264 f++;
245 } 265 }
246 266
247 outlen += len - last; 267 outlen += len - last;
248 return outlen; 268 return outlen;
249 } 269 }
250 270
251 static void apply(char *buf, char *orig, int len, struct flist *l) 271 static int apply(char *buf, char *orig, int len, struct flist *l)
252 { 272 {
253 struct frag *f = l->head; 273 struct frag *f = l->head;
254 int last = 0; 274 int last = 0;
255 char *p = buf; 275 char *p = buf;
256 276
257 while (f != l->tail) { 277 while (f != l->tail) {
278 if (f->start < last || f->end > len) {
279 if (!PyErr_Occurred())
280 PyErr_SetString(mpatch_Error,
281 "invalid patch");
282 return 0;
283 }
258 memcpy(p, orig + last, f->start - last); 284 memcpy(p, orig + last, f->start - last);
259 p += f->start - last; 285 p += f->start - last;
260 memcpy(p, f->data, f->len); 286 memcpy(p, f->data, f->len);
261 last = f->end; 287 last = f->end;
262 p += f->len; 288 p += f->len;
263 f++; 289 f++;
264 } 290 }
265 memcpy(p, orig + last, len - last); 291 memcpy(p, orig + last, len - last);
292 return 1;
266 } 293 }
267 294
268 /* recursively generate a patch of all bins between start and end */ 295 /* recursively generate a patch of all bins between start and end */
269 static struct flist *fold(PyObject *bins, int start, int end) 296 static struct flist *fold(PyObject *bins, int start, int end)
270 { 297 {
302 return text; 329 return text;
303 } 330 }
304 331
305 patch = fold(bins, 0, len); 332 patch = fold(bins, 0, len);
306 if (!patch) 333 if (!patch)
307 return PyErr_NoMemory(); 334 return NULL;
308 335
309 outlen = calcsize(PyString_Size(text), patch); 336 outlen = calcsize(PyString_Size(text), patch);
337 if (outlen < 0) {
338 result = NULL;
339 goto cleanup;
340 }
310 result = PyString_FromStringAndSize(NULL, outlen); 341 result = PyString_FromStringAndSize(NULL, outlen);
311 if (result) { 342 if (!result) {
312 in = PyString_AsString(text); 343 result = NULL;
313 out = PyString_AsString(result); 344 goto cleanup;
314 apply(out, in, PyString_Size(text), patch); 345 }
315 } 346 in = PyString_AsString(text);
316 347 out = PyString_AsString(result);
348 if (!apply(out, in, PyString_Size(text), patch)) {
349 Py_DECREF(result);
350 result = NULL;
351 }
352 cleanup:
317 lfree(patch); 353 lfree(patch);
318 return result; 354 return result;
319 } 355 }
320 356
321 static PyMethodDef methods[] = { 357 static PyMethodDef methods[] = {
325 361
326 PyMODINIT_FUNC 362 PyMODINIT_FUNC
327 initmpatch(void) 363 initmpatch(void)
328 { 364 {
329 Py_InitModule3("mpatch", methods, mpatch_doc); 365 Py_InitModule3("mpatch", methods, mpatch_doc);
330 } 366 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL);
331 367 }
368