On Fri Jan 06 13:16:40 2012,
http://wookey.livejournal.com/ wrote:
Show quoted text
Show quoted text> The short version is that jh_manifest adds a file entry and the
> previously-OK directory entry becomes corrupt with an incorrect
> compressed size.
It's about deflated empty files / directories, which have size==0 but
csize==2.
I'm attaching a test case for this. I'm also attaching a fix that I made
before discovering it's already fixed in another way with r14788 of the
SVN repository at
http://svn.ali.as/cpan/trunk/Archive-Zip .
The binary test data is included in the Git patch, but I'm also
attaching it as an uuencoded version for your convenience.
Please note that a bug in t/common.pl makes all the 'testZip()' tests in
for instance t/02_main.t get skipped. I'm also including a proposed
patch for this.
Hope at least some parts of this will be useful. Please consider making
a release with a fix for this issue soon.
Thanks for your work on free software,
--
Niko Tyni (Debian Perl Group)
ntyni@debian.org
From b8adb151fbc48f2cd7b5bb3b95a8e4d8152225e6 Mon Sep 17 00:00:00 2001
From: Niko Tyni <ntyni@debian.org>
Date: Tue, 10 Jan 2012 20:40:04 +0200
Subject: [PATCH 2/3] TODO test for [rt.cpan.org #73797]: deflated empty file
/ directory gets corrupted
When reading a zip with a deflated empty file / directory and then
writing it out, the output gets corrupted. 'unzip -t' outputs:
Archive: testout.zip
META-INF/: ucsize 0 <> csize 2 for STORED entry
continuing with "compressed" size value
testing: META-INF/ bad CRC 1a6cd7b3 (should be 00000000)
Add a TODO test for this. The test file was created with 'jar'
from OpenJDK 6:
mkdir empty && /usr/lib/jvm/java-6-openjdk/bin/jar c empty/ > empty.jar
---
t/17_bug_73797.t | 29 +++++++++++++++++++++++++++++
t/data/jar.zip | Bin 0 -> 427 bytes
2 files changed, 29 insertions(+), 0 deletions(-)
create mode 100644 t/17_bug_73797.t
create mode 100644 t/data/jar.zip
diff --git a/t/17_bug_73797.t b/t/17_bug_73797.t
new file mode 100644
index 0000000..9280d84
--- /dev/null
+++ b/t/17_bug_73797.t
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use strict;
+
+BEGIN {
+ $| = 1;
+ $^W = 1;
+}
+use Archive::Zip qw( :ERROR_CODES );
+use Test::More tests => 4;
+
+BEGIN {
+ unshift @INC, "t/";
+ require( File::Spec->catfile('t', 'common.pl') )
+ or die "Can't load t/common.pl";
+}
+
+my $zip = Archive::Zip->new();
+isa_ok( $zip, 'Archive::Zip' );
+is( $zip->read('t/data/jar.zip'), AZ_OK, 'Read file' );
+is($zip->writeToFileNamed(OUTPUTZIP), AZ_OK, 'Wrote file');
+
+my ($status, $zipout) = testZip();
+# STDERR->print("status= $status, out=$zipout\n");
+skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
+TODO: {
+ local $TODO = "deflated empty files/directories corrupt the output";
+is( $status, 0, "output zip isn't corrupted" );
+}
diff --git a/t/data/jar.zip b/t/data/jar.zip
new file mode 100644
index 0000000000000000000000000000000000000000..a58c356035743874f2d61b2e4fbaf240f8e9b73d
GIT binary patch
literal 427
zcmWIWW@Zs#-~d9YA}t37B*4kQ!r<!~;;8HC=cfPf6axb@Lx49s2S^1IR9OH{%_2Y*
zaLvAsex7cw!6ACSZl8V6oc8h7)w{^+t*dqJ%=yhh23L$9JT21m^40P5y;!=6g>%MB
z$s^J;H8NPHKhyk?rY8PWJX~!0l4oMt70*;(XMQUBSi}f+NWSGHR(GH^APjN{7uZpP
zXue<uik7772Y53wi7=pg6y^(%M^ORX<sfgPYelvf<V^&y1v24Ukvt7Dfr|mR`w%7^
W12Vy`Wn}{iG6Uf{ApIP~VE_PkdPo=m
literal 0
HcmV?d00001
--
1.7.8.2
From 92b2b67dd4728d10b053f172063be6ad1d14da8f Mon Sep 17 00:00:00 2001
From: Niko Tyni <ntyni@debian.org>
Date: Wed, 11 Jan 2012 21:47:46 +0200
Subject: [PATCH 3/3] Fix for [rt.cpan.org #73797]: deflated empty file /
directory gets corrupted
The output header needs to be refreshed also in the case where
uncompressed size is 0 but the compressed size is > 0 (deflation
of an empty file.)
---
lib/Archive/Zip/Member.pm | 2 +-
t/17_bug_73797.t | 3 ---
2 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/lib/Archive/Zip/Member.pm b/lib/Archive/Zip/Member.pm
index f86ef75..d4d709a 100644
--- a/lib/Archive/Zip/Member.pm
+++ b/lib/Archive/Zip/Member.pm
@@ -1011,7 +1011,7 @@ sub _writeToFileHandle {
# I need to do this if I can't refresh the header
# and I don't know compressed size or crc32 fields.
my $headerFieldsUnknown = (
- ( $self->uncompressedSize() > 0 )
+ ( $self->uncompressedSize() > 0 or $self->compressedSize > 0 )
and ($self->compressionMethod() == COMPRESSION_STORED
or $self->desiredCompressionMethod() == COMPRESSION_DEFLATED )
);
diff --git a/t/17_bug_73797.t b/t/17_bug_73797.t
index 9280d84..8cacf54 100644
--- a/t/17_bug_73797.t
+++ b/t/17_bug_73797.t
@@ -23,7 +23,4 @@ is($zip->writeToFileNamed(OUTPUTZIP), AZ_OK, 'Wrote file');
my ($status, $zipout) = testZip();
# STDERR->print("status= $status, out=$zipout\n");
skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
-TODO: {
- local $TODO = "deflated empty files/directories corrupt the output";
is( $status, 0, "output zip isn't corrupted" );
-}
--
1.7.8.2
Message body not shown because it is not plain text.
From c191ff37a6998471dd37d6f5f383236a2e6f492c Mon Sep 17 00:00:00 2001
From: Niko Tyni <ntyni@debian.org>
Date: Tue, 10 Jan 2012 20:28:48 +0200
Subject: [PATCH 1/3] Make the embedded File::Which::which() work in BEGIN
blocks
The File::Which::which() subroutine uses a lexical variable @path_ext,
which used to be uninitialized when the subroutine was called
from BEGIN blocks.
This included the 'use constant' lines, making both HAVEZIP and HAVEUNZIP
constants unconditionally false and disabling 'testzip' functionality
in for instance t/02_main.t:
ok 132 # skip No 'unzip' program to test against
---
t/common.pl | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/t/common.pl b/t/common.pl
index 808d6b8..1560fd2 100644
--- a/t/common.pl
+++ b/t/common.pl
@@ -7,6 +7,7 @@ use constant OUTPUTZIP => 'testout.zip';
# Do we have the 'zip' and 'unzip' programs?
# Embed a copy of the module, rather than adding a dependency
+BEGIN {
SCOPE: {
package File::Which;
@@ -103,6 +104,7 @@ SCOPE: {
}
}
}
+}
use constant HAVEZIP => !! File::Which::which('zip');
use constant HAVEUNZIP => !! File::Which::which('unzip');
--
1.7.8.2