You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl-cvs@perl.apache.org by to...@apache.org on 2008/07/30 18:48:12 UTC

svn commit: r681118 - in /perl/modperl/trunk: Changes t/apache/read3.t t/apache/read4.t t/response/TestApache/read3.pm t/response/TestApache/read4.pm xs/Apache2/RequestIO/Apache2__RequestIO.h

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);