Skip to content

Commit ef93ff7

Browse files
committed
Add appheader tests; fix buffer overflow in main_get_appheader
1 parent 7b6ff92 commit ef93ff7

File tree

2 files changed

+108
-28
lines changed

2 files changed

+108
-28
lines changed

Diff for: xdelta3/xdelta3-main.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -2810,14 +2810,15 @@ main_get_appheader (xd3_stream *stream, main_file *ifile,
28102810

28112811
if (appheadsz > 0)
28122812
{
2813+
const int kMaxArgs = 4;
28132814
char *start = (char*)apphead;
28142815
char *slash;
28152816
int place = 0;
2816-
char *parsed[4];
2817+
char *parsed[kMaxArgs];
28172818

28182819
memset (parsed, 0, sizeof (parsed));
28192820

2820-
while ((slash = strchr (start, '/')) != NULL)
2821+
while ((slash = strchr (start, '/')) != NULL && place < (kMaxArgs-1))
28212822
{
28222823
*slash = 0;
28232824
parsed[place++] = start;

Diff for: xdelta3/xdelta3-test.h

+105-26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* 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.
33
* Joshua P. MacDonald
44
*
55
* This program is free software; you can redistribute it and/or modify
@@ -54,7 +54,7 @@ void mt_init(mtrand *mt, uint32_t seed) {
5454
/* only MSBs of the array mt[]. */
5555
/* 2002/01/09 modified by Makoto Matsumoto */
5656
mt->mt_buffer_[i] =
57-
(1812433253UL * (mt->mt_buffer_[i-1] ^
57+
(1812433253UL * (mt->mt_buffer_[i-1] ^
5858
(mt->mt_buffer_[i-1] >> 30)) + i);
5959
}
6060
}
@@ -69,20 +69,20 @@ uint32_t mt_random (mtrand *mt) {
6969
int kk;
7070

7171
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) |
7373
(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] ^
7575
(y >> 1) ^ mag01[y & 0x1UL];
7676
}
7777
for (;kk < MT_LEN - 1; kk++) {
78-
y = (mt->mt_buffer_[kk] & UPPER_MASK) |
78+
y = (mt->mt_buffer_[kk] & UPPER_MASK) |
7979
(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)] ^
8181
(y >> 1) ^ mag01[y & 0x1UL];
8282
}
83-
y = (mt->mt_buffer_[MT_LEN - 1] & UPPER_MASK) |
83+
y = (mt->mt_buffer_[MT_LEN - 1] & UPPER_MASK) |
8484
(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] ^
8686
(y >> 1) ^ mag01[y & 0x1UL];
8787
mt->mt_index_ = 0;
8888
}
@@ -166,7 +166,7 @@ static int do_cmd (xd3_stream *stream, const char *buf)
166166
{
167167
stream->msg = "abnormal command termination";
168168
}
169-
return XD3_INTERNAL;
169+
return ret;
170170
}
171171
return 0;
172172
}
@@ -257,8 +257,10 @@ int test_setup (void)
257257
static int
258258
test_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out)
259259
{
260-
usize_t ts = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2;
261-
usize_t ss = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2;
260+
usize_t ts = (mt_random (&static_mtrand) % TEST_FILE_MEAN) +
261+
TEST_FILE_MEAN / 2;
262+
usize_t ss = (mt_random (&static_mtrand) % TEST_FILE_MEAN) +
263+
TEST_FILE_MEAN / 2;
262264
uint8_t *buf = (uint8_t*) malloc (ts + ss), *sbuf = buf, *tbuf = buf + ss;
263265
usize_t sadd = 0, sadd_max = (usize_t)(ss * TEST_ADD_RATIO);
264266
FILE *tf = NULL, *sf = NULL;
@@ -409,7 +411,7 @@ test_compare_files (const char* tgt, const char *rec)
409411
{
410412
if (obuf[i] != rbuf[i])
411413
{
412-
XPR(NT "byte %u (read %u @ %"Q"u) %d != %d\n",
414+
XPR(NT "byte %u (read %u @ %"Q"u) %d != %d\n",
413415
(int)i, (int)oc, offset, obuf[i], rbuf[i]);
414416
diffs++;
415417
return XD3_INTERNAL;
@@ -421,20 +423,20 @@ test_compare_files (const char* tgt, const char *rec)
421423

422424
fclose (orig);
423425
fclose (recons);
424-
if (diffs != 0)
426+
if (diffs != 0)
425427
{
426428
return XD3_INTERNAL;
427429
}
428430
return 0;
429431
}
430432

431433
static int
432-
test_save_copy (const char *origname)
434+
test_copy_to (const char *from, const char *to)
433435
{
434436
char buf[TESTBUFSIZE];
435437
int ret;
436438

437-
snprintf_func (buf, TESTBUFSIZE, "cp -f %s %s", origname, TEST_COPY_FILE);
439+
snprintf_func (buf, TESTBUFSIZE, "cp -f %s %s", from, to);
438440

439441
if ((ret = system (buf)) != 0)
440442
{
@@ -444,6 +446,12 @@ test_save_copy (const char *origname)
444446
return 0;
445447
}
446448

449+
static int
450+
test_save_copy (const char *origname)
451+
{
452+
return test_copy_to(origname, TEST_COPY_FILE);
453+
}
454+
447455
static int
448456
test_file_size (const char* file, xoff_t *size)
449457
{
@@ -499,7 +507,7 @@ test_read_integer_error (xd3_stream *stream, usize_t trunto, const char *msg)
499507
inp = buf->base;
500508
max = buf->base + buf->next - trunto;
501509

502-
if ((ret = xd3_read_uint32_t (stream, & inp, max, & rval)) !=
510+
if ((ret = xd3_read_uint32_t (stream, & inp, max, & rval)) !=
503511
XD3_INVALID_INPUT ||
504512
!MSG_IS (msg))
505513
{
@@ -1654,11 +1662,11 @@ test_compressed_stream_overflow (xd3_stream *stream, int ignore)
16541662
if ((buf = (uint8_t*) malloc (TWO_MEGS_AND_DELTA)) == NULL) { return ENOMEM; }
16551663

16561664
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)
16581666
{
16591667
int j;
16601668
int off = mt_random(& static_mtrand) % 10;
1661-
for (j = 0; j < 256; j++)
1669+
for (j = 0; j < 256; j++)
16621670
{
16631671
buf[i + j] = j + off;
16641672
}
@@ -1683,11 +1691,11 @@ test_compressed_stream_overflow (xd3_stream *stream, int ignore)
16831691
}
16841692

16851693
/* Test transfer of exactly 32bits worth of data. */
1686-
if ((ret = test_streaming (stream,
1687-
buf,
1688-
buf + (1 << 20),
1689-
buf + (2 << 20),
1690-
1 << 12)))
1694+
if ((ret = test_streaming (stream,
1695+
buf,
1696+
buf + (1 << 20),
1697+
buf + (2 << 20),
1698+
1 << 12)))
16911699
{
16921700
goto fail;
16931701
}
@@ -1889,7 +1897,7 @@ test_recode_command2 (xd3_stream *stream, int has_source,
18891897
}
18901898

18911899
/* 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",
18931901
program_name, test_softcfg_str,
18941902
has_adler32 ? "" : "-n ",
18951903
has_apphead ? "-A=encode_apphead " : "-A= ",
@@ -1910,7 +1918,7 @@ test_recode_command2 (xd3_stream *stream, int has_source,
19101918
snprintf_func (recmd, TESTBUFSIZE,
19111919
"%s recode %s -f %s %s %s %s %s", program_name, test_softcfg_str,
19121920
recoded_adler32 ? "" : "-n ",
1913-
!change_apphead ? "" :
1921+
!change_apphead ? "" :
19141922
(recoded_apphead ? "-A=recode_apphead " : "-A= "),
19151923
recoded_secondary ? "-S djw " : "-S none ",
19161924
TEST_DELTA_FILE,
@@ -2361,6 +2369,76 @@ test_no_output (xd3_stream *stream, int ignore)
23612369
return 0;
23622370
}
23632371

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+
23642442
/***********************************************************************
23652443
Source identical optimization
23662444
***********************************************************************/
@@ -2603,7 +2681,7 @@ test_string_matching (xd3_stream *stream, int ignore)
26032681
default: CHECK(0);
26042682
}
26052683

2606-
snprintf_func (rptr, rbuf+TESTBUFSIZE-rptr, "%d/%d",
2684+
snprintf_func (rptr, rbuf+TESTBUFSIZE-rptr, "%d/%d",
26072685
inst->pos, inst->size);
26082686
rptr += strlen (rptr);
26092687

@@ -2848,6 +2926,7 @@ xd3_selftest (void)
28482926
DO_TEST (force_behavior, 0, 0);
28492927
DO_TEST (stdout_behavior, 0, 0);
28502928
DO_TEST (no_output, 0, 0);
2929+
DO_TEST (appheader, 0, 0);
28512930
DO_TEST (command_line_arguments, 0, 0);
28522931

28532932
#if EXTERNAL_COMPRESSION

0 commit comments

Comments
 (0)