diff options
author | Yann Ylavic <ylavic@apache.org> | 2019-03-28 23:39:31 +0100 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2019-03-28 23:39:31 +0100 |
commit | 28064636a726d7ecd12b4cd834880a7db6c398a7 (patch) | |
tree | 256869c3b7b09b148912d078765fec996a4d34c3 | |
parent | mod_cache: follow up to r1856493: always terminate cache_strqtok() returns. (diff) | |
download | apache2-28064636a726d7ecd12b4cd834880a7db6c398a7.tar.xz apache2-28064636a726d7ecd12b4cd834880a7db6c398a7.zip |
mod_cache: follow up to r1856493: cache_strqtok() to reject quoted tokens.
Use a real state machine to track where quotes are allowed, and for
better clarity too...
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1856507 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | modules/cache/cache_util.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/modules/cache/cache_util.c b/modules/cache/cache_util.c index ae00c10c8f..d8018c74f2 100644 --- a/modules/cache/cache_util.c +++ b/modules/cache/cache_util.c @@ -932,7 +932,12 @@ apr_status_t cache_strqtok(char *str, char **token, char **arg, char **last) { #define CACHE_TOKEN_SEPS "\t ," apr_status_t rv = APR_SUCCESS; - int quoted = 0; + enum { + IN_TOKEN, + IN_BETWEEN, + IN_ARGUMENT, + IN_QUOTES + } state = IN_TOKEN; char *wpos; if (!str) { /* subsequent call */ @@ -964,32 +969,43 @@ apr_status_t cache_strqtok(char *str, char **token, char **arg, char **last) * quoted strings, escaped characters. */ for (wpos = str; *str; ++str) { - if (!quoted) { - if (*str == '"') { - quoted = 1; - continue; - } - if (arg && !*arg && *str == '=') { + switch (state) { + case IN_TOKEN: + if (*str == '=') { + state = IN_BETWEEN; *wpos++ = '\0'; *arg = wpos; continue; } + break; + + case IN_BETWEEN: + if (*str == '"') { + state = IN_QUOTES; + continue; + } + /* fall through */ + state = IN_ARGUMENT; + case IN_ARGUMENT: if (TEST_CHAR(*str, T_HTTP_TOKEN_STOP)) { - break; + goto end; } - } - else { + break; + + default: + AP_DEBUG_ASSERT(state == IN_QUOTES); if (*str == '"') { ++str; - break; + goto end; } if (*str == '\\' && *(str + 1)) { ++str; } + break; } *wpos++ = *str; } - +end: /* anything after should be trailing OWS or comma */ for (; *str; ++str) { if (*str == ',') { |