uncompress: fix buffer underrun by corrupted input
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 18 Aug 2011 12:29:41 +0000 (14:29 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 18 Aug 2011 12:29:41 +0000 (14:29 +0200)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
archival/libarchive/decompress_uncompress.c
testsuite/uncompress.tests [new file with mode: 0755]

index 44d8942..329894b 100644 (file)
@@ -163,7 +163,8 @@ unpack_Z_stream(int fd_in, int fd_out)
 
                if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
                        rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ);
-//error check??
+                       if (rsize < 0)
+                               bb_error_msg(bb_msg_read_error);
                        insize += rsize;
                }
 
@@ -195,6 +196,8 @@ unpack_Z_stream(int fd_in, int fd_out)
 
 
                        if (oldcode == -1) {
+                               if (code >= 256)
+                                       bb_error_msg_and_die("corrupted data"); /* %ld", code); */
                                oldcode = code;
                                finchar = (int) oldcode;
                                outbuf[outpos++] = (unsigned char) finchar;
@@ -239,6 +242,8 @@ unpack_Z_stream(int fd_in, int fd_out)
 
                        /* Generate output characters in reverse order */
                        while ((long) code >= (long) 256) {
+                               if (stackp <= &htabof(0))
+                                       bb_error_msg_and_die("corrupted data");
                                *--stackp = tab_suffixof(code);
                                code = tab_prefixof(code);
                        }
@@ -263,8 +268,7 @@ unpack_Z_stream(int fd_in, int fd_out)
                                                }
 
                                                if (outpos >= OBUFSIZ) {
-                                                       full_write(fd_out, outbuf, outpos);
-//error check??
+                                                       xwrite(fd_out, outbuf, outpos);
                                                        IF_DESKTOP(total_written += outpos;)
                                                        outpos = 0;
                                                }
@@ -292,8 +296,7 @@ unpack_Z_stream(int fd_in, int fd_out)
        } while (rsize > 0);
 
        if (outpos > 0) {
-               full_write(fd_out, outbuf, outpos);
-//error check??
+               xwrite(fd_out, outbuf, outpos);
                IF_DESKTOP(total_written += outpos;)
        }
 
diff --git a/testsuite/uncompress.tests b/testsuite/uncompress.tests
new file mode 100755 (executable)
index 0000000..51a2334
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+# Copyright 2011 by Denys Vlasenko
+# Licensed under GPLv2, see file LICENSE in this source tree.
+
+. ./testing.sh
+
+# testing "test name" "commands" "expected result" "file input" "stdin"
+
+testing "uncompress < \x1f\x9d\x90 \x01 x N" \
+'uncompress 2>&1 1>/dev/null; echo $?' \
+"\
+uncompress: corrupted data
+1
+" \
+"" "\
+\x1f\x9d\x90\
+\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\
+"
+
+exit $FAILCOUNT