diff options
author | Yann Ylavic <ylavic@apache.org> | 2021-11-12 22:46:11 +0100 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2021-11-12 22:46:11 +0100 |
commit | beec41a39a7206a8ed95d6aac31631a2f10118cd (patch) | |
tree | 59791c12c8e6a00b81e787d91f4ae21928d9dcd2 /server | |
parent | apreq: Sync r1894977 from libapreq. (diff) | |
download | apache2-beec41a39a7206a8ed95d6aac31631a2f10118cd.tar.xz apache2-beec41a39a7206a8ed95d6aac31631a2f10118cd.zip |
apreq: Sync r1894982 from libapreq.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1894985 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server')
-rw-r--r-- | server/apreq_util.c | 205 |
1 files changed, 131 insertions, 74 deletions
diff --git a/server/apreq_util.c b/server/apreq_util.c index 7b0f3b1022..eba8b8b3f6 100644 --- a/server/apreq_util.c +++ b/server/apreq_util.c @@ -839,100 +839,157 @@ APREQ_DECLARE(apr_status_t) apreq_file_mktemp(apr_file_t **fp, } -/* - * 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; + do { + const char *hde, *v; + apr_size_t tail = 0; - while (apr_isspace(*key) && key > hdr + nlen) - --key; + /* 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; } |