]> granicus.if.org Git - apache/commitdiff
Bring forward from 1.3:
authorTony Finch <fanf@apache.org>
Thu, 18 Jan 2001 22:36:58 +0000 (22:36 +0000)
committerTony Finch <fanf@apache.org>
Thu, 18 Jan 2001 22:36:58 +0000 (22:36 +0000)
I broke mod_rewrite by modifying strings in place when expanding them,
because variable lookups can cause subrequests which cause mod_rewrite
to do its stuff again including an expansion on the same string, which
is then syntactically invalid. So copy the lookup keys somewhere else
before using them in such a way that may cause recursion.

In addition to this, my parser could also be confused by complicated
nested rewrite map expansions like ${map1:${map2:key|dflt}|dflt} so
fix that too by keeping track of {} when looking for |.

PR:             7087

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87723 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/mappers/mod_rewrite.c
modules/mappers/mod_rewrite.h

diff --git a/CHANGES b/CHANGES
index 55e99d4855860f992addd6169c683d7329b39787..aa880bb1c5746fcf7cc11095516ace586fb7b7d2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,9 @@
 Changes with Apache 2.0b1
 
+  *) Fix the handling of variable expansion look-ahead in mod_rewrite,
+     i.e. syntax like %{LA-U:REMOTE_USER}, and also fix the parsing of
+     more complicated nested RewriteMap lookups. PR#7087 [Tony Finch]
+
   *) Fix the RFC number mentioned when complaining about a missing
      Host: header. PR#7079 [Alexey Toptygin <alexeyt@wam.umd.edu>]
 
index f1a014f69076cbc0cc701aae5d63c33a5e18282d..f7d17504ab07b5291664cf7e9247964a28f932d9 100644 (file)
@@ -2288,7 +2288,13 @@ static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
            if (endp == NULL) {
                goto skip;
            }
-           *endp = '\0';
+           /*
+            * These lookups may be recursive in a very convoluted
+            * fashion -- see the LA-U and LA-F variable expansion
+            * prefixes -- so we copy lookup keys to a separate buffer
+            * rather than adding zero bytes in order to use them in
+            * place.
+            */
            if (inp[0] == '$') {
                /* ${...} map lookup expansion */
                /*
@@ -2303,43 +2309,39 @@ static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
                 * looking at it is that the recursion is entirely
                 * driven by the syntax of the nested curly brackets.
                 */
-               char *key, *dflt, *result;
+               char *map, *key, *dflt, *result;
                char xkey[MAX_STRING_LEN];
                char xdflt[MAX_STRING_LEN];
-               char *empty = "";
-               key = strchr(inp, ':');
-               if (key == NULL) {
-                   *endp = '}';
+               key = find_char_in_brackets(inp, ':', '{', '}');
+               if (key == NULL)
                    goto skip;
-               }
-               *key++ = '\0';
-               dflt = strchr(key, '|');
+               map  = apr_pstrndup(r->pool, inp+2, key-inp-2);
+               dflt = find_char_in_brackets(inp, '|', '{', '}');
                if (dflt == NULL) {
-                   dflt = empty;
-               }
-               else {
-                   *dflt++ = '\0';
+                   key  = apr_pstrndup(r->pool, key+1, endp-key-1);
+                   dflt = "";
+               } else {
+                   key  = apr_pstrndup(r->pool, key+1, dflt-key-1);
+                   dflt = apr_pstrndup(r->pool, dflt+1, endp-dflt-1);
                }
                do_expand(r, key,  xkey,  sizeof(xkey),  briRR, briRC);
-               do_expand(r, dflt, xdflt, sizeof(xdflt), briRR, briRC);
-               result = lookup_map(r, inp+2, xkey);
-               if (result == NULL) {
-                   result = xdflt;
-               }
-               span = apr_cpystrn(outp, result, space) - outp;
-               key[-1] = ':';
-               if (dflt != empty) {
-                   dflt[-1] = '|';
+               result = lookup_map(r, map, xkey);
+               if (result) {
+                   span = apr_cpystrn(outp, result, space) - outp;
+               } else {
+                   do_expand(r, dflt, xdflt, sizeof(xdflt), briRR, briRC);
+                   span = apr_cpystrn(outp, xdflt, space) - outp;
                }
            }
            else if (inp[0] == '%') {
                /* %{...} variable lookup expansion */
-               span = apr_cpystrn(outp, lookup_variable(r, inp+2), space) - outp;
+               char *var;
+               var  = apr_pstrndup(r->pool, inp+2, endp-inp-2);
+               span = apr_cpystrn(outp, lookup_variable(r, var), space) - outp;
            }
            else {
                span = 0;
            }
-           *endp = '}';
            inp = endp+1;
            outp += span;
            space -= span;
@@ -4073,7 +4075,7 @@ static int compare_lexicography(char *cpNum1, char *cpNum2)
 
 /*
 **
-**  Find end of bracketed expression
+**  Bracketed expression handling
 **  s points after the opening bracket
 **
 */
@@ -4093,6 +4095,30 @@ static char *find_closing_bracket(char *s, int left, int right)
     return NULL;
 }
 
+static char *find_char_in_brackets(char *s, int c, int left, int right)
+{
+    int depth;
+
+    for (depth = 1; *s; ++s) {
+       if (*s == c && depth == 1) {
+           return s;
+       }
+       else if (*s == right && --depth == 0) {
+           return NULL;
+       }
+       else if (*s == left) {
+           ++depth;
+       }
+    }
+    return NULL;
+}
+
+/*
+**
+** Module paraphernalia
+**
+*/
+
 #ifdef NETWARE
 int main(int argc, char *argv[]) 
 {
index d70f32fdc9a2faffa5467b7542f48bc00a39be04..9ed59ce5f3125261673176698996ba74caa0e28b 100644 (file)
@@ -469,8 +469,9 @@ static int    subreq_ok(request_rec *r);
     /* Lexicographic Comparison */
 static int compare_lexicography(char *cpNum1, char *cpNum2);
 
-    /* Find end of bracketed expression */
+    /* Bracketed expression handling */
 static char *find_closing_bracket(char *s, int left, int right);
+static char *find_char_in_brackets(char *s, int c, int left, int right);
 
 #endif /* _MOD_REWRITE_H */