You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Jim Jagielski <ji...@jaguNET.com> on 2002/07/06 23:00:38 UTC

[PATCH] Making the protocol check runtime

This is not the complete patch, but implements the logic of the
protocol check... This also avoids the use of '%n' for sscanf and
instead uses a nice little trick.

Comments? If this looks good, I'll add the remaining bits (like the
directive) and commit.

Index: src/main/http_protocol.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.322
diff -u -r1.322 http_protocol.c
--- src/main/http_protocol.c	26 Jun 2002 18:34:00 -0000	1.322
+++ src/main/http_protocol.c	6 Jul 2002 20:55:42 -0000
@@ -991,7 +991,9 @@
     const char *uri;
     conn_rec *conn = r->connection;
     unsigned int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
-    int len, n = 0;
+    int len = 0;
+    int valid_protocol = 1;
+    char *kruft;
 
     /* Read past empty lines until we get a real request line,
      * a read error, the connection closes (EOF), or we timeout.
@@ -1053,26 +1055,41 @@
     r->assbackwards = (ll[0] == '\0');
     r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9");
 
-    if (2 == sscanf(r->protocol, "HTTP/%u.%u%n", &major, &minor, &n)
-      && minor < HTTP_VERSION(1,0))	/* don't allow HTTP/0.1000 */
-	r->proto_num = HTTP_VERSION(major, minor);
+    /* Avoid sscanf in the common case */
+    if (strlen(r->protocol) == 8
+        && r->protocol[0] == 'H' && r->protocol[1] == 'T'
+	&& r->protocol[2] == 'T' && r->protocol[3] == 'P'
+        && r->protocol[4] == '/' && ap_isdigit(r->protocol[5])
+	&& r->protocol[6] == '.' && ap_isdigit(r->protocol[7])) {
+        r->proto_num = HTTP_VERSION(r->protocol[5] - '0', r->protocol[7] - '0');
+    }
     else {
-	r->proto_num = HTTP_VERSION(1,0);
-	n = 0;
+	kruft = ap_palloc(r->pool, strlen(r->protocol)+1);
+	if (2 == sscanf(r->protocol, "HTTP/%u.%u%s", &major, &minor, kruft)
+	    && minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */
+	    r->proto_num = HTTP_VERSION(major, minor);
+	else {
+	    r->proto_num = HTTP_VERSION(1,0);
+	    valid_protocol = 0;
+	}
     }
 
     /* Check for a valid protocol, and disallow everything but whitespace
-     * after the protocol string */
-    while (ap_isspace(r->protocol[n]))
-        ++n;
-    if (r->protocol[n] != '\0') {
-        r->status    = HTTP_BAD_REQUEST;
-        r->proto_num = HTTP_VERSION(1,0);
-        r->protocol  = ap_pstrdup(r->pool, "HTTP/1.0");
-        ap_table_setn(r->notes, "error-notes",
-                      "The request line contained invalid characters "
-                      "following the protocol string.<P>\n");
-        return 0;
+     * after the protocol string. A protocol string of nothing but
+     * whitespace is considered valid */
+    if (ap_protocol_req_check && !valid_protocol) {
+        int n = 0;
+	while (ap_isspace(r->protocol[n]))
+	    ++n;
+	if (r->protocol[n] != '\0') {
+	    r->status    = HTTP_BAD_REQUEST;
+	    r->proto_num = HTTP_VERSION(1,0);
+	    r->protocol  = ap_pstrdup(r->pool, "HTTP/1.0");
+	    ap_table_setn(r->notes, "error-notes",
+                     "The request line contained invalid characters "
+                     "following the protocol string.<P>\n");
+	    return 0;
+	}
     }
 
     return 1;
-- 
===========================================================================
   Jim Jagielski   [|]   jim@jaguNET.com   [|]   http://www.jaguNET.com/
      "A society that will trade a little liberty for a little order
             will lose both and deserve neither" - T.Jefferson