comparison mercurial/mpatch.c @ 4358: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
4357:3f1b0c0fb4fd 4358: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