pmqs / IO-Compress

IO-Compress - Perl5 module to read/write compressed data in multiple formats
14 stars 16 forks source link

Calling nextStream on an IO::Uncompress::Zip object in Transparent mode dies when input is uncompressed #34

Closed tlhackque closed 2 years ago

tlhackque commented 2 years ago

The recommended mechanism for processing all members of a Zip file is to call nextStream at EOF untiil it returns 0 (no more data).

If an uncompressed file is passed to such an application, the application doesn't know that the data is uncompressed. So at EOF it calls nextStream to see if there's another member.

IO::Compress::Unzip isa IO::Uncompress::RawInflate, which isa IO::Uncompress::Base, where the nextStream method call lands. In turn, it calls IO::Unompress::Base::gotoNextStream.

When IO::Unompress::Base::gotoNextStream calls $self->reset(), reset's subsequent call to *$self->{Uncomp}->reset() dies, since *$self->{Uncomp} is undefined in this case.

Demo:

$ cat >foo.txt <<EOF
1234
5678
EOF
$  ./nextstream
1234
5678
Can't call method "reset" on an undefined value at .../IO/Uncompress/Base.pm line 991, <GEN0> line 2.

$ modver IO::Uncompress::Unzip IO::Uncompress::Base
IO::Uncompress::Unzip 2.102
IO::Uncompress::Base 2.102
#!/usr/bin/perl
use warnings;
use strict;
use IO::Uncompress::Unzip( qw/$UnzipError/);
my $in = IO::Uncompress::Unzip->new( "foo.txt",
                                     { AutoClose => 1, Transparent => 1,} ) or
  die( "foo.txt: $UnzipError\n" );
my $status;
for( $status = 1; $status > 0; $status = $in->nextStream ) {
    print $_ while( <$in> );
}
die( "error: $!\n" ) if( $status < 0 );
exit;

This patch seems to work, at least for this case.

--- IO/Uncompress/Base.pm.orig     2021-02-28 03:31:51.000000000 -0500
+++ IO/Uncompress/Base.pm          2021-10-27 10:36:58.000000000 -0400
@@ -1004,10 +1004,12 @@

 sub nextStream
 {
     my $self = shift ;

+    return 0 if( *$self->{Plain} );
+
     my $status = $self->gotoNextStream();
     $status == 1
         or return $status ;

     *$self->{Pending} = ''
pmqs commented 2 years ago

Hi @tlhackque

I can reproduce the issue with the sample code you provided and the patch does indeed silence the error.

Need to have a think about whether your fix has any unexpected knock-on impacts, but this is an issue that needs fixed

thanks for the very good bug report

pmqs commented 2 years ago

Closing issue. Fixed included in b0f93fe62f84b7d4d4bb8d2ea8e6d5432887103f