Mercurial > hg
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 |