summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2021-11-12 22:46:11 +0100
committerYann Ylavic <ylavic@apache.org>2021-11-12 22:46:11 +0100
commitbeec41a39a7206a8ed95d6aac31631a2f10118cd (patch)
tree59791c12c8e6a00b81e787d91f4ae21928d9dcd2 /server
parentapreq: Sync r1894977 from libapreq. (diff)
downloadapache2-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.c205
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;
}