]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge of /httpd/httpd/trunk:r1893724
authorStefan Eissing <icing@apache.org>
Fri, 1 Oct 2021 11:21:11 +0000 (11:21 +0000)
committerStefan Eissing <icing@apache.org>
Fri, 1 Oct 2021 11:21:11 +0000 (11:21 +0000)
  *) core: AP_NORMALIZE_DECODE_UNRESERVED should normalize the second dot in
     the uri-path when it's preceded by a dot.  [Yann Ylavic]

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1893775 13f79535-47bb-0310-9956-ffa450edef68

changes-entries/normalize_unreserved.txt [new file with mode: 0644]
server/util.c

diff --git a/changes-entries/normalize_unreserved.txt b/changes-entries/normalize_unreserved.txt
new file mode 100644 (file)
index 0000000..4782967
--- /dev/null
@@ -0,0 +1,2 @@
+  *) core: AP_NORMALIZE_DECODE_UNRESERVED should normalize the second dot in
+     the uri-path when it's preceded by a dot.  [Yann Ylavic]
\ No newline at end of file
index 2a7fdda8e9798587afb74b588bc6bdc1c5cd954b..896574b4c57faa2a345563de43eb861d926a8cf4 100644 (file)
@@ -502,7 +502,8 @@ static char x2c(const char *what);
 AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags)
 {
     int ret = 1;
-    apr_size_t l = 1, w = 1;
+    apr_size_t l = 1, w = 1, n;
+    int decode_unreserved = (flags & AP_NORMALIZE_DECODE_UNRESERVED) != 0;
 
     if (!IS_SLASH(path[0])) {
         /* Besides "OPTIONS *", a request-target should start with '/'
@@ -529,7 +530,7 @@ AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags)
          *  be decoded to their corresponding unreserved characters by
          *  URI normalizers.
          */
-        if ((flags & AP_NORMALIZE_DECODE_UNRESERVED)
+        if (decode_unreserved
                 && path[l] == '%' && apr_isxdigit(path[l + 1])
                                   && apr_isxdigit(path[l + 2])) {
             const char c = x2c(&path[l + 1]);
@@ -567,8 +568,17 @@ AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags)
                     continue;
                 }
 
-                /* Remove /xx/../ segments */
-                if (path[l + 1] == '.' && IS_SLASH_OR_NUL(path[l + 2])) {
+                /* Remove /xx/../ segments (or /xx/.%2e/ when
+                 * AP_NORMALIZE_DECODE_UNRESERVED is set since we
+                 * decoded only the first dot above).
+                 */
+                n = l + 1;
+                if ((path[n] == '.' || (decode_unreserved
+                                        && path[n] == '%'
+                                        && path[++n] == '2'
+                                        && (path[++n] == 'e'
+                                            || path[n] == 'E')))
+                        && IS_SLASH_OR_NUL(path[n + 1])) {
                     /* Wind w back to remove the previous segment */
                     if (w > 1) {
                         do {
@@ -585,7 +595,7 @@ AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags)
                     }
 
                     /* Move l forward to the next segment */
-                    l += 2;
+                    l = n + 1;
                     if (path[l]) {
                         l++;
                     }