Skip to content

Commit 0b0ef93

Browse files
committed
kwaj_read_headers(): fix handling of non-terminated strings
1 parent 4c004e9 commit 0b0ef93

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+164
-14
lines changed

Diff for: libmspack/ChangeLog

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
2017-11-26 Stuart Caie <kyzer@cabextract.org.uk>
2+
3+
* kwajd_read_headers(): fix up the logic of reading the filename and
4+
extension headers to avoid a one or two byte overwrite. Thanks to
5+
Jakub Wilk for finding the issue.
6+
7+
* test/kwajd_test.c: add tests for KWAJ filename.ext handling
8+
19
2017-10-16 Stuart Caie <kyzer@cabextract.org.uk>
210

311
* test/cabd_test.c: update the short string tests to expect not only

Diff for: libmspack/Makefile.am

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ lib_LTLIBRARIES = libmspack.la
2424
noinst_LTLIBRARIES = libmscabd.la libmschmd.la
2525
noinst_PROGRAMS = examples/cabd_memory examples/multifh test/cabd_md5 \
2626
test/cabd_test test/chmd_find test/chmd_md5 \
27-
test/chmd_order test/chminfo
27+
test/chmd_order test/chminfo test/kwajd_test
2828

2929
libmspack_la_SOURCES = mspack/mspack.h \
3030
mspack/system.h mspack/system.c \
@@ -89,3 +89,5 @@ test_chmd_order_SOURCES = test/chmd_order.c test/md5.c test/md5.h \
8989
test_chmd_order_LDADD = libmschmd.la
9090
test_chminfo_SOURCES = test/chminfo.c libmschmd.la
9191
test_chminfo_LDADD = libmschmd.la
92+
test_kwajd_test_SOURCES = test/kwajd_test.c libmspack.la
93+
test_kwajd_test_LDADD = libmspack.la

Diff for: libmspack/mspack/kwajd.c

+19-13
Original file line numberDiff line numberDiff line change
@@ -198,30 +198,36 @@ static int kwajd_read_headers(struct mspack_system *sys,
198198

199199
/* filename and extension */
200200
if (hdr->headers & (MSKWAJ_HDR_HASFILENAME | MSKWAJ_HDR_HASFILEEXT)) {
201-
off_t pos = sys->tell(fh);
202-
char *fn = (char *) sys->alloc(sys, (size_t) 13);
203-
201+
int len;
204202
/* allocate memory for maximum length filename */
205-
if (! fn) return MSPACK_ERR_NOMEMORY;
206-
hdr->filename = fn;
203+
char *fn = (char *) sys->alloc(sys, (size_t) 13);
204+
if (!(hdr->filename = fn)) return MSPACK_ERR_NOMEMORY;
207205

208206
/* copy filename if present */
209207
if (hdr->headers & MSKWAJ_HDR_HASFILENAME) {
210-
if (sys->read(fh, &buf[0], 9) != 9) return MSPACK_ERR_READ;
211-
for (i = 0; i < 9; i++, fn++) if (!(*fn = buf[i])) break;
212-
pos += (i < 9) ? i+1 : 9;
213-
if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START))
208+
/* read and copy up to 9 bytes of a null terminated string */
209+
if ((len = sys->read(fh, &buf[0], 9)) < 2) return MSPACK_ERR_READ;
210+
for (i = 0; i < len; i++) if (!(*fn++ = buf[i])) break;
211+
/* if string was 9 bytes with no null terminator, reject it */
212+
if (i == 9 && buf[8] != '\0') return MSPACK_ERR_DATAFORMAT;
213+
/* seek to byte after string ended in file */
214+
if (sys->seek(fh, (off_t)(i + 1 - len), MSPACK_SYS_SEEK_CUR))
214215
return MSPACK_ERR_SEEK;
216+
fn--; /* remove the null terminator */
215217
}
216218

217219
/* copy extension if present */
218220
if (hdr->headers & MSKWAJ_HDR_HASFILEEXT) {
219221
*fn++ = '.';
220-
if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ;
221-
for (i = 0; i < 4; i++, fn++) if (!(*fn = buf[i])) break;
222-
pos += (i < 4) ? i+1 : 4;
223-
if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START))
222+
/* read and copy up to 4 bytes of a null terminated string */
223+
if ((len = sys->read(fh, &buf[0], 4)) < 2) return MSPACK_ERR_READ;
224+
for (i = 0; i < len; i++) if (!(*fn++ = buf[i])) break;
225+
/* if string was 4 bytes with no null terminator, reject it */
226+
if (i == 4 && buf[3] != '\0') return MSPACK_ERR_DATAFORMAT;
227+
/* seek to byte after string ended in file */
228+
if (sys->seek(fh, (off_t)(i + 1 - len), MSPACK_SYS_SEEK_CUR))
224229
return MSPACK_ERR_SEEK;
230+
fn--; /* remove the null terminator */
225231
}
226232
*fn = '\0';
227233
}

