From a2119c09e95eeb871c2b30046f596d61257b108c Mon Sep 17 00:00:00 2001
From: Matthew Holt <mholt@users.noreply.github.com>
Date: Tue, 19 Oct 2021 12:25:36 -0600
Subject: map: Fix 95c03506 (avoid repeated expansions)

---
 modules/caddyhttp/map/map.go      | 28 +++++++++++-----------------
 modules/caddyhttp/map/map_test.go | 27 ++++++++++++++++++++++-----
 2 files changed, 33 insertions(+), 22 deletions(-)

(limited to 'modules/caddyhttp')

diff --git a/modules/caddyhttp/map/map.go b/modules/caddyhttp/map/map.go
index 670a55b..8394955 100644
--- a/modules/caddyhttp/map/map.go
+++ b/modules/caddyhttp/map/map.go
@@ -131,27 +131,21 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhtt
 		// find the first mapping matching the input and return
 		// the requested destination/output value
 		for _, m := range h.Mappings {
-			if m.re != nil {
-				if m.re.MatchString(input) {
-					if output := m.Outputs[destIdx]; output == nil {
-						continue
-					} else {
-						var result []byte
-						for _, submatches := range m.re.FindAllStringSubmatchIndex(input, -1) {
-							result = m.re.ExpandString(result, m.Outputs[destIdx].(string), input, submatches)
-						}
-						output = string(result)
-						return output, true
-					}
-				}
+			output := m.Outputs[destIdx]
+			if output == nil {
 				continue
 			}
-			if input == m.Input {
-				if output := m.Outputs[destIdx]; output == nil {
+			if m.re != nil {
+				var result []byte
+				matches := m.re.FindStringSubmatchIndex(input)
+				if matches == nil {
 					continue
-				} else {
-					return output, true
 				}
+				result = m.re.ExpandString(result, output.(string), input, matches)
+				return string(result), true
+			}
+			if input == m.Input {
+				return output, true
 			}
 		}
 
diff --git a/modules/caddyhttp/map/map_test.go b/modules/caddyhttp/map/map_test.go
index 59e5c5e..2789459 100644
--- a/modules/caddyhttp/map/map_test.go
+++ b/modules/caddyhttp/map/map_test.go
@@ -14,11 +14,11 @@ import (
 func TestHandler(t *testing.T) {
 	for i, tc := range []struct {
 		handler Handler
-		reqPath string
+		reqURI  string
 		expect  map[string]interface{}
 	}{
 		{
-			reqPath: "/foo",
+			reqURI: "/foo",
 			handler: Handler{
 				Source:       "{http.request.uri.path}",
 				Destinations: []string{"{output}"},
@@ -34,7 +34,7 @@ func TestHandler(t *testing.T) {
 			},
 		},
 		{
-			reqPath: "/abcdef",
+			reqURI: "/abcdef",
 			handler: Handler{
 				Source:       "{http.request.uri.path}",
 				Destinations: []string{"{output}"},
@@ -50,7 +50,7 @@ func TestHandler(t *testing.T) {
 			},
 		},
 		{
-			reqPath: "/ABCxyzDEF",
+			reqURI: "/ABCxyzDEF",
 			handler: Handler{
 				Source:       "{http.request.uri.path}",
 				Destinations: []string{"{output}"},
@@ -65,12 +65,29 @@ func TestHandler(t *testing.T) {
 				"output": "...xyz...",
 			},
 		},
+		{
+			// Test case from https://caddy.community/t/map-directive-and-regular-expressions/13866/14?u=matt
+			reqURI: "/?s=0%27+AND+%28SELECT+0+FROM+%28SELECT+count%28%2A%29%2C+CONCAT%28%28SELECT+%40%40version%29%2C+0x23%2C+FLOOR%28RAND%280%29%2A2%29%29+AS+x+FROM+information_schema.columns+GROUP+BY+x%29+y%29+-+-+%27",
+			handler: Handler{
+				Source:       "{http.request.uri}",
+				Destinations: []string{"{output}"},
+				Mappings: []Mapping{
+					{
+						InputRegexp: "(?i)(\\^|`|<|>|%|\\\\|\\{|\\}|\\|)",
+						Outputs:     []interface{}{"3"},
+					},
+				},
+			},
+			expect: map[string]interface{}{
+				"output": "3",
+			},
+		},
 	} {
 		if err := tc.handler.Provision(caddy.Context{}); err != nil {
 			t.Fatalf("Test %d: Provisioning handler: %v", i, err)
 		}
 
-		req, err := http.NewRequest(http.MethodGet, tc.reqPath, nil)
+		req, err := http.NewRequest(http.MethodGet, tc.reqURI, nil)
 		if err != nil {
 			t.Fatalf("Test %d: Creating request: %v", i, err)
 		}
-- 
cgit v1.2.3