summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2019-03-28 23:39:31 +0100
committerYann Ylavic <ylavic@apache.org>2019-03-28 23:39:31 +0100
commit28064636a726d7ecd12b4cd834880a7db6c398a7 (patch)
tree256869c3b7b09b148912d078765fec996a4d34c3
parentmod_cache: follow up to r1856493: always terminate cache_strqtok() returns. (diff)
downloadapache2-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.c40
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 == ',') {