Skip Menu |

This queue is for tickets about the Compress-Raw-Zlib CPAN distribution.

Report information
The Basics
Id: 91558
Status: resolved
Priority: 0/
Queue: Compress-Raw-Zlib

People
Owner: Nobody in particular
Requestors: 'spro^^*%*^6ut# [...] &$%*c
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 2.064



Subject: [PATCH] Handle non-PVs better
See the attached patch. I tested this with a debugging bleadperl, which failed assertions whenever SvCUR was used on a typeglob. I’m afraid I have not had time to check whether we need new #defines for 5.6 and 5.8, and I do not foresee having an opportunity any time soon. Some of the changes to Zlib.xs are not tested in the new test script in the patch, as I don’t know how to reach all the code paths. I am currently working on a debug mode for perl (PERL_DEBUG_READONLY_COW) that will turn all COW buffer violations into crashes. That was what drew my attention to this. The changes to scan() fix crashes that I am getting from some of the IO-Compress tests.
Subject: patch.txt
diff -Nurp Compress-Raw-Zlib-2.063-_WLyA5-orig/MANIFEST Compress-Raw-Zlib-2.063-_WLyA5/MANIFEST --- Compress-Raw-Zlib-2.063-_WLyA5-orig/MANIFEST 2013-11-02 08:24:44.000000000 -0700 +++ Compress-Raw-Zlib-2.063-_WLyA5/MANIFEST 2013-12-15 16:31:36.000000000 -0800 @@ -6,6 +6,7 @@ t/02zlib.t t/07bufsize.t t/09limitoutput.t t/18lvalue.t +t/19nonpv.t t/99pod.t t/Test/Builder.pm t/Test/More.pm diff -Nurp Compress-Raw-Zlib-2.063-_WLyA5-orig/Zlib.xs Compress-Raw-Zlib-2.063-_WLyA5/Zlib.xs --- Compress-Raw-Zlib-2.063-_WLyA5-orig/Zlib.xs 2013-05-19 04:21:34.000000000 -0700 +++ Compress-Raw-Zlib-2.063-_WLyA5/Zlib.xs 2013-12-15 21:28:14.000000000 -0800 @@ -864,13 +864,14 @@ _inflateInit(flags, windowBits, bufsize, Safefree(s) ; s = NULL ; } - else if (SvCUR(dictionary)) { + else if (sv_len(dictionary)) { #ifdef AT_LEAST_ZLIB_1_2_2_1 /* Zlib 1.2.2.1 or better allows a dictionary with raw inflate */ if (s->WindowBits < 0) { + STRLEN dlen; + const Bytef* b = (const Bytef*)SvPVbyte(dictionary, dlen); err = inflateSetDictionary(&(s->stream), - (const Bytef*)SvPVbyte_nolen(dictionary), - SvCUR(dictionary)); + b, dlen); if (err != Z_OK) { Safefree(s) ; s = NULL ; @@ -938,6 +939,7 @@ deflate (s, buf, output) uInt prefix = NO_INIT int RETVAL = 0; uLong bufinc = NO_INIT + STRLEN origlen = NO_INIT CODE: bufinc = s->bufsize; @@ -949,8 +951,8 @@ deflate (s, buf, output) if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) croak("Wide character in Compress::Raw::Zlib::Deflate::deflate input parameter"); #endif - s->stream.next_in = (Bytef*)SvPV_nomg_nolen(buf) ; - s->stream.avail_in = SvCUR(buf) ; + s->stream.next_in = (Bytef*)SvPV_nomg(buf, origlen) ; + s->stream.avail_in = origlen; if (s->flags & FLAG_CRC32) s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ; @@ -1033,7 +1035,7 @@ deflate (s, buf, output) } s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ; - s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ; + s->uncompressedBytes += origlen - s->stream.avail_in ; s->last_error = RETVAL ; if (RETVAL == Z_OK) { @@ -1365,6 +1367,7 @@ inflate (s, buf, output, eof=FALSE) #ifdef UTF8_AVAILABLE bool out_utf8 = FALSE; #endif + STRLEN origlen; CODE: bufinc = s->bufsize; /* If the buffer is a reference, dereference it */ @@ -1381,8 +1384,8 @@ inflate (s, buf, output, eof=FALSE) #endif /* initialise the input buffer */ - s->stream.next_in = (Bytef*)SvPV_nomg_nolen(buf) ; - s->stream.avail_in = SvCUR(buf) ; + s->stream.next_in = (Bytef*)SvPV_nomg(buf, origlen) ; + s->stream.avail_in = origlen ; /* and retrieve the output buffer */ output = deRef_l(output, "inflate") ; @@ -1445,10 +1448,11 @@ Perl_sv_dump(output); */ if (RETVAL == Z_NEED_DICT && s->dictionary) { + STRLEN dlen; + const Bytef* b = SvPV(s->dictionary, dlen) ; s->dict_adler = s->stream.adler ; RETVAL = inflateSetDictionary(&(s->stream), - (const Bytef*)SvPVX(s->dictionary), - SvCUR(s->dictionary)); + b, dlen); if (RETVAL == Z_OK) continue; } @@ -1497,7 +1501,7 @@ Perl_sv_dump(output); */ s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length; s->uncompressedBytes += s->bytesInflated ; - s->compressedBytes += SvCUR(buf) - s->stream.avail_in ; + s->compressedBytes += origlen - s->stream.avail_in ; SvPOK_only(output); SvCUR_set(output, prefix_length + s->bytesInflated) ; @@ -1571,7 +1575,7 @@ inflateSync (s, buf) #endif /* initialise the input buffer */ - s->stream.next_in = (Bytef*)SvPV_nomg_nolen(buf) ; + s->stream.next_in = (Bytef*)SvPV_force_nomg_nolen(buf) ; s->stream.avail_in = SvCUR(buf) ; /* inflateSync doesn't create any output */ diff -Nurp Compress-Raw-Zlib-2.063-_WLyA5-orig/t/19nonpv.t Compress-Raw-Zlib-2.063-_WLyA5/t/19nonpv.t --- Compress-Raw-Zlib-2.063-_WLyA5-orig/t/19nonpv.t 1969-12-31 16:00:00.000000000 -0800 +++ Compress-Raw-Zlib-2.063-_WLyA5/t/19nonpv.t 2013-12-21 05:54:51.000000000 -0800 @@ -0,0 +1,135 @@ +BEGIN { + if ($ENV{PERL_CORE}) { + chdir 't' if -d 't'; + @INC = ("../lib", "lib/compress"); + } +} + +use lib qw(t t/compress); +use strict; +use warnings; + +use Test::More ; +use CompTestUtils; + +BEGIN +{ + # use Test::NoWarnings, if available + my $extra = 0 ; + $extra = 1 + if eval { require Test::NoWarnings ; import Test::NoWarnings; 1 }; + + plan tests => 38 + $extra ; + + use_ok('Compress::Raw::Zlib', 2) ; +} + + + +my $hello = <<EOM ; +hello world +this is a test +EOM + +my $len = length $hello ; + +# Check zlib_version and ZLIB_VERSION are the same. +SKIP: { + skip "TEST_SKIP_VERSION_CHECK is set", 1 + if $ENV{TEST_SKIP_VERSION_CHECK}; + is Compress::Raw::Zlib::zlib_version, ZLIB_VERSION, + "ZLIB_VERSION matches Compress::Raw::Zlib::zlib_version" ; +} + + +{ + title 'non-PV dictionary'; + # ============================== + + my $dictionary = *hello ; + + ok my $x = new Compress::Raw::Zlib::Deflate({-Level => Z_BEST_COMPRESSION, + -Dictionary => $dictionary}) ; + + my $dictID = $x->dict_adler() ; + + my ($X, $Y, $Z); + cmp_ok $x->deflate($hello, $X), '==', Z_OK; + cmp_ok $x->flush($Y), '==', Z_OK; + $X .= $Y ; + + ok my $k = new Compress::Raw::Zlib::Inflate(-Dictionary => $dictionary) ; + + cmp_ok $k->inflate($X, $Z), '==', Z_STREAM_END; + is $k->dict_adler(), $dictID; + is $hello, $Z ; + +} + +{ + + title "deflate/inflate - non-PV buffers"; + # ============================== + + my $hello = *hello ; + my @hello = split('', $hello) ; + my ($err, $x, $X, $status); + + ok( ($x, $err) = new Compress::Raw::Zlib::Deflate, "Create deflate object" ); + ok $x, "Compress::Raw::Zlib::Deflate ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + ok ! defined $x->msg() ; + is $x->total_in(), 0, "total_in() == 0" ; + is $x->total_out(), 0, "total_out() == 0" ; + + $X = "" ; + my $Answer = ''; + $status = $x->deflate($hello, $X) ; + $Answer .= $X ; + + cmp_ok $status, '==', Z_OK, "deflate returned Z_OK" ; + + cmp_ok $x->flush($X), '==', Z_OK, "flush returned Z_OK" ; + $Answer .= $X ; + + ok ! defined $x->msg() ; + is $x->total_in(), length $hello, "total_in ok" ; + is $x->total_out(), length $Answer, "total_out ok" ; + + my $k; + ok(($k, $err) = new Compress::Raw::Zlib::Inflate); + ok $k, "Compress::Raw::Zlib::Inflate ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + ok ! defined $k->msg(), "No error messages" ; + is $k->total_in(), 0, "total_in() == 0" ; + is $k->total_out(), 0, "total_out() == 0" ; + my $GOT = ''; + my $Z; + $Z = 1 ;#x 2000 ; + my $Alen = length $Answer; + $status = $k->inflate($Answer, $Z) ; + $GOT .= $Z ; + + cmp_ok $status, '==', Z_STREAM_END, "Got Z_STREAM_END" ; + is $GOT, $hello, "uncompressed data matches ok" ; + ok ! defined $k->msg(), "No error messages" ; + is $k->total_in(), $Alen, "total_in ok" ; + is $k->total_out(), length $hello , "total_out ok"; + + + ok(($k, $err) = new Compress::Raw::Zlib::Inflate); + ok $k, "Compress::Raw::Zlib::Inflate ok" ; + cmp_ok $err, '==', Z_OK, "status is Z_OK" ; + + $Z = ""; + $status = $k->inflate($hello, $Z); + is $Z, "", 'inflating *hello does not crash'; + + $hello = *hello; + $status = $k->inflateSync($hello); + cmp_ok $status, "!=", Z_OK, + "inflateSync on *hello returns error (and does not crash)"; +} +