As I discovered today whilst trying to test some other modifications to
setup.exe, it currently silently decompresses a corrupt setup.bz2 into a zero
length file.

This should only cause problems if signature checking is disabled, or if the
bz2 file got corrupted before it was signed.

Patch attached.
>From a905bdbc2d61d375927c98f65e68b69f220fcffb Mon Sep 17 00:00:00 2001
From: Jon TURNEY <jon.tur...@dronecode.org.uk>
Date: Thu, 4 Nov 2010 18:34:13 +0000
Subject: [PATCH] Don't silently ignore corrupt bz2 files

(This should only be a problem when either signatures are ignored,
or the setup.bz2 is corrupted before being signed)

Return 0 indicating EOF when decompressing bz, after bzDecompress returns
BZ_STREAM_END, rather than continue to try to call bzDecompress beyond the
end of the compressed data, generating a BZ_SEQUENCE_ERROR.

Detect if an error occurred decompressing the ini file, and report it.
---
 ChangeLog      |   10 ++++++++++
 compress_bz.cc |    4 ++++
 compress_bz.h  |    1 +
 ini.cc         |   10 +++++-----
 4 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8448885..d8193ab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2010-11-04 Jon TURNEY <jon.tur...@dronecode.org.uk>
+
+       * compress_bz.h (compress): Add endReached flag.
+       * compress_bz.cc (read, compress_bz): Use endReached flag to return 0
+       for a read when EOF has been reached, after BZ2_bzDecompress returns
+       BZ_STREAM_END, rather than continue to try to call BZ2_bzDecompress
+       beyond the end of the compressed data, generating a BZ_SEQUENCE_ERROR.
+       * ini.cc (do_remote_ini): Now that bz2_stream doesn't always have a
+       spurious error, detect and report if an error occurred decompressing.
+
 2010-09-13  Václav Haisman  <v.hais...@sh.cvut.cz>
 
        * propsheet.cc (PropSheet::SetActivePage): Remove :: from call to
diff --git a/compress_bz.cc b/compress_bz.cc
index 5145015..866a1ff 100644
--- a/compress_bz.cc
+++ b/compress_bz.cc
@@ -36,6 +36,7 @@ compress_bz::compress_bz (io_stream * parent) : peeklen (0), 
position (0)
   owns_original = true;
 
   initialisedOk = 0;
+  endReached = 0;
   bufN = 0;
   writing = 0;
   strm.bzalloc = 0;
@@ -57,6 +58,8 @@ compress_bz::read (void *buffer, size_t len)
 {
   if (!initialisedOk || writing)
     return EBADF;
+  if (endReached)
+    return 0;
   if (len == 0)
     return 0;
 
@@ -113,6 +116,7 @@ compress_bz::read (void *buffer, size_t len)
        }
       if (ret == BZ_STREAM_END)
        {
+         endReached = 1;
          position += len - strm.avail_out;
          return len - strm.avail_out;
        }
diff --git a/compress_bz.h b/compress_bz.h
index dffd789..24f68a7 100644
--- a/compress_bz.h
+++ b/compress_bz.h
@@ -63,6 +63,7 @@ private:
   int lasterr;
   bz_stream strm;
   int initialisedOk;
+  int endReached;
   int bufN;
   char buf[4096];
   int writing;
diff --git a/ini.cc b/ini.cc
index 51c6fa3..f27a4e5 100644
--- a/ini.cc
+++ b/ini.cc
@@ -192,17 +192,17 @@ do_remote_ini (HWND owner)
            {
              io_stream *uncompressed = new io_stream_memory ();
 
-             if (io_stream::copy (bz2_stream, uncompressed) != 0 ||
-                 bz2_stream->error () == EIO)
+             if ((io_stream::copy (bz2_stream, uncompressed) != 0) ||
+                  (bz2_stream->error() != 0))
                {
                  /* There was a problem decompressing bz2.  */
-                 delete bz2_stream;
-                 delete uncompressed;
                  ini_file = NULL;
                  log (LOG_PLAIN) <<
-                   "Warning: Problem encountered while uncompressing " <<
+                   "Warning: Error code " << bz2_stream->error() << " occurred 
while uncompressing " <<
                    current_ini_name << " - possibly truncated or corrupt bzip2"
                    " file.  Retrying with uncompressed version." << endLog;
+                 delete bz2_stream;
+                 delete uncompressed;
                }
              else
                {
-- 
1.7.2.3

Reply via email to