1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Several robustness improvements to protect mongrel against bad HTTP requests.

git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@138 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
zedshaw 2006-04-03 02:27:59 +00:00
parent 6c8d479b38
commit 3c804d5e15
6 changed files with 201 additions and 77 deletions

View file

@ -9,6 +9,7 @@
static VALUE mMongrel;
static VALUE cHttpParser;
static VALUE cURIClassifier;
static VALUE eHttpParserError;
static int id_handler_map;
static VALUE global_http_prefix;
@ -32,15 +33,36 @@ static VALUE global_mongrel_version;
static VALUE global_server_software;
static VALUE global_port_80;
#define DEF_GLOBAL(name, val) global_##name = rb_obj_freeze(rb_str_new2(val)); rb_global_variable(&global_##name);
/** Defines common length and error messages for input length validation. */
#define DEF_MAX_LENGTH(N,length) const size_t MAX_##N##_LENGTH = length; const char *MAX_##N##_LENGTH_ERR = "HTTP element " # N " is longer than the " # length " allowed length.";
/** Validates the max length of given input and throws an HttpParserError exception if over. */
#define VALIDATE_MAX_LENGTH(len, N) if(len > MAX_##N##_LENGTH) { rb_raise(eHttpParserError, MAX_##N##_LENGTH_ERR); }
/** Defines global strings in the init method. */
#define DEF_GLOBAL(N, val) global_##N = rb_obj_freeze(rb_str_new2(val)); rb_global_variable(&global_##N);
/* Defines the maximum allowed lengths for various input elements.*/
DEF_MAX_LENGTH(FIELD_NAME, 256);
DEF_MAX_LENGTH(FIELD_VALUE, 80 * 1024);
DEF_MAX_LENGTH(REQUEST_URI, 512);
DEF_MAX_LENGTH(QUERY_STRING, (1024 * 10));
DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
void http_field(void *data, const char *field, size_t flen, const char *value, size_t vlen)
{
char *ch, *end;
VALUE req = (VALUE)data;
VALUE v = rb_str_new(value, vlen);
VALUE f = rb_str_dup(global_http_prefix);
VALUE v = Qnil;
VALUE f = Qnil;
VALIDATE_MAX_LENGTH(flen, FIELD_NAME);
VALIDATE_MAX_LENGTH(vlen, FIELD_VALUE);
v = rb_str_new(value, vlen);
f = rb_str_dup(global_http_prefix);
f = rb_str_buf_cat(f, field, flen);
for(ch = RSTRING(f)->ptr, end = ch + RSTRING(f)->len; ch < end; ch++) {
@ -57,14 +79,20 @@ void http_field(void *data, const char *field, size_t flen, const char *value, s
void request_method(void *data, const char *at, size_t length)
{
VALUE req = (VALUE)data;
VALUE val = rb_str_new(at, length);
VALUE val = Qnil;
val = rb_str_new(at, length);
rb_hash_aset(req, global_request_method, val);
}
void request_uri(void *data, const char *at, size_t length)
{
VALUE req = (VALUE)data;
VALUE val = rb_str_new(at, length);
VALUE val = Qnil;
VALIDATE_MAX_LENGTH(length, REQUEST_URI);
val = rb_str_new(at, length);
rb_hash_aset(req, global_request_uri, val);
}
@ -72,7 +100,11 @@ void request_uri(void *data, const char *at, size_t length)
void query_string(void *data, const char *at, size_t length)
{
VALUE req = (VALUE)data;
VALUE val = rb_str_new(at, length);
VALUE val = Qnil;
VALIDATE_MAX_LENGTH(length, QUERY_STRING);
val = rb_str_new(at, length);
rb_hash_aset(req, global_query_string, val);
}
@ -136,6 +168,7 @@ VALUE HttpParser_alloc(VALUE klass)
hp->query_string = query_string;
hp->http_version = http_version;
hp->header_done = header_done;
http_parser_init(hp);
obj = Data_Wrap_Struct(klass, NULL, HttpParser_free, hp);
@ -214,8 +247,10 @@ VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data)
http->data = (void *)req_hash;
http_parser_execute(http, RSTRING(data)->ptr, RSTRING(data)->len);
VALIDATE_MAX_LENGTH(http_parser_nread(http), HEADER);
if(http_parser_has_error(http)) {
rb_raise(rb_eStandardError, "HTTP Parsing failure");
rb_raise(eHttpParserError, "Invalid HTTP format, parsing fails.");
} else {
return INT2FIX(http_parser_nread(http));
}
@ -479,6 +514,8 @@ void Init_http11()
DEF_GLOBAL(server_software, "SERVER_SOFTWARE");
DEF_GLOBAL(port_80, "80");
eHttpParserError = rb_define_class_under(mMongrel, "HttpParserError", rb_eIOError);
cHttpParser = rb_define_class_under(mMongrel, "HttpParser", rb_cObject);
rb_define_alloc_func(cHttpParser, HttpParser_alloc);
rb_define_method(cHttpParser, "initialize", HttpParser_init,0);

View file

@ -6,10 +6,10 @@
#include <ctype.h>
#include <string.h>
#define MARK(S,F) assert((F) - (S)->mark >= 0); (S)->mark = (F);
#define MARK(S,F) (S)->mark = (F);
/** machine **/
#line 101 "ext/http11/http11_parser.rl"
#line 107 "ext/http11/http11_parser.rl"
/** Data **/
@ -21,7 +21,7 @@ static int http_parser_first_final = 53;
static int http_parser_error = 1;
#line 105 "ext/http11/http11_parser.rl"
#line 111 "ext/http11/http11_parser.rl"
int http_parser_init(http_parser *parser) {
int cs = 0;
@ -30,7 +30,7 @@ int http_parser_init(http_parser *parser) {
{
cs = http_parser_start;
}
#line 109 "ext/http11/http11_parser.rl"
#line 115 "ext/http11/http11_parser.rl"
parser->cs = cs;
parser->body_start = NULL;
parser->content_len = 0;
@ -71,7 +71,7 @@ st1:
goto _out1;
tr13:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st2;
st2:
if ( ++p == pe )
@ -117,9 +117,10 @@ case 7:
goto tr33;
goto st1;
tr33:
#line 29 "ext/http11/http11_parser.rl"
#line 30 "ext/http11/http11_parser.rl"
{
if(parser->request_method != NULL)
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->request_method != NULL)
parser->request_method(parser->data, parser->mark, p - parser->mark);
}
goto st8;
@ -127,7 +128,7 @@ st8:
if ( ++p == pe )
goto _out8;
case 8:
#line 131 "ext/http11/http11_parser.c"
#line 132 "ext/http11/http11_parser.c"
switch( (*p) ) {
case 42: goto tr27;
case 43: goto tr28;
@ -145,26 +146,28 @@ case 8:
goto st1;
tr27:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st9;
st9:
if ( ++p == pe )
goto _out9;
case 9:
#line 155 "ext/http11/http11_parser.c"
#line 156 "ext/http11/http11_parser.c"
if ( (*p) == 32 )
goto tr34;
goto st1;
tr34:
#line 33 "ext/http11/http11_parser.rl"
#line 35 "ext/http11/http11_parser.rl"
{
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->request_uri != NULL)
parser->request_uri(parser->data, parser->mark, p - parser->mark);
}
goto st10;
tr46:
#line 37 "ext/http11/http11_parser.rl"
#line 40 "ext/http11/http11_parser.rl"
{
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->query_string != NULL)
parser->query_string(parser->data, parser->mark, p - parser->mark);
}
@ -173,19 +176,19 @@ st10:
if ( ++p == pe )
goto _out10;
case 10:
#line 177 "ext/http11/http11_parser.c"
#line 180 "ext/http11/http11_parser.c"
if ( (*p) == 72 )
goto tr11;
goto st1;
tr11:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st11;
st11:
if ( ++p == pe )
goto _out11;
case 11:
#line 189 "ext/http11/http11_parser.c"
#line 192 "ext/http11/http11_parser.c"
if ( (*p) == 84 )
goto st12;
goto st1;
@ -243,8 +246,9 @@ case 18:
goto st18;
goto st1;
tr37:
#line 42 "ext/http11/http11_parser.rl"
#line 46 "ext/http11/http11_parser.rl"
{
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->http_version != NULL)
parser->http_version(parser->data, parser->mark, p - parser->mark);
}
@ -252,6 +256,7 @@ tr37:
tr49:
#line 22 "ext/http11/http11_parser.rl"
{
assert(p - (parser->mark - 1) >= 0 && "buffer overflow");
if(parser->http_field != NULL) {
parser->http_field(parser->data,
parser->field_start, parser->field_len,
@ -263,7 +268,7 @@ st19:
if ( ++p == pe )
goto _out19;
case 19:
#line 267 "ext/http11/http11_parser.c"
#line 272 "ext/http11/http11_parser.c"
if ( (*p) == 10 )
goto st20;
goto st1;
@ -303,7 +308,7 @@ case 21:
goto tr40;
goto st1;
tr40:
#line 46 "ext/http11/http11_parser.rl"
#line 52 "ext/http11/http11_parser.rl"
{
parser->body_start = p+1;
if(parser->header_done != NULL)
@ -315,7 +320,7 @@ st53:
if ( ++p == pe )
goto _out53;
case 53:
#line 319 "ext/http11/http11_parser.c"
#line 324 "ext/http11/http11_parser.c"
goto st1;
tr36:
#line 16 "ext/http11/http11_parser.rl"
@ -325,7 +330,7 @@ st22:
if ( ++p == pe )
goto _out22;
case 22:
#line 329 "ext/http11/http11_parser.c"
#line 334 "ext/http11/http11_parser.c"
switch( (*p) ) {
case 33: goto st22;
case 58: goto tr32;
@ -360,7 +365,7 @@ st23:
if ( ++p == pe )
goto _out23;
case 23:
#line 364 "ext/http11/http11_parser.c"
#line 369 "ext/http11/http11_parser.c"
if ( (*p) == 13 )
goto tr49;
goto tr52;
@ -372,19 +377,19 @@ st24:
if ( ++p == pe )
goto _out24;
case 24:
#line 376 "ext/http11/http11_parser.c"
#line 381 "ext/http11/http11_parser.c"
if ( (*p) == 13 )
goto tr49;
goto st24;
tr28:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st25;
st25:
if ( ++p == pe )
goto _out25;
case 25:
#line 388 "ext/http11/http11_parser.c"
#line 393 "ext/http11/http11_parser.c"
switch( (*p) ) {
case 43: goto st25;
case 58: goto st26;
@ -403,13 +408,13 @@ case 25:
goto st1;
tr30:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st26;
st26:
if ( ++p == pe )
goto _out26;
case 26:
#line 413 "ext/http11/http11_parser.c"
#line 418 "ext/http11/http11_parser.c"
switch( (*p) ) {
case 32: goto tr34;
case 37: goto st27;
@ -451,20 +456,20 @@ case 28:
goto st1;
tr29:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st29;
st29:
if ( ++p == pe )
goto _out29;
case 29:
#line 461 "ext/http11/http11_parser.c"
#line 466 "ext/http11/http11_parser.c"
switch( (*p) ) {
case 32: goto tr34;
case 37: goto st31;
case 47: goto st1;
case 60: goto st1;
case 62: goto st1;
case 63: goto tr44;
case 63: goto tr43;
case 127: goto st1;
}
if ( (*p) > 31 ) {
@ -482,7 +487,7 @@ case 30:
case 37: goto st31;
case 60: goto st1;
case 62: goto st1;
case 63: goto tr44;
case 63: goto tr43;
case 127: goto st1;
}
if ( (*p) > 31 ) {
@ -517,9 +522,10 @@ case 32:
} else
goto st30;
goto st1;
tr44:
#line 33 "ext/http11/http11_parser.rl"
tr43:
#line 35 "ext/http11/http11_parser.rl"
{
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->request_uri != NULL)
parser->request_uri(parser->data, parser->mark, p - parser->mark);
}
@ -528,7 +534,7 @@ st33:
if ( ++p == pe )
goto _out33;
case 33:
#line 532 "ext/http11/http11_parser.c"
#line 538 "ext/http11/http11_parser.c"
switch( (*p) ) {
case 32: goto tr46;
case 37: goto tr51;
@ -544,13 +550,13 @@ case 33:
goto tr50;
tr50:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st34;
st34:
if ( ++p == pe )
goto _out34;
case 34:
#line 554 "ext/http11/http11_parser.c"
#line 560 "ext/http11/http11_parser.c"
switch( (*p) ) {
case 32: goto tr46;
case 37: goto st35;
@ -566,13 +572,13 @@ case 34:
goto st34;
tr51:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st35;
st35:
if ( ++p == pe )
goto _out35;
case 35:
#line 576 "ext/http11/http11_parser.c"
#line 582 "ext/http11/http11_parser.c"
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
goto st36;
@ -597,13 +603,13 @@ case 36:
goto st1;
tr14:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st37;
st37:
if ( ++p == pe )
goto _out37;
case 37:
#line 607 "ext/http11/http11_parser.c"
#line 613 "ext/http11/http11_parser.c"
if ( (*p) == 69 )
goto st38;
goto st1;
@ -616,13 +622,13 @@ case 38:
goto st1;
tr15:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st39;
st39:
if ( ++p == pe )
goto _out39;
case 39:
#line 626 "ext/http11/http11_parser.c"
#line 632 "ext/http11/http11_parser.c"
if ( (*p) == 69 )
goto st40;
goto st1;
@ -642,13 +648,13 @@ case 41:
goto st1;
tr16:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st42;
st42:
if ( ++p == pe )
goto _out42;
case 42:
#line 652 "ext/http11/http11_parser.c"
#line 658 "ext/http11/http11_parser.c"
if ( (*p) == 80 )
goto st43;
goto st1;
@ -689,13 +695,13 @@ case 47:
goto st1;
tr17:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st48;
st48:
if ( ++p == pe )
goto _out48;
case 48:
#line 699 "ext/http11/http11_parser.c"
#line 705 "ext/http11/http11_parser.c"
switch( (*p) ) {
case 79: goto st49;
case 85: goto st38;
@ -710,13 +716,13 @@ case 49:
goto st1;
tr18:
#line 14 "ext/http11/http11_parser.rl"
{ MARK(parser, p); }
{MARK(parser, p); }
goto st50;
st50:
if ( ++p == pe )
goto _out50;
case 50:
#line 720 "ext/http11/http11_parser.c"
#line 726 "ext/http11/http11_parser.c"
if ( (*p) == 82 )
goto st51;
goto st1;
@ -791,15 +797,15 @@ case 52:
_out: {}
}
#line 128 "ext/http11/http11_parser.rl"
#line 134 "ext/http11/http11_parser.rl"
parser->cs = cs;
parser->nread = p - buffer;
if(parser->body_start) {
/* final \r\n combo encountered so stop right here */
#line 802 "ext/http11/http11_parser.c"
#line 134 "ext/http11/http11_parser.rl"
#line 808 "ext/http11/http11_parser.c"
#line 140 "ext/http11/http11_parser.rl"
parser->nread++;
}
@ -811,8 +817,8 @@ int http_parser_finish(http_parser *parser)
int cs = parser->cs;
#line 815 "ext/http11/http11_parser.c"
#line 145 "ext/http11/http11_parser.rl"
#line 821 "ext/http11/http11_parser.c"
#line 151 "ext/http11/http11_parser.rl"
parser->cs = cs;

View file

@ -5,13 +5,13 @@
#include <ctype.h>
#include <string.h>
#define MARK(S,F) assert((F) - (S)->mark >= 0); (S)->mark = (F);
#define MARK(S,F) (S)->mark = (F);
/** machine **/
%%{
machine http_parser;
action mark { MARK(parser, fpc); }
action mark {MARK(parser, fpc); }
action start_field { parser->field_start = fpc; }
action write_field {
@ -20,6 +20,7 @@
action start_value { MARK(parser, fpc); }
action write_value {
assert(p - (parser->mark - 1) >= 0 && "buffer overflow");
if(parser->http_field != NULL) {
parser->http_field(parser->data,
parser->field_start, parser->field_len,
@ -27,22 +28,27 @@
}
}
action request_method {
if(parser->request_method != NULL)
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->request_method != NULL)
parser->request_method(parser->data, parser->mark, p - parser->mark);
}
action request_uri {
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->request_uri != NULL)
parser->request_uri(parser->data, parser->mark, p - parser->mark);
}
action query_string {
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->query_string != NULL)
parser->query_string(parser->data, parser->mark, p - parser->mark);
}
action http_version {
assert(p - parser->mark >= 0 && "buffer overflow");
if(parser->http_version != NULL)
parser->http_version(parser->data, parser->mark, p - parser->mark);
}
action done {
parser->body_start = p+1;
if(parser->header_done != NULL)
@ -61,7 +67,7 @@
extra = ("!" | "*" | "'" | "(" | ")" | ",");
reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">");
national = any - (alpha | digit | reserved | extra | safe | unsafe);
national = any -- (alpha | digit | reserved | extra | safe | unsafe);
unreserved = (alpha | digit | safe | extra | national);
escape = ("%" xdigit xdigit);
uchar = (unreserved | escape);
@ -69,7 +75,7 @@
tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
# elements
token = (ascii - (CTL | tspecials));
token = (ascii -- (CTL | tspecials));
# URI schemes and absolute paths
scheme = ( alpha | digit | "+" | "-" | "." )* ;
@ -89,11 +95,11 @@
HTTP_Version = ("HTTP/" http_number) >mark %http_version ;
Request_Line = (Method " " Request_URI " " HTTP_Version CRLF) ;
field_name = (token - ":")+ >start_field %write_field;
field_name = (token -- ":")+ >start_field %write_field;
field_value = any* >start_value %write_value;
message_header = field_name ":" field_value $0 CRLF >1;
message_header = field_name ":" field_value :> CRLF;
Request = Request_Line (message_header)* ( CRLF @done);

View file

@ -110,7 +110,11 @@ module Mongrel
ERROR_503_RESPONSE="HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
# The basic max request size we'll try to read.
CHUNK_SIZE=(16 * 1024)
CHUNK_SIZE=(4 * 1024)
# This is the maximum header that is allowed before a client is booted. The parser detects
# this, but we'd also like to do this as well.
MAX_HEADER=1024 * (80 + 32)
# Format to generate a correct RFC 1123 date. rdoc for Time is wrong, there is no httpdate function.
RFC_1123_DATE_FORMAT="%a, %d %B %Y %H:%M:%S GMT".freeze
@ -259,13 +263,12 @@ module Mongrel
attr_reader :header_sent
attr_reader :status_sent
def initialize(socket, filter = nil)
def initialize(socket)
@socket = socket
@body = StringIO.new
@status = 404
@header = HeaderOut.new(StringIO.new)
@header[Const::DATE] = HttpServer.httpdate(Time.now)
@filter = filter
@body_sent = false
@header_sent = false
@status_sent = false
@ -343,6 +346,8 @@ module Mongrel
end
# This is the main driver of Mongrel, while the Mognrel::HttpParser and Mongrel::URIClassifier
# make up the majority of how the server functions. It's a very simple class that just
# has a thread accepting connections and a simple HttpServer.process_client function
@ -432,14 +437,20 @@ module Mongrel
else
# gotta stream and read again until we can get the parser to be character safe
# TODO: make this more efficient since this means we're parsing a lot repeatedly
if data.length >= Const::MAX_HEADER
raise HttpParserError.new("HEADER is longer than allowed, aborting client early.")
end
parser.reset
data << client.readpartial(Const::CHUNK_SIZE)
end
end
rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL
# ignored
rescue HttpParserError
STDERR.puts "BAD CLIENT: #$!"
rescue => details
STDERR.puts "ERROR(#{details.class}): #{details}"
STDERR.puts "ERROR: #$!"
STDERR.puts details.backtrace.join("\n")
ensure
client.close

View file

@ -70,11 +70,9 @@ module ObjectTracker
# Strings can't be tracked easily and are so numerous that they drown out all else
# so we just ignore them in the counts.
ObjectSpace.each_object do |obj|
if not obj.kind_of? String
ospace << obj.object_id
counts[obj.class] ||= 0
counts[obj.class] += 1
end
ospace << obj.object_id
counts[obj.class] ||= 0
counts[obj.class] += 1
end
dead_objects = @active_objects - ospace

View file

@ -2,6 +2,7 @@ require 'test/unit'
require 'http11'
require 'mongrel'
require 'benchmark'
require 'digest/sha1'
include Mongrel
@ -38,6 +39,72 @@ class HttpParserTest < Test::Unit::TestCase
assert parser.error?, "Parser SHOULD have error"
end
# lame random garbage maker
def rand_data(min, max, readable=true)
count = min + ((rand(max)+1) *10).to_i
res = count.to_s + "/"
if readable
res << Digest::SHA1.hexdigest(rand(count * 1000).to_s) * (count / 40)
else
res << Digest::SHA1.digest(rand(count * 1000).to_s) * (count / 20)
end
return res
end
def test_horrible_queries
parser = HttpParser.new
# first verify that large random get requests fail
100.times do |c|
get = "GET /#{rand_data(1024, 1024+(c*1024))} HTTP/1.1\r\n"
assert_raises Mongrel::HttpParserError do
parser.execute({}, get)
parser.reset
end
end
# then that large header names are caught
100.times do |c|
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
assert_raises Mongrel::HttpParserError do
parser.execute({}, get)
parser.reset
end
end
# then that large mangled field values are caught
100.times do |c|
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
assert_raises Mongrel::HttpParserError do
parser.execute({}, get)
parser.reset
end
end
# then large headers are rejected too
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
get << "X-Test: test\r\n" * (80 * 1024)
assert_raises Mongrel::HttpParserError do
parser.execute({}, get)
parser.reset
end
# finally just that random garbage gets blocked all the time
10.times do |c|
get = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
assert_raises Mongrel::HttpParserError do
parser.execute({}, get)
parser.reset
end
end
end
def test_query_parse
res = HttpRequest.query_parse("zed=1&frank=2")
assert res["zed"], "didn't get the request right"
@ -51,7 +118,6 @@ class HttpParserTest < Test::Unit::TestCase
assert_equal 4,res["zed"].length, "wrong number for zed"
assert_equal "11",res["frank"], "wrong number for frank"
end
end