Diff for: libmspack/test/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ chmd_find
88
chmd_md5
99
chmd_order
1010
chminfo
11+
kwajd_test

Diff for: libmspack/test/kwajd_test.c

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/* KWAJ regression test suite */
2+
3+
#ifdef HAVE_CONFIG_H
4+
#include <config.h>
5+
#endif
6+
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <string.h>
10+
#include <mspack.h>
11+
12+
unsigned int test_count = 0;
13+
#define TEST(x) do {\
14+
test_count++; \
15+
if (!(x)) {printf("%s:%d FAILED %s\n",__FUNCTION__,__LINE__,#x);exit(1);} \
16+
} while (0)
17+
18+
/* test parsing of KWAJ filename/extension headers */
19+
void kwajd_open_test_01() {
20+
struct mskwaj_decompressor *kwajd;
21+
struct mskwajd_header *hdr;
22+
23+
kwajd = mspack_create_kwaj_decompressor(NULL);
24+
TEST(kwajd != NULL);
25+
26+
hdr = kwajd->open(kwajd, "test_files/kwajd/f00.kwj");
27+
TEST(hdr != NULL);
28+
TEST(hdr->filename == NULL);
29+
kwajd->close(kwajd, hdr);
30+
31+
#define TEST_FNAME(testfile, fname) \
32+
hdr = kwajd->open(kwajd, testfile); \
33+
TEST(hdr != NULL); \
34+
TEST(hdr->filename != NULL); \
35+
TEST(!strcmp(fname, hdr->filename)); \
36+
kwajd->close(kwajd, hdr)
37+
#define TEST_FNAME_BAD(testfile) \
38+
hdr = kwajd->open(kwajd, testfile); \
39+
TEST(hdr == NULL); \
40+
TEST(kwajd->last_error(kwajd) == MSPACK_ERR_DATAFORMAT)
41+
42+
TEST_FNAME("test_files/kwajd/f01.kwj", ".1");
43+
TEST_FNAME("test_files/kwajd/f02.kwj", ".12");
44+
TEST_FNAME("test_files/kwajd/f03.kwj", ".123");
45+
46+
TEST_FNAME("test_files/kwajd/f10.kwj", "1");
47+
TEST_FNAME("test_files/kwajd/f11.kwj", "1.1");
48+
TEST_FNAME("test_files/kwajd/f12.kwj", "1.12");
49+
TEST_FNAME("test_files/kwajd/f13.kwj", "1.123");
50+
51+
TEST_FNAME("test_files/kwajd/f20.kwj", "12");
52+
TEST_FNAME("test_files/kwajd/f21.kwj", "12.1");
53+
TEST_FNAME("test_files/kwajd/f22.kwj", "12.12");
54+
TEST_FNAME("test_files/kwajd/f23.kwj", "12.123");
55+
56+
TEST_FNAME("test_files/kwajd/f30.kwj", "123");
57+
TEST_FNAME("test_files/kwajd/f31.kwj", "123.1");
58+
TEST_FNAME("test_files/kwajd/f32.kwj", "123.12");
59+
TEST_FNAME("test_files/kwajd/f33.kwj", "123.123");
60+
61+
TEST_FNAME("test_files/kwajd/f40.kwj", "1234");
62+
TEST_FNAME("test_files/kwajd/f41.kwj", "1234.1");
63+
TEST_FNAME("test_files/kwajd/f42.kwj", "1234.12");
64+
TEST_FNAME("test_files/kwajd/f43.kwj", "1234.123");
65+
66+
TEST_FNAME("test_files/kwajd/f50.kwj", "12345");
67+
TEST_FNAME("test_files/kwajd/f51.kwj", "12345.1");
68+
TEST_FNAME("test_files/kwajd/f52.kwj", "12345.12");
69+
TEST_FNAME("test_files/kwajd/f53.kwj", "12345.123");
70+
71+
TEST_FNAME("test_files/kwajd/f60.kwj", "123456");
72+
TEST_FNAME("test_files/kwajd/f61.kwj", "123456.1");
73+
TEST_FNAME("test_files/kwajd/f62.kwj", "123456.12");
74+
TEST_FNAME("test_files/kwajd/f63.kwj", "123456.123");
75+
76+
TEST_FNAME("test_files/kwajd/f70.kwj", "1234567");
77+
TEST_FNAME("test_files/kwajd/f71.kwj", "1234567.1");
78+
TEST_FNAME("test_files/kwajd/f72.kwj", "1234567.12");
79+
TEST_FNAME("test_files/kwajd/f73.kwj", "1234567.123");
80+
81+
TEST_FNAME("test_files/kwajd/f80.kwj", "12345678");
82+
TEST_FNAME("test_files/kwajd/f81.kwj", "12345678.1");
83+
TEST_FNAME("test_files/kwajd/f82.kwj", "12345678.12");
84+
TEST_FNAME("test_files/kwajd/f83.kwj", "12345678.123");
85+
86+
TEST_FNAME_BAD("test_files/kwajd/f04.kwj");
87+
TEST_FNAME_BAD("test_files/kwajd/f14.kwj");
88+
TEST_FNAME_BAD("test_files/kwajd/f24.kwj");
89+
TEST_FNAME_BAD("test_files/kwajd/f34.kwj");
90+
TEST_FNAME_BAD("test_files/kwajd/f44.kwj");
91+
TEST_FNAME_BAD("test_files/kwajd/f54.kwj");
92+
TEST_FNAME_BAD("test_files/kwajd/f64.kwj");
93+
TEST_FNAME_BAD("test_files/kwajd/f74.kwj");
94+
TEST_FNAME_BAD("test_files/kwajd/f84.kwj");
95+
96+
TEST_FNAME_BAD("test_files/kwajd/f90.kwj");
97+
TEST_FNAME_BAD("test_files/kwajd/f91.kwj");
98+
TEST_FNAME_BAD("test_files/kwajd/f92.kwj");
99+
TEST_FNAME_BAD("test_files/kwajd/f93.kwj");
100+
TEST_FNAME_BAD("test_files/kwajd/f94.kwj");
101+
102+
103+
mspack_destroy_kwaj_decompressor(kwajd);
104+
}
105+
106+
int main() {
107+
int selftest;
108+
109+
MSPACK_SYS_SELFTEST(selftest);
110+
TEST(selftest == MSPACK_ERR_OK);
111+
112+
kwajd_open_test_01();
113+
114+
printf("ALL %d TESTS PASSED.\n", test_count);
115+
return 0;
116+
}

Diff for: libmspack/test/test_files/kwajd/f00.kwj

15 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f01.kwj

17 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f02.kwj

18 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f03.kwj

19 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f04.kwj

19 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f10.kwj

17 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f11.kwj

19 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f12.kwj

20 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f13.kwj

21 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f14.kwj

21 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f20.kwj

18 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f21.kwj

20 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f22.kwj

21 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f23.kwj

22 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f24.kwj

22 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f30.kwj

19 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f31.kwj

21 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f32.kwj

22 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f33.kwj

23 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f34.kwj

23 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f40.kwj

20 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f41.kwj

22 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f42.kwj

23 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f43.kwj

24 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f44.kwj

24 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f50.kwj

21 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f51.kwj

23 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f52.kwj

24 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f53.kwj

25 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f54.kwj

25 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f60.kwj

22 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f61.kwj

24 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f62.kwj

25 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f63.kwj

26 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f64.kwj

26 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f70.kwj

23 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f71.kwj

25 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f72.kwj

26 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f73.kwj

27 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f74.kwj

27 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f80.kwj

24 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f81.kwj

26 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f82.kwj

27 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f83.kwj

28 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f84.kwj

28 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f90.kwj

24 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f91.kwj

26 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f92.kwj

27 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f93.kwj

28 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/f94.kwj

28 Bytes
Binary file not shown.

Diff for: libmspack/test/test_files/kwajd/make.pl

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/perl -w
2+
use strict;
3+
my $name = '123456789';
4+
for my $file (0 .. 9) {
5+
for my $ext (0 .. 4) {
6+
open my $fh, '>', "f$file$ext.kwj";
7+
my $offset = 14 + $file + $ext;
8+
my $flags = ($file > 0 ? 8 : 0) | ($ext > 0 ? 16 : 0);
9+
print $fh pack 'A4Vvvv', 'KWAJ', 0xD127F088, 0, $offset, $flags;
10+
print $fh substr $name, 0, $file if $file > 0;
11+
print $fh "\0" if $file > 0 && $file < 9;
12+
print $fh substr $name, 0, $ext if $ext > 0;
13+
print $fh "\0" if $ext > 0 && $ext < 4;
14+
print $fh "\xFF";
15+
close $fh;
16+
}
17+
}

0 commit comments

Comments
 (0)