Subject: | Reading (possibly infinitiely) when CONTENT_LENGTH > $POST_MAX |
I just ran a test case that causes CGI.pm to go into a hard, infinite
loop when run in the command line.
In CGI::init:
METHOD: {
# avoid unreasonably large postings
if (($POST_MAX > 0) && ($content_length > $POST_MAX)) {
# quietly read and discard the post
my $buffer;
my $tmplength = $content_length;
while($tmplength > 0) {
my $maxbuffer = ($tmplength < 10000)?$tmplength:10000;
my $bytesread = $MOD_PERL ?
$self->r->read($buffer,$maxbuffer) : read(STDIN,$buffer,$maxbuffer);
$tmplength -= $bytesread;
}
$self->cgi_error("413 Request entity too large");
last METHOD;
...
}
The problem occurs when read() no longer reads anything and returns 0
but $tmplength hasn't been zeroed out yet. Seems like there needs to be
an additional exit condition when $bytesread == 0 after the call to read().
In my environment I set CONTENT_LENGTH to a silly number (1000000000 [1
billion]). I figured that my $POST_MAX of 50*1024*1024 would have
stopped this request from being processed without even bothering to read
any bytes. But the behavior is to
# quietly read and discard the post
Why do this? Why not just immediately return the "413 Request entity
too large" without bothering to read. (Suggested patch attached.)
I did not reproduce this when running as a CGI, but I wonder what would
happen if someone posted a very large file and then interrupted its
transmission.
I'm running 3.15, but I downloaded 3.20 and this code hasn't changed
between the two.
Perl info:
This is perl, v5.8.8 built for MSWin32-x86-multi-thread
(with 25 registered patches, see perl -V for more detail)
Copyright 1987-2006, Larry Wall
Binary build 817 [257965] provided by ActiveState
http://www.ActiveState.com
Built Mar 20 2006 17:54:25
OS: Windows 2000 Professional, fully patched as of 2006.05.12.
Cheers,
Richard
Subject: | cgi.patch |
--- \perl\lib\CGI.pm Sun Jan 08 08:53:52 2006
+++ \temp\CGI.pm Fri May 12 15:56:46 2006
@@ -508,14 +508,7 @@ sub init {
# avoid unreasonably large postings
if (($POST_MAX > 0) && ($content_length > $POST_MAX)) {
- # quietly read and discard the post
- my $buffer;
- my $tmplength = $content_length;
- while($tmplength > 0) {
- my $maxbuffer = ($tmplength < 10000)?$tmplength:10000;
- my $bytesread = $MOD_PERL ? $self->r->read($buffer,$maxbuffer) : read(STDIN,$buffer,$maxbuffer);
- $tmplength -= $bytesread;
- }
+ # discard the post, unread
$self->cgi_error("413 Request entity too large");
last METHOD;
}