]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] implement http_is_ver_token to fix response parsing
authorWilly Tarreau <w@1wt.eu>
Sun, 4 Mar 2007 17:13:58 +0000 (18:13 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 4 Mar 2007 17:13:58 +0000 (18:13 +0100)
This new character map improves accuracy when parsing HTTP version,
which helps inspecting requests, and fixes response handling.

include/proto/proto_http.h
src/proto_http.c

index 4863fe80c97f6017912e3d351d8e2b50abc5c3e1..324a5776fa5eb746915ff095c45c7202e37b0fd8 100644 (file)
@@ -36,6 +36,9 @@
  *   SPHT                = SP or HT. Use this macro and not a boolean expression for best speed.
  *   CRLF                = CR or LF. Use this macro and not a boolean expression for best speed.
  *   token               = any CHAR except CTL or SEP. Use this macro and not a boolean expression for best speed.
+ *
+ * added for ease of use:
+ *   ver_token           = 'H', 'P', 'T', '/', '.', and digits.
  */
 
 extern const char http_is_ctl[256];
@@ -44,6 +47,7 @@ extern const char http_is_lws[256];
 extern const char http_is_spht[256];
 extern const char http_is_crlf[256];
 extern const char http_is_token[256];
+extern const char http_is_ver_token[256];
 
 #define HTTP_IS_CTL(x)   (http_is_ctl[(unsigned char)(x)])
 #define HTTP_IS_SEP(x)   (http_is_sep[(unsigned char)(x)])
@@ -51,6 +55,7 @@ extern const char http_is_token[256];
 #define HTTP_IS_SPHT(x)  (http_is_spht[(unsigned char)(x)])
 #define HTTP_IS_CRLF(x)  (http_is_crlf[(unsigned char)(x)])
 #define HTTP_IS_TOKEN(x) (http_is_token[(unsigned char)(x)])
+#define HTTP_IS_VER_TOKEN(x) (http_is_ver_token[(unsigned char)(x)])
 
 int event_accept(int fd);
 int process_session(struct task *t);
index 289ece6c22d61ccfabd42cf400bf9b6c1bc85297..0eea5fdfb5ab07a4962c595a52e4f7e8e539bb4a 100644 (file)
@@ -294,6 +294,18 @@ const char http_is_token[256] = {
 };
 
 
+/*
+ * An http ver_token is any ASCII which can be found in an HTTP version,
+ * which includes 'H', 'T', 'P', '/', '.' and any digit.
+ */
+const char http_is_ver_token[256] = {
+       ['.'] = 1, ['/'] = 1,
+       ['0'] = 1, ['1'] = 1, ['2'] = 1, ['3'] = 1, ['4'] = 1,
+       ['5'] = 1, ['6'] = 1, ['7'] = 1, ['8'] = 1, ['9'] = 1,
+       ['H'] = 1, ['P'] = 1, ['T'] = 1,
+};
+
+
 #ifdef DEBUG_FULL
 static char *cli_stnames[5] = {"HDR", "DAT", "SHR", "SHW", "CLS" };
 static char *srv_stnames[7] = {"IDL", "CON", "HDR", "DAT", "SHR", "SHW", "CLS" };
@@ -540,7 +552,7 @@ const char *http_parse_rspline(struct http_msg *msg, const char *msg_buf, int st
        switch (state)  {
        http_msg_rpver:
        case HTTP_MSG_RPVER:
-               if (likely(HTTP_IS_TOKEN(*ptr)))
+               if (likely(HTTP_IS_VER_TOKEN(*ptr)))
                        EAT_AND_JUMP_OR_RETURN(http_msg_rpver, HTTP_MSG_RPVER);
 
                if (likely(HTTP_IS_SPHT(*ptr))) {
@@ -722,18 +734,24 @@ const char *http_parse_reqline(struct http_msg *msg, const char *msg_buf, int st
 
        http_msg_rqver:
        case HTTP_MSG_RQVER:
-               if (likely(!HTTP_IS_CRLF(*ptr)))
+               if (likely(HTTP_IS_VER_TOKEN(*ptr)))
                        EAT_AND_JUMP_OR_RETURN(http_msg_rqver, HTTP_MSG_RQVER);
-               msg->sl.rq.v_l = (ptr - msg_buf) - msg->sl.rq.v;
-       http_msg_rqline_eol:
-               /* We have seen the end of line. Note that we do not
-                * necessarily have the \n yet, but at least we know that we
-                * have EITHER \r OR \n, otherwise the request would not be
-                * complete. We can then record the request length and return
-                * to the caller which will be able to register it.
-                */
-               msg->sl.rq.l = ptr - msg->sol;
-               return ptr;
+
+               if (likely(HTTP_IS_CRLF(*ptr))) {
+                       msg->sl.rq.v_l = (ptr - msg_buf) - msg->sl.rq.v;
+               http_msg_rqline_eol:
+                       /* We have seen the end of line. Note that we do not
+                        * necessarily have the \n yet, but at least we know that we
+                        * have EITHER \r OR \n, otherwise the request would not be
+                        * complete. We can then record the request length and return
+                        * to the caller which will be able to register it.
+                        */
+                       msg->sl.rq.l = ptr - msg->sol;
+                       return ptr;
+               }
+
+               /* neither an HTTP_VER token nor a CRLF */
+               goto http_msg_invalid;
 
 #ifdef DEBUG_FULL
        default: