You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by yl...@apache.org on 2021/11/12 21:46:12 UTC

svn commit: r1894985 - /httpd/httpd/trunk/server/apreq_util.c

Author: ylavic
Date: Fri Nov 12 21:46:11 2021
New Revision: 1894985

URL: http://svn.apache.org/viewvc?rev=1894985&view=rev
Log:
apreq: Sync r1894982 from libapreq.

Modified:
    httpd/httpd/trunk/server/apreq_util.c

Modified: httpd/httpd/trunk/server/apreq_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/apreq_util.c?rev=1894985&r1=1894984&r2=1894985&view=diff
==============================================================================
--- httpd/httpd/trunk/server/apreq_util.c (original)
+++ httpd/httpd/trunk/server/apreq_util.c Fri Nov 12 21:46:11 2021
@@ -839,100 +839,157 @@ APREQ_DECLARE(apr_status_t) apreq_file_m
 }
 
 
-/*
- * is_2616_token() is the verbatim definition from section 2.2
- * in the rfc itself.  We try to optimize it around the
- * expectation that the argument is not a token, which
- * should be the typical usage.
- */
-
-static APR_INLINE
-unsigned is_2616_token(const char c) {
-    switch (c) {
-    case ' ': case ';': case ',': case '"': case '\t':
-        /* The chars we are expecting are listed above;
-           the chars below are just for completeness. */
-    case '?': case '=': case '@': case ':': case '\\': case '/':
-    case '(': case ')':
-    case '<': case '>':
-    case '{': case '}':
-    case '[': case ']':
-        return 0;
-    default:
-        if (apr_iscntrl(c))
-            return 0;
-    }
-    return 1;
-}
+#define IS_SPACE_CHAR(c) ((c) == '\t' || (c) == ' ')
+#define IS_TOKEN_CHAR(c) (apr_isalnum(c) \
+                          || ((c) && strchr("!#$%&'*+-.^_`|~", (c))))
 
 APREQ_DECLARE(apr_status_t)
     apreq_header_attribute(const char *hdr,
                            const char *name, const apr_size_t nlen,
                            const char **val, apr_size_t *vlen)
 {
-    const char *key, *v;
-
-    /* Must ensure first char isn't '=', so we can safely backstep. */
-    while (*hdr == '=')
-        ++hdr;
+    int done = 0;
 
-    while ((key = strchr(hdr, '=')) != NULL) {
+    if (!nlen)
+        return APREQ_ERROR_NOATTR;
 
-        v = key + 1;
-        --key;
-
-        while (apr_isspace(*key) && key > hdr + nlen)
-            --key;
+    do {
+        const char *hde, *v;
+        apr_size_t tail = 0;
+
+        /* Parse the name => [hdr:hde[ */
+        hde = hdr;
+    look_for_end_name:
+        switch (*hde) {
+        case 0:
+        case '\r':
+        case '\n':
+            done = 1;
+        case '=':
+        case ';':
+        case ',':
+            v = hde + 1;
+            hde -= tail;
+            break;
+        case ' ':
+        case '\t':
+            if (hde == hdr)
+                ++hdr;
+            else
+                ++tail;
+            ++hde;
+            goto look_for_end_name;
+        default:
+            /* The name is a token */
+            if (!IS_TOKEN_CHAR(*hde))
+                return APREQ_ERROR_BADCHAR;
+            /* Nothing after the tail */
+            if (tail)
+                return APREQ_ERROR_BADATTR;
+            ++hde;
+            goto look_for_end_name;
+        }
 
-        key -= nlen - 1;
+        /* Parse the value => (*val, *vlen) */
+        if (v[-1] == '=') {
+            if (hde == hdr) {
+                /* The name can't be empty */
+                return APREQ_ERROR_BADATTR;
+            }
 
-        while (apr_isspace(*v))
-            ++v;
+            while (IS_SPACE_CHAR(*v))
+                ++v;
 
-        if (*v == '"') {
-            ++v;
-            *val = v;
+            /* Quoted string ? */
+            if (*v == '"') {
+                *val = ++v;
+
+                /* XXX: the interface does not permit unescaping,
+                 *      it should have pool to allocate from.
+                 * The caller can't know whether a returned '\\' is
+                 * a quoted-char or not..
+                 */
+            look_for_end_quote:
+                switch (*v) {
+                case 0:
+                case '\r':
+                case '\n':
+                    return APREQ_ERROR_BADSEQ;
+                case '"':
+                    *vlen = v - *val;
+                    break;
+                case '\\':
+                    if (v[1] != 0)
+                        ++v;
+                    ++v;
+                    goto look_for_end_quote;
+                default:
+                    if (apr_iscntrl(*v))
+                        return APREQ_ERROR_BADCHAR;
+                    ++v;
+                    goto look_for_end_quote;
+                }
 
-        look_for_end_quote:
-            switch (*v) {
-            case '"':
-                break;
-            case 0:
-                return APREQ_ERROR_BADSEQ;
-            case '\\':
-                if (v[1] != 0)
+            look_for_after_quote:
+                switch (*v) {
+                case 0:
+                case '\r':
+                case '\n':
+                    done = 1;
+                case ';':
+                case ',':
+                    break;
+                case ' ':
+                case '\t':
+                    goto look_for_after_quote;
+                default:
+                    if (apr_iscntrl(*v))
+                        return APREQ_ERROR_BADCHAR;
+                    return APREQ_ERROR_BADSEQ;
+                }
+            }
+            else {
+                *val = v;
+                tail = 0;
+
+            look_for_end_value:
+                switch (*v) {
+                case 0:
+                case '\r':
+                case '\n':
+                    done = 1;
+                case ';':
+                case ',':
+                    *vlen = v - *val - tail;
+                    break;
+                case ' ':
+                case '\t':
+                    if (*val == v)
+                        ++*val;
+                    else
+                        ++tail;
                     ++v;
-            default:
-                ++v;
-                goto look_for_end_quote;
+                    goto look_for_end_value;
+                default:
+                    if (apr_iscntrl(*v))
+                        return APREQ_ERROR_BADCHAR;
+                    ++v;
+                    tail = 0;
+                    goto look_for_end_value;
+                }
             }
         }
         else {
-            *val = v;
-
-        look_for_terminator:
-            switch (*v) {
-            case 0:
-            case ' ':
-            case ';':
-            case ',':
-            case '\t':
-            case '\r':
-            case '\n':
-                break;
-            default:
-                ++v;
-                goto look_for_terminator;
-            }
+            *val = NULL;
+            *vlen = 0;
         }
 
-        if (key >= hdr && strncasecmp(key, name, nlen) == 0) {
-            *vlen = v - *val;
-            if (key == hdr || ! is_2616_token(key[-1]))
-                return APR_SUCCESS;
+        if (hdr + nlen == hde && strncasecmp(hdr, name, nlen) == 0) {
+            return APR_SUCCESS;
         }
-        hdr = v;
-    }
+
+        hdr = v + 1;
+    } while (!done);
 
     return APREQ_ERROR_NOATTR;
 }