Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/mpatch.c @ 4375:11dc22eb8e8d
Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
- fix off by 11 when checking if there are more hunks (found by Maris Fogels)
- bail out if start is greater than end
- check if new hunk starts after start/end/len block of current hunk as
the pointer can wrap around on very large values, reproducible with
import mpatch; mpatch.patchedsize(12, 'x'*12)
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Sat, 27 Jan 2007 23:07:06 +0100 |
parents | cc856c4d91ca |
children | 4759da3e4dc8 |
comparison
equal
deleted
inserted
replaced
4367:3f1b0c0fb4fd | 4375:11dc22eb8e8d |
---|---|
219 /* decode a binary patch into a hunk list */ | 219 /* decode a binary patch into a hunk list */ |
220 static struct flist *decode(char *bin, int len) | 220 static struct flist *decode(char *bin, int len) |
221 { | 221 { |
222 struct flist *l; | 222 struct flist *l; |
223 struct frag *lt; | 223 struct frag *lt; |
224 char *end = bin + len; | 224 char *data = bin + 12, *end = bin + len; |
225 char decode[12]; /* for dealing with alignment issues */ | 225 char decode[12]; /* for dealing with alignment issues */ |
226 | 226 |
227 /* assume worst case size, we won't have many of these lists */ | 227 /* assume worst case size, we won't have many of these lists */ |
228 l = lalloc(len / 12); | 228 l = lalloc(len / 12); |
229 if (!l) | 229 if (!l) |
230 return NULL; | 230 return NULL; |
231 | 231 |
232 lt = l->tail; | 232 lt = l->tail; |
233 | 233 |
234 while (bin < end) { | 234 while (data <= end) { |
235 memcpy(decode, bin, 12); | 235 memcpy(decode, bin, 12); |
236 lt->start = ntohl(*(uint32_t *)decode); | 236 lt->start = ntohl(*(uint32_t *)decode); |
237 lt->end = ntohl(*(uint32_t *)(decode + 4)); | 237 lt->end = ntohl(*(uint32_t *)(decode + 4)); |
238 lt->len = ntohl(*(uint32_t *)(decode + 8)); | 238 lt->len = ntohl(*(uint32_t *)(decode + 8)); |
239 lt->data = bin + 12; | 239 if (lt->start > lt->end) |
240 bin += 12 + lt->len; | 240 break; /* sanity check */ |
241 bin = data + lt->len; | |
242 if (bin < data) | |
243 break; /* big data + big (bogus) len can wrap around */ | |
244 lt->data = data; | |
245 data = bin + 12; | |
241 lt++; | 246 lt++; |
242 } | 247 } |
243 | 248 |
244 if (bin != end) { | 249 if (bin != end) { |
245 if (!PyErr_Occurred()) | 250 if (!PyErr_Occurred()) |
365 static PyObject * | 370 static PyObject * |
366 patchedsize(PyObject *self, PyObject *args) | 371 patchedsize(PyObject *self, PyObject *args) |
367 { | 372 { |
368 long orig, start, end, len, outlen = 0, last = 0; | 373 long orig, start, end, len, outlen = 0, last = 0; |
369 int patchlen; | 374 int patchlen; |
370 char *bin, *binend; | 375 char *bin, *binend, *data; |
371 char decode[12]; /* for dealing with alignment issues */ | 376 char decode[12]; /* for dealing with alignment issues */ |
372 | 377 |
373 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen)) | 378 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen)) |
374 return NULL; | 379 return NULL; |
375 | 380 |
376 binend = bin + patchlen; | 381 binend = bin + patchlen; |
377 | 382 data = bin + 12; |
378 while (bin < binend) { | 383 |
384 while (data <= binend) { | |
379 memcpy(decode, bin, 12); | 385 memcpy(decode, bin, 12); |
380 start = ntohl(*(uint32_t *)decode); | 386 start = ntohl(*(uint32_t *)decode); |
381 end = ntohl(*(uint32_t *)(decode + 4)); | 387 end = ntohl(*(uint32_t *)(decode + 4)); |
382 len = ntohl(*(uint32_t *)(decode + 8)); | 388 len = ntohl(*(uint32_t *)(decode + 8)); |
383 bin += 12 + len; | 389 if (start > end) |
390 break; /* sanity check */ | |
391 bin = data + len; | |
392 if (bin < data) | |
393 break; /* big data + big (bogus) len can wrap around */ | |
394 data = bin + 12; | |
384 outlen += start - last; | 395 outlen += start - last; |
385 last = end; | 396 last = end; |
386 outlen += len; | 397 outlen += len; |
387 } | 398 } |
388 | 399 |