B
Brad Hilton
Hello,
In its current state, cgi.rb can lead to a cgi application spinning out
of control, eating up all cpu resources.
The read_multipart() function of cgi.rb assumes that the client will
post the expected data, as is manifest in the code:
until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
<snip>...
end
Unfortunately, when a browser interrupts a file upload (for example) the
above condition never becomes true, so the app just spins forever.
Using mozilla as a test case, and uploading a large enough file to the
following script, you can reproduce this by hitting the Reload button on
your browser before the file has uploaded completely.
I'm not sure if it is the perfect solution, but I found that by placing:
raise("Incomplete multipart post") if $stdin.eof?
just inside the above "until" test, the problem disappears. E.g.,
---------------
until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
raise("Incomplete multipart post") if $stdin.eof?
<rest of code>...
end
---------------
Regards,
Brad Hilton
-----------------------
Sample script: test.cgi
-----------------------
require 'cgi'
cgi = CGI.new
print "Content-type: text/html\n\n"
print <<EOF
<html>
<body>
Hit "Reload" before file has uploaded completely to expose problem...
<form method=post action="test.cgi" enctype="multipart/form-data">
<input type=file name=upload_file size=30>
<br>
<input type=submit value="go">
</form>
</body>
</html>
EOF
In its current state, cgi.rb can lead to a cgi application spinning out
of control, eating up all cpu resources.
The read_multipart() function of cgi.rb assumes that the client will
post the expected data, as is manifest in the code:
until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
<snip>...
end
Unfortunately, when a browser interrupts a file upload (for example) the
above condition never becomes true, so the app just spins forever.
Using mozilla as a test case, and uploading a large enough file to the
following script, you can reproduce this by hitting the Reload button on
your browser before the file has uploaded completely.
I'm not sure if it is the perfect solution, but I found that by placing:
raise("Incomplete multipart post") if $stdin.eof?
just inside the above "until" test, the problem disappears. E.g.,
---------------
until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
raise("Incomplete multipart post") if $stdin.eof?
<rest of code>...
end
---------------
Regards,
Brad Hilton
-----------------------
Sample script: test.cgi
-----------------------
require 'cgi'
cgi = CGI.new
print "Content-type: text/html\n\n"
print <<EOF
<html>
<body>
Hit "Reload" before file has uploaded completely to expose problem...
<form method=post action="test.cgi" enctype="multipart/form-data">
<input type=file name=upload_file size=30>
<br>
<input type=submit value="go">
</form>
</body>
</html>
EOF