Author: torsten Date: Wed Jul 30 09:48:12 2008 New Revision: 681118 URL: http://svn.apache.org/viewvc?rev=681118&view=rev Log: a few enhancements to Apache2::RequestIO::read plus bugfix: read() used to clear the buffer at end of file. Now it return 0 but does not touch the buffer
Added: perl/modperl/trunk/t/apache/read3.t perl/modperl/trunk/t/apache/read4.t perl/modperl/trunk/t/response/TestApache/read3.pm perl/modperl/trunk/t/response/TestApache/read4.pm Modified: perl/modperl/trunk/Changes perl/modperl/trunk/xs/Apache2/RequestIO/Apache2__RequestIO.h Modified: perl/modperl/trunk/Changes URL: http://svn.apache.org/viewvc/perl/modperl/trunk/Changes?rev=681118&r1=681117&r2=681118&view=diff ============================================================================== --- perl/modperl/trunk/Changes (original) +++ perl/modperl/trunk/Changes Wed Jul 30 09:48:12 2008 @@ -12,6 +12,10 @@ =item 2.0.5-dev +Make sure Apache2::RequestIO::read doesn't clear the buffer on end of +file and handle negative offsets and offsets that are larger than +the current string length. [Torsten Foertsch] + Fix a problem that could make APR::XSLoader and Apache2::XSLoader load the wrong shared library. [Torsten Foertsch] Added: perl/modperl/trunk/t/apache/read3.t URL: http://svn.apache.org/viewvc/perl/modperl/trunk/t/apache/read3.t?rev=681118&view=auto ============================================================================== --- perl/modperl/trunk/t/apache/read3.t (added) +++ perl/modperl/trunk/t/apache/read3.t Wed Jul 30 09:48:12 2008 @@ -0,0 +1,4 @@ +# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*- +use Apache::TestRequest 'POST_BODY_ASSERT'; +print POST_BODY_ASSERT "/TestApache__read3", + content => "foobar"x2000; Added: perl/modperl/trunk/t/apache/read4.t URL: http://svn.apache.org/viewvc/perl/modperl/trunk/t/apache/read4.t?rev=681118&view=auto ============================================================================== --- perl/modperl/trunk/t/apache/read4.t (added) +++ perl/modperl/trunk/t/apache/read4.t Wed Jul 30 09:48:12 2008 @@ -0,0 +1,4 @@ +# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*- +use Apache::TestRequest 'POST_BODY_ASSERT'; +print POST_BODY_ASSERT "/TestApache__read4", + content => "foobar"x2; Added: perl/modperl/trunk/t/response/TestApache/read3.pm URL: http://svn.apache.org/viewvc/perl/modperl/trunk/t/response/TestApache/read3.pm?rev=681118&view=auto ============================================================================== --- perl/modperl/trunk/t/response/TestApache/read3.pm (added) +++ perl/modperl/trunk/t/response/TestApache/read3.pm Wed Jul 30 09:48:12 2008 @@ -0,0 +1,39 @@ +# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*- +package TestApache::read3; + +# extra tests in addition to TestApache::read + +use strict; +use warnings FATAL => 'all'; + +use Apache2::RequestRec (); +use Apache2::RequestIO (); +use APR::Table (); + +use Apache::Test; +use Apache::TestUtil; + +use Apache2::Const -compile => qw(OK); + +my $expected = "foobar"x2000; + +sub handler { + my $r = shift; + + plan $r, tests => 1; + + # test to read data up to end of file is signaled + my $data = ''; + my $where = 0; + my $len; + do { + $len = $r->read($data, 100, $where); + $where += $len; + } while ($len > 0); + + ok t_cmp($data, $expected, "reading up to end of file"); + + Apache2::Const::OK; +} +1; + Added: perl/modperl/trunk/t/response/TestApache/read4.pm URL: http://svn.apache.org/viewvc/perl/modperl/trunk/t/response/TestApache/read4.pm?rev=681118&view=auto ============================================================================== --- perl/modperl/trunk/t/response/TestApache/read4.pm (added) +++ perl/modperl/trunk/t/response/TestApache/read4.pm Wed Jul 30 09:48:12 2008 @@ -0,0 +1,113 @@ +# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*- +package TestApache::read4; + +# extra tests in addition to TestApache::read + +use strict; +use warnings FATAL => 'all'; + +use Apache2::RequestRec (); +use Apache2::RequestIO (); +use APR::Table (); + +use Apache::Test; +use Apache::TestUtil; + +use Apache2::Const -compile => qw(OK); + +my @expected = ("123foo", + "123456".("\0"x(1000-length("123456")))."bar", + "123f", + "23f\0\0o", + qr/Can't coerce readonly REF to string in/, + $^V, + "ARo", + qr/Modification of a read-only value attempted/, + ".........", + "\0\0ar", + "12", + ""); + +sub X::TIESCALAR {bless []=>'X'} +sub X::FETCH {$_[0]->[0]} +sub X::STORE {$_[0]->[0]=$_[1]} + +sub handler { + my $r = shift; + + plan $r, tests => 12; + my $test = 0; + + # we get the string "foobarfoobar" as input here + + # this test consumes 3 bytes + my $data = 12345; + $r->read($data, 3, -2); + ok t_cmp($data, $expected[$test++], "negative offset"); + + + # "barfoobar" still to be read + $data = 123456; + # now $data is a valid IV but has a PV buffer assigned. + # read() has to convert to a valid PV. + $r->read($data, 3, 1000); + ok t_cmp($data, $expected[$test++], "offset > length of string"); + + + # "foobar" still to be read + $r->read($data, 1, 3); + ok t_cmp($data, $expected[$test++], "shrink string"); + + + # "oobar" still to be read + substr($data, 0, 1) = ''; # set the OOK flag (PV starts at offset 1) + $r->read($data, 1, 5); + ok t_cmp($data, $expected[$test++], "PV with OOK flag set"); + + + # "obar" still to be read + # this test dies BEFORE reading anything + eval {$r->read($^V, 1)}; + ok t_cmp($@, $expected[$test++], "read-only \$^V"); + ok t_cmp($^V, $expected[$test++], "\$^V untouched"); + + + # "obar" still to be read + $data=[]; + eval {$r->read($data, 1, 2)}; + ok t_cmp($data, $expected[$test++], "passing an RV as data"); + + + # "bar" still to be read + # this test consumes the "b" although it should not + "........."=~/(.*)/; + eval {$r->read($1, 1)}; + my $x="$1"; # just in case + ok t_cmp($@, $expected[$test++], "read-only \$1"); + ok t_cmp($x, $expected[$test++], "\$1 untouched"); + + + # "ar" still to be read + # now eat up the rest of input + tie $data, 'X'; + $data=''; + $r->read($data, 100, 2); + ok t_cmp(tied($data)->[0], $expected[$test++], "read into a tied buffer"); + + untie $data; + + + # input is empty + $data=123456; + $r->read($data, 1000, 2); + ok t_cmp($data, $expected[$test++], "read at eof"); + + + # input is empty + $r->read($data, 1000); + ok t_cmp($data, $expected[$test++], "repeated read at eof"); + + Apache2::Const::OK; +} +1; + Modified: perl/modperl/trunk/xs/Apache2/RequestIO/Apache2__RequestIO.h URL: http://svn.apache.org/viewvc/perl/modperl/trunk/xs/Apache2/RequestIO/Apache2__RequestIO.h?rev=681118&r1=681117&r2=681118&view=diff ============================================================================== --- perl/modperl/trunk/xs/Apache2/RequestIO/Apache2__RequestIO.h (original) +++ perl/modperl/trunk/xs/Apache2/RequestIO/Apache2__RequestIO.h Wed Jul 30 09:48:12 2008 @@ -235,28 +235,37 @@ apr_off_t offset) { SSize_t total; + STRLEN blen; if (!SvOK(buffer)) { sv_setpvn(buffer, "", 0); } + (void)SvPV_force(buffer, blen); /* make it a valid PV */ + if (len <= 0) { Perl_croak(aTHX_ "The LENGTH argument can't be negative"); } - /* XXX: need to handle negative offset */ - /* XXX: need to pad with \0 if offset > size of the buffer */ + /* handle negative offset */ + if (offset < 0) { + if (-offset > (int)blen) Perl_croak(aTHX_ "Offset outside string"); + offset += blen; + } mpxs_sv_grow(buffer, len+offset); - total = modperl_request_read(aTHX_ r, SvPVX(buffer)+offset, len); - if (total > 0) { - mpxs_sv_cur_set(buffer, offset+total); - } - else { - sv_setpvn(buffer, "", 0); + /* need to pad with \0 if offset > size of the buffer */ + if (offset > SvCUR(buffer)) { + Zero(SvEND(buffer), offset - SvCUR(buffer), char); } + total = modperl_request_read(aTHX_ r, SvPVX(buffer)+offset, len); + + /* modperl_request_read can return only >=0. So it's safe to do this. */ + /* if total==0 we need to set the buffer length in case it is larger */ + mpxs_sv_cur_set(buffer, offset+total); + /* must run any set magic */ SvSETMAGIC(buffer);