From 9282a06e55cb142666d6ed565c9031e728b7d537 Mon Sep 17 00:00:00 2001 From: Eric Covener Date: Sun, 5 Mar 2023 20:31:40 +0000 Subject: avoid delimiting the query with a backreference git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1908097 13f79535-47bb-0310-9956-ffa450edef68 --- modules/mappers/mod_rewrite.c | 46 +++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) (limited to 'modules') diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index a315b84b32..97c0413fdb 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -173,6 +173,7 @@ static const char* really_last_key = "rewrite_really_last"; #define RULEFLAG_END (1<<17) #define RULEFLAG_ESCAPENOPLUS (1<<18) #define RULEFLAG_QSLAST (1<<19) +#define RULEFLAG_QSNONE (1<<20) /* programattic only */ /* return code of the rewrite rule * the result may be escaped - or not @@ -799,11 +800,19 @@ static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme) * split out a QUERY_STRING part from * the current URI string */ -static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, - int qslast) +static void splitout_queryargs(request_rec *r, int flags) { char *q; int split, skip; + int qsappend = flags & RULEFLAG_QSAPPEND; + int qsdiscard = flags & RULEFLAG_QSDISCARD; + int qslast = flags & RULEFLAG_QSLAST; + + if (flags & RULEFLAG_QSNONE) { + rewritelog(r, 2, NULL, "discarding query string, no parse from substitution"); + r->args = NULL; + return; + } /* don't touch, unless it's a scheme for which a query string makes sense. * See RFC 1738 and RFC 2368. @@ -828,7 +837,7 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, olduri = apr_pstrdup(r->pool, r->filename); *q++ = '\0'; if (qsappend) { - if (*q) { + if (*q) { r->args = apr_pstrcat(r->pool, q, "&" , r->args, NULL); } } @@ -836,9 +845,9 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, r->args = apr_pstrdup(r->pool, q); } - if (r->args) { + if (r->args) { len = strlen(r->args); - + if (!len) { r->args = NULL; } @@ -2789,7 +2798,8 @@ static apr_status_t rewritelock_remove(void *data) * XXX: what an inclined parser. Seems we have to leave it so * for backwards compat. *sigh* */ -static char *parseargline(apr_pool_t *p, char *str, char **a1, char **a2, char **a3) +static char *parseargline(apr_pool_t *p, char *str, char **a1, + char **a2, char **a2_end, char **a3) { char quote; @@ -2840,8 +2850,10 @@ static char *parseargline(apr_pool_t *p, char *str, char **a1, char **a2, char * if (!*str) { *a3 = NULL; /* 3rd argument is optional */ + *a2_end = str; return NULL; } + *a2_end = str; *str++ = '\0'; while (apr_isspace(*str)) { @@ -3395,7 +3407,7 @@ static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf, rewrite_server_conf *sconf; rewritecond_entry *newcond; ap_regex_t *regexp; - char *a1 = NULL, *a2 = NULL, *a3 = NULL; + char *a1 = NULL, *a2 = NULL, *a2_end, *a3 = NULL; const char *err; sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module); @@ -3413,7 +3425,7 @@ static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf, * of the argument line. So we can use a1 .. a3 without * copying them again. */ - if ((err = parseargline(cmd->pool, str, &a1, &a2, &a3))) { + if ((err = parseargline(cmd->pool, str, &a1, &a2, &a2_end, &a3))) { return apr_psprintf(cmd->pool, "RewriteCond: %s " "(TestString=%s, CondPattern=%s, flags=%s)", err, a1, a2, a3); @@ -3822,7 +3834,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, rewrite_server_conf *sconf; rewriterule_entry *newrule; ap_regex_t *regexp; - char *a1 = NULL, *a2 = NULL, *a3 = NULL; + char *a1 = NULL, *a2 = NULL, *a2_end, *a3 = NULL; const char *err; sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module); @@ -3836,7 +3848,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, } /* parse the argument line ourself */ - if ((err = parseargline(cmd->pool, str, &a1, &a2, &a3))) { + if ((err = parseargline(cmd->pool, str, &a1, &a2, &a2_end, &a3))) { return apr_psprintf(cmd->pool, "RewriteRule: %s " "(pattern='%s', substitution='%s', flags='%s')", err, a1, a2, a3); @@ -3884,6 +3896,16 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, newrule->flags |= RULEFLAG_NOSUB; } + if (*(a2_end-1) == '?') { + /* a literal ? at the end of the unsubstituted rewrite rule */ + newrule->flags |= RULEFLAG_QSNONE; + } + else if (newrule->flags & RULEFLAG_QSDISCARD) { + if (NULL == ap_strchr(newrule->output, '?')) { + newrule->flags |= RULEFLAG_QSNONE; + } + } + /* now, if the server or per-dir config holds an * array of RewriteCond entries, we take it for us * and clear the array @@ -4292,9 +4314,7 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx) r->path_info = NULL; } - splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND, - p->flags & RULEFLAG_QSDISCARD, - p->flags & RULEFLAG_QSLAST); + splitout_queryargs(r, p->flags); /* Add the previously stripped per-directory location prefix, unless * (1) it's an absolute URL path and -- cgit v1.2.1