about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorzedshaw <zedshaw@19e92222-5c0b-0410-8929-a290d50e31e9>2006-04-03 02:27:59 +0000
committerzedshaw <zedshaw@19e92222-5c0b-0410-8929-a290d50e31e9>2006-04-03 02:27:59 +0000
commit3c804d5e15f084cd5aec5f7184dbffc1d7350951 (patch)
tree1945fd315dd88f0c8773ac7a461f5965548a3104
parent6c8d479b380ef624b6ae7a4588d37c32ffc2579e (diff)
downloadunicorn-3c804d5e15f084cd5aec5f7184dbffc1d7350951.tar.gz
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@138 19e92222-5c0b-0410-8929-a290d50e31e9
-rw-r--r--ext/http11/http11.c51
-rw-r--r--ext/http11/http11_parser.c110
-rw-r--r--ext/http11/http11_parser.rl20
-rw-r--r--lib/mongrel.rb19
-rw-r--r--lib/mongrel/debug.rb8
-rw-r--r--test/test_http11.rb70
6 files changed, 201 insertions, 77 deletions
diff --git a/ext/http11/http11.c b/ext/http11/http11.c
index 99bca06..d89f0d4 100644
--- a/ext/http11/http11.c
+++ b/ext/http11/http11.c
@@ -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);
diff --git a/ext/http11/http11_parser.c b/ext/http11/http11_parser.c
index fcbfa31..d1ea06a 100644
--- a/ext/http11/http11_parser.c
+++ b/ext/http11/http11_parser.c
@@ -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;
 
diff --git a/ext/http11/http11_parser.rl b/ext/http11/http11_parser.rl
index 8ef4acb..af3a444 100644
--- a/ext/http11/http11_parser.rl
+++ b/ext/http11/http11_parser.rl
@@ -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);
 
diff --git a/lib/mongrel.rb b/lib/mongrel.rb
index 25b9062..2c84018 100644
--- a/lib/mongrel.rb
+++ b/lib/mongrel.rb
@@ -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
diff --git a/lib/mongrel/debug.rb b/lib/mongrel/debug.rb
index 94b906d..5beacff 100644
--- a/lib/mongrel/debug.rb
+++ b/lib/mongrel/debug.rb
@@ -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
diff --git a/test/test_http11.rb b/test/test_http11.rb
index 9c8975c..e100d2b 100644
--- a/test/test_http11.rb
+++ b/test/test_http11.rb
@@ -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