diff options
author | josh.macdonald <jmacd@users.noreply.github.com> | 2014-10-12 05:24:22 +0000 |
---|---|---|
committer | josh.macdonald <jmacd@users.noreply.github.com> | 2014-10-12 05:24:22 +0000 |
commit | ef93ff74203e030073b898c05e8b4860b5d09ef2 (patch) | |
tree | 3c43503fa2990764fd53cf733121b7c063f86f5e | |
parent | 7b6ff92bf4f954b70f92b04eadcf43fe69403cc8 (diff) |
Add appheader tests; fix buffer overflow in main_get_appheader
-rw-r--r-- | xdelta3/xdelta3-main.h | 5 | ||||
-rw-r--r-- | xdelta3/xdelta3-test.h | 131 |
2 files changed, 108 insertions, 28 deletions
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h index 090b7d9..5146b38 100644 --- a/xdelta3/xdelta3-main.h +++ b/xdelta3/xdelta3-main.h | |||
@@ -2810,14 +2810,15 @@ main_get_appheader (xd3_stream *stream, main_file *ifile, | |||
2810 | 2810 | ||
2811 | if (appheadsz > 0) | 2811 | if (appheadsz > 0) |
2812 | { | 2812 | { |
2813 | const int kMaxArgs = 4; | ||
2813 | char *start = (char*)apphead; | 2814 | char *start = (char*)apphead; |
2814 | char *slash; | 2815 | char *slash; |
2815 | int place = 0; | 2816 | int place = 0; |
2816 | char *parsed[4]; | 2817 | char *parsed[kMaxArgs]; |
2817 | 2818 | ||
2818 | memset (parsed, 0, sizeof (parsed)); | 2819 | memset (parsed, 0, sizeof (parsed)); |
2819 | 2820 | ||
2820 | while ((slash = strchr (start, '/')) != NULL) | 2821 | while ((slash = strchr (start, '/')) != NULL && place < (kMaxArgs-1)) |
2821 | { | 2822 | { |
2822 | *slash = 0; | 2823 | *slash = 0; |
2823 | parsed[place++] = start; | 2824 | parsed[place++] = start; |
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h index e9848b6..0e10251 100644 --- a/xdelta3/xdelta3-test.h +++ b/xdelta3/xdelta3-test.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* xdelta 3 - delta compression tools and library Copyright (C) 2001, | 1 | /* xdelta 3 - delta compression tools and library Copyright (C) 2001, |
2 | * 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012. | 2 | * 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012. |
3 | * Joshua P. MacDonald | 3 | * Joshua P. MacDonald |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -54,7 +54,7 @@ void mt_init(mtrand *mt, uint32_t seed) { | |||
54 | /* only MSBs of the array mt[]. */ | 54 | /* only MSBs of the array mt[]. */ |
55 | /* 2002/01/09 modified by Makoto Matsumoto */ | 55 | /* 2002/01/09 modified by Makoto Matsumoto */ |
56 | mt->mt_buffer_[i] = | 56 | mt->mt_buffer_[i] = |
57 | (1812433253UL * (mt->mt_buffer_[i-1] ^ | 57 | (1812433253UL * (mt->mt_buffer_[i-1] ^ |
58 | (mt->mt_buffer_[i-1] >> 30)) + i); | 58 | (mt->mt_buffer_[i-1] >> 30)) + i); |
59 | } | 59 | } |
60 | } | 60 | } |
@@ -69,20 +69,20 @@ uint32_t mt_random (mtrand *mt) { | |||
69 | int kk; | 69 | int kk; |
70 | 70 | ||
71 | for (kk = 0; kk < MT_LEN - MT_IA; kk++) { | 71 | for (kk = 0; kk < MT_LEN - MT_IA; kk++) { |
72 | y = (mt->mt_buffer_[kk] & UPPER_MASK) | | 72 | y = (mt->mt_buffer_[kk] & UPPER_MASK) | |
73 | (mt->mt_buffer_[kk + 1] & LOWER_MASK); | 73 | (mt->mt_buffer_[kk + 1] & LOWER_MASK); |
74 | mt->mt_buffer_[kk] = mt->mt_buffer_[kk + MT_IA] ^ | 74 | mt->mt_buffer_[kk] = mt->mt_buffer_[kk + MT_IA] ^ |
75 | (y >> 1) ^ mag01[y & 0x1UL]; | 75 | (y >> 1) ^ mag01[y & 0x1UL]; |
76 | } | 76 | } |
77 | for (;kk < MT_LEN - 1; kk++) { | 77 | for (;kk < MT_LEN - 1; kk++) { |
78 | y = (mt->mt_buffer_[kk] & UPPER_MASK) | | 78 | y = (mt->mt_buffer_[kk] & UPPER_MASK) | |
79 | (mt->mt_buffer_[kk + 1] & LOWER_MASK); | 79 | (mt->mt_buffer_[kk + 1] & LOWER_MASK); |
80 | mt->mt_buffer_[kk] = mt->mt_buffer_[kk + (MT_IA - MT_LEN)] ^ | 80 | mt->mt_buffer_[kk] = mt->mt_buffer_[kk + (MT_IA - MT_LEN)] ^ |
81 | (y >> 1) ^ mag01[y & 0x1UL]; | 81 | (y >> 1) ^ mag01[y & 0x1UL]; |
82 | } | 82 | } |
83 | y = (mt->mt_buffer_[MT_LEN - 1] & UPPER_MASK) | | 83 | y = (mt->mt_buffer_[MT_LEN - 1] & UPPER_MASK) | |
84 | (mt->mt_buffer_[0] & LOWER_MASK); | 84 | (mt->mt_buffer_[0] & LOWER_MASK); |
85 | mt->mt_buffer_[MT_LEN - 1] = mt->mt_buffer_[MT_IA - 1] ^ | 85 | mt->mt_buffer_[MT_LEN - 1] = mt->mt_buffer_[MT_IA - 1] ^ |
86 | (y >> 1) ^ mag01[y & 0x1UL]; | 86 | (y >> 1) ^ mag01[y & 0x1UL]; |
87 | mt->mt_index_ = 0; | 87 | mt->mt_index_ = 0; |
88 | } | 88 | } |
@@ -166,7 +166,7 @@ static int do_cmd (xd3_stream *stream, const char *buf) | |||
166 | { | 166 | { |
167 | stream->msg = "abnormal command termination"; | 167 | stream->msg = "abnormal command termination"; |
168 | } | 168 | } |
169 | return XD3_INTERNAL; | 169 | return ret; |
170 | } | 170 | } |
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
@@ -257,8 +257,10 @@ int test_setup (void) | |||
257 | static int | 257 | static int |
258 | test_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out) | 258 | test_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out) |
259 | { | 259 | { |
260 | usize_t ts = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2; | 260 | usize_t ts = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + |
261 | usize_t ss = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2; | 261 | TEST_FILE_MEAN / 2; |
262 | usize_t ss = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + | ||
263 | TEST_FILE_MEAN / 2; | ||
262 | uint8_t *buf = (uint8_t*) malloc (ts + ss), *sbuf = buf, *tbuf = buf + ss; | 264 | uint8_t *buf = (uint8_t*) malloc (ts + ss), *sbuf = buf, *tbuf = buf + ss; |
263 | usize_t sadd = 0, sadd_max = (usize_t)(ss * TEST_ADD_RATIO); | 265 | usize_t sadd = 0, sadd_max = (usize_t)(ss * TEST_ADD_RATIO); |
264 | FILE *tf = NULL, *sf = NULL; | 266 | FILE *tf = NULL, *sf = NULL; |
@@ -409,7 +411,7 @@ test_compare_files (const char* tgt, const char *rec) | |||
409 | { | 411 | { |
410 | if (obuf[i] != rbuf[i]) | 412 | if (obuf[i] != rbuf[i]) |
411 | { | 413 | { |
412 | XPR(NT "byte %u (read %u @ %"Q"u) %d != %d\n", | 414 | XPR(NT "byte %u (read %u @ %"Q"u) %d != %d\n", |
413 | (int)i, (int)oc, offset, obuf[i], rbuf[i]); | 415 | (int)i, (int)oc, offset, obuf[i], rbuf[i]); |
414 | diffs++; | 416 | diffs++; |
415 | return XD3_INTERNAL; | 417 | return XD3_INTERNAL; |
@@ -421,7 +423,7 @@ test_compare_files (const char* tgt, const char *rec) | |||
421 | 423 | ||
422 | fclose (orig); | 424 | fclose (orig); |
423 | fclose (recons); | 425 | fclose (recons); |
424 | if (diffs != 0) | 426 | if (diffs != 0) |
425 | { | 427 | { |
426 | return XD3_INTERNAL; | 428 | return XD3_INTERNAL; |
427 | } | 429 | } |
@@ -429,12 +431,12 @@ test_compare_files (const char* tgt, const char *rec) | |||
429 | } | 431 | } |
430 | 432 | ||
431 | static int | 433 | static int |
432 | test_save_copy (const char *origname) | 434 | test_copy_to (const char *from, const char *to) |
433 | { | 435 | { |
434 | char buf[TESTBUFSIZE]; | 436 | char buf[TESTBUFSIZE]; |
435 | int ret; | 437 | int ret; |
436 | 438 | ||
437 | snprintf_func (buf, TESTBUFSIZE, "cp -f %s %s", origname, TEST_COPY_FILE); | 439 | snprintf_func (buf, TESTBUFSIZE, "cp -f %s %s", from, to); |
438 | 440 | ||
439 | if ((ret = system (buf)) != 0) | 441 | if ((ret = system (buf)) != 0) |
440 | { | 442 | { |
@@ -445,6 +447,12 @@ test_save_copy (const char *origname) | |||
445 | } | 447 | } |
446 | 448 | ||
447 | static int | 449 | static int |
450 | test_save_copy (const char *origname) | ||
451 | { | ||
452 | return test_copy_to(origname, TEST_COPY_FILE); | ||
453 | } | ||
454 | |||
455 | static int | ||
448 | test_file_size (const char* file, xoff_t *size) | 456 | test_file_size (const char* file, xoff_t *size) |
449 | { | 457 | { |
450 | struct stat sbuf; | 458 | struct stat sbuf; |
@@ -499,7 +507,7 @@ test_read_integer_error (xd3_stream *stream, usize_t trunto, const char *msg) | |||
499 | inp = buf->base; | 507 | inp = buf->base; |
500 | max = buf->base + buf->next - trunto; | 508 | max = buf->base + buf->next - trunto; |
501 | 509 | ||
502 | if ((ret = xd3_read_uint32_t (stream, & inp, max, & rval)) != | 510 | if ((ret = xd3_read_uint32_t (stream, & inp, max, & rval)) != |
503 | XD3_INVALID_INPUT || | 511 | XD3_INVALID_INPUT || |
504 | !MSG_IS (msg)) | 512 | !MSG_IS (msg)) |
505 | { | 513 | { |
@@ -1654,11 +1662,11 @@ test_compressed_stream_overflow (xd3_stream *stream, int ignore) | |||
1654 | if ((buf = (uint8_t*) malloc (TWO_MEGS_AND_DELTA)) == NULL) { return ENOMEM; } | 1662 | if ((buf = (uint8_t*) malloc (TWO_MEGS_AND_DELTA)) == NULL) { return ENOMEM; } |
1655 | 1663 | ||
1656 | memset (buf, 0, TWO_MEGS_AND_DELTA); | 1664 | memset (buf, 0, TWO_MEGS_AND_DELTA); |
1657 | for (i = 0; i < (2 << 20); i += 256) | 1665 | for (i = 0; i < (2 << 20); i += 256) |
1658 | { | 1666 | { |
1659 | int j; | 1667 | int j; |
1660 | int off = mt_random(& static_mtrand) % 10; | 1668 | int off = mt_random(& static_mtrand) % 10; |
1661 | for (j = 0; j < 256; j++) | 1669 | for (j = 0; j < 256; j++) |
1662 | { | 1670 | { |
1663 | buf[i + j] = j + off; | 1671 | buf[i + j] = j + off; |
1664 | } | 1672 | } |
@@ -1683,11 +1691,11 @@ test_compressed_stream_overflow (xd3_stream *stream, int ignore) | |||
1683 | } | 1691 | } |
1684 | 1692 | ||
1685 | /* Test transfer of exactly 32bits worth of data. */ | 1693 | /* Test transfer of exactly 32bits worth of data. */ |
1686 | if ((ret = test_streaming (stream, | 1694 | if ((ret = test_streaming (stream, |
1687 | buf, | 1695 | buf, |
1688 | buf + (1 << 20), | 1696 | buf + (1 << 20), |
1689 | buf + (2 << 20), | 1697 | buf + (2 << 20), |
1690 | 1 << 12))) | 1698 | 1 << 12))) |
1691 | { | 1699 | { |
1692 | goto fail; | 1700 | goto fail; |
1693 | } | 1701 | } |
@@ -1889,7 +1897,7 @@ test_recode_command2 (xd3_stream *stream, int has_source, | |||
1889 | } | 1897 | } |
1890 | 1898 | ||
1891 | /* First encode */ | 1899 | /* First encode */ |
1892 | snprintf_func (ecmd, TESTBUFSIZE, "%s %s -f %s %s %s %s %s %s %s", | 1900 | snprintf_func (ecmd, TESTBUFSIZE, "%s %s -f %s %s %s %s %s %s %s", |
1893 | program_name, test_softcfg_str, | 1901 | program_name, test_softcfg_str, |
1894 | has_adler32 ? "" : "-n ", | 1902 | has_adler32 ? "" : "-n ", |
1895 | has_apphead ? "-A=encode_apphead " : "-A= ", | 1903 | has_apphead ? "-A=encode_apphead " : "-A= ", |
@@ -1910,7 +1918,7 @@ test_recode_command2 (xd3_stream *stream, int has_source, | |||
1910 | snprintf_func (recmd, TESTBUFSIZE, | 1918 | snprintf_func (recmd, TESTBUFSIZE, |
1911 | "%s recode %s -f %s %s %s %s %s", program_name, test_softcfg_str, | 1919 | "%s recode %s -f %s %s %s %s %s", program_name, test_softcfg_str, |
1912 | recoded_adler32 ? "" : "-n ", | 1920 | recoded_adler32 ? "" : "-n ", |
1913 | !change_apphead ? "" : | 1921 | !change_apphead ? "" : |
1914 | (recoded_apphead ? "-A=recode_apphead " : "-A= "), | 1922 | (recoded_apphead ? "-A=recode_apphead " : "-A= "), |
1915 | recoded_secondary ? "-S djw " : "-S none ", | 1923 | recoded_secondary ? "-S djw " : "-S none ", |
1916 | TEST_DELTA_FILE, | 1924 | TEST_DELTA_FILE, |
@@ -2361,6 +2369,76 @@ test_no_output (xd3_stream *stream, int ignore) | |||
2361 | return 0; | 2369 | return 0; |
2362 | } | 2370 | } |
2363 | 2371 | ||
2372 | /* This tests that the default appheader works */ | ||
2373 | static int | ||
2374 | test_appheader (xd3_stream *stream, int ignore) | ||
2375 | { | ||
2376 | int i; | ||
2377 | int ret; | ||
2378 | char buf[TESTBUFSIZE]; | ||
2379 | char bogus[TESTBUFSIZE]; | ||
2380 | xoff_t ssize, tsize; | ||
2381 | test_setup (); | ||
2382 | |||
2383 | if ((ret = test_make_inputs (stream, &ssize, &tsize))) { return ret; } | ||
2384 | |||
2385 | snprintf_func (buf, TESTBUFSIZE, "%s -q -f -e -s %s %s %s", program_name, | ||
2386 | TEST_SOURCE_FILE, TEST_TARGET_FILE, TEST_DELTA_FILE); | ||
2387 | if ((ret = do_cmd (stream, buf))) { return ret; } | ||
2388 | |||
2389 | if ((ret = test_copy_to (program_name, TEST_RECON2_FILE))) { return ret; } | ||
2390 | |||
2391 | snprintf_func (buf, TESTBUFSIZE, "chmod 0700 %s", TEST_RECON2_FILE); | ||
2392 | if ((ret = do_cmd (stream, buf))) { return ret; } | ||
2393 | |||
2394 | if ((ret = test_save_copy (TEST_TARGET_FILE))) { return ret; } | ||
2395 | if ((ret = test_copy_to (TEST_SOURCE_FILE, TEST_TARGET_FILE))) { return ret; } | ||
2396 | |||
2397 | if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_COPY_FILE)) == 0) | ||
2398 | { | ||
2399 | return XD3_INVALID; // I.e., files are different! | ||
2400 | } | ||
2401 | |||
2402 | // Test that the target file is restored. | ||
2403 | snprintf_func (buf, TESTBUFSIZE, "(cd /tmp && %s -q -f -d %s)", | ||
2404 | TEST_RECON2_FILE, | ||
2405 | TEST_DELTA_FILE); | ||
2406 | if ((ret = do_cmd (stream, buf))) { return ret; } | ||
2407 | |||
2408 | if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_COPY_FILE)) != 0) | ||
2409 | { | ||
2410 | return ret; | ||
2411 | } | ||
2412 | |||
2413 | // Test a malicious string w/ entries > 4 in the appheader by having | ||
2414 | // the encoder write it: | ||
2415 | for (i = 0; i < TESTBUFSIZE / 4; ++i) | ||
2416 | { | ||
2417 | bogus[2*i] = 'G'; | ||
2418 | bogus[2*i+1] = '/'; | ||
2419 | } | ||
2420 | bogus[TESTBUFSIZE/2-1] = 0; | ||
2421 | |||
2422 | snprintf_func (buf, TESTBUFSIZE, | ||
2423 | "%s -q -f -A=%s -e -s %s %s %s", program_name, bogus, | ||
2424 | TEST_SOURCE_FILE, TEST_TARGET_FILE, TEST_DELTA_FILE); | ||
2425 | if ((ret = do_cmd (stream, buf))) { return ret; } | ||
2426 | // Then read it: | ||
2427 | snprintf_func (buf, TESTBUFSIZE, "(cd /tmp && %s -q -f -d %s)", | ||
2428 | TEST_RECON2_FILE, | ||
2429 | TEST_DELTA_FILE); | ||
2430 | if ((ret = do_cmd (stream, buf)) == 0) | ||
2431 | { | ||
2432 | return XD3_INVALID; // Impossible | ||
2433 | } | ||
2434 | if (!WIFEXITED(ret)) | ||
2435 | { | ||
2436 | return XD3_INVALID; // Must have crashed! | ||
2437 | } | ||
2438 | |||
2439 | return 0; | ||
2440 | } | ||
2441 | |||
2364 | /*********************************************************************** | 2442 | /*********************************************************************** |
2365 | Source identical optimization | 2443 | Source identical optimization |
2366 | ***********************************************************************/ | 2444 | ***********************************************************************/ |
@@ -2603,7 +2681,7 @@ test_string_matching (xd3_stream *stream, int ignore) | |||
2603 | default: CHECK(0); | 2681 | default: CHECK(0); |
2604 | } | 2682 | } |
2605 | 2683 | ||
2606 | snprintf_func (rptr, rbuf+TESTBUFSIZE-rptr, "%d/%d", | 2684 | snprintf_func (rptr, rbuf+TESTBUFSIZE-rptr, "%d/%d", |
2607 | inst->pos, inst->size); | 2685 | inst->pos, inst->size); |
2608 | rptr += strlen (rptr); | 2686 | rptr += strlen (rptr); |
2609 | 2687 | ||
@@ -2848,6 +2926,7 @@ xd3_selftest (void) | |||
2848 | DO_TEST (force_behavior, 0, 0); | 2926 | DO_TEST (force_behavior, 0, 0); |
2849 | DO_TEST (stdout_behavior, 0, 0); | 2927 | DO_TEST (stdout_behavior, 0, 0); |
2850 | DO_TEST (no_output, 0, 0); | 2928 | DO_TEST (no_output, 0, 0); |
2929 | DO_TEST (appheader, 0, 0); | ||
2851 | DO_TEST (command_line_arguments, 0, 0); | 2930 | DO_TEST (command_line_arguments, 0, 0); |
2852 | 2931 | ||
2853 | #if EXTERNAL_COMPRESSION | 2932 | #if EXTERNAL_COMPRESSION |