The problem can be reproduced by issuing a second call to imgsize with a
compressed (CWS) file. The "under persistent environment" part of this
bug can be explained by this fact. Attached is a patch to t/all.t which
demonstrates this problem. Note, I disabled caching because the problem
code is never executed for files when caching is set. To get around the
problem in my environment I created my own version of sub swfmxsize.
Here is my version:
# adapted from Image::Size::my_swfmxsize() to work in isolation and solve
# bug:
http://rt.cpan.org/Public/Bug/Display.html?id=20623
sub _my_swfmxsize
{
my ($image) = @_;
my $header = substr($$image, 0, 1058);
my $ver = Image::Size::_bin2int(unpack 'B8', substr($header, 3, 1));
my ($d, $status) = Compress::Zlib::inflateInit();
my $buffer = substr($header, 8, 1024); # cannot pass substr to
inflate!!!
($header, $status) = $d->inflate($buffer);
# we know this is a CWS, but zlib had a problem
if ($status != Z_OK && $status != Z_STREAM_END) {
return (undef, undef,
'Corrupt CWS, unable to decompress header: ' . $d->msg())
}
my $bs = unpack 'B133', substr($header, 0, 9);
my $bits = Image::Size::_bin2int(substr($bs, 0, 5));
my $x = int(Image::Size::_bin2int(substr($bs, 5+$bits, $bits))/20);
my $y = int(Image::Size::_bin2int(substr($bs, 5+$bits*3, $bits))/20);
return ($x, $y, 'CWS');
}
Note that this version does not pass the substr call directly to
d->inflate(). This line causes the error:
substr outside of string at blib/lib/Image/Size.pm (autosplit into
blib/lib/auto/Image/Size/swfmxsize.al) line 1135.
Toward the end of the substr perldoc page it states:
If the lvalue returned by substr is used after the EXPR is
changed in any way, the behaviour may not be as expected and is
subject to change. This caveat includes code such as
"print(substr($foo,$a,$b)=$bar)" or "(sub-
str($foo,$a,$b)=$bar)=$fud" (where $foo is changed via the sub-
string assignment, and then the substr is used again), or where
a substr() is aliased via a "foreach" loop or passed as a
parameter or a reference to it is taken and then the alias,
parameter, or deref'd reference either is used after the origi-
nal EXPR has been changed or is assigned to and then used a
second time.
So in this case since substr is being passed to a method it is being
used as an lvalue since arguments are passed into subroutines by
aliasing. Since the behavior is unexpected your Perl version/OS
combination may produce different results. I am using Perl " v5.8.5
built for i686-linux".
Also, to illustrate the sub string issue in a more controlled
environment try running:
perl -e'sub problem{}; problem(substr("asdf",5,6))'
On my system this dies (has a return code of 255) with the message
"substr outside of string at -e line 1." When I run this on a different
Perl (version 5.005_03 built for sun4-solaris) I get the same message
but only as a warning (Perl returns with a 0). Also the die or warning
only occurs when the offset is outside the bounds of the string. This
example executes cleanly:
perl -e'sub problem{}; problem(substr("asdf",4,5))'
And to demonstrate the point about the problem occurring only in the
context of a subroutine call, this also executes cleanly:
perl -e'substr("asdf",5,6)'
I hope this helps!