Repository: google/go-safeweb (go)

Issue:
All registered paths call the same handler
Buggy place: https://github.com/google/go-safeweb/blob/0c2edce93f20a51c77af2057b966ab5530e2114e/safehttp/mux.go#L75.

The closure passed to `mux.HandleFunc` captures local loop variables, making each instance of `handlersPerMethod` point to the same `map`. Oops.

Pull request description:
Fix Handler registering mixup.
Fixes #240.

Patch:
diff --git a/safehttp/mux.go b/safehttp/mux.go
index fb41b1b..5dd1ae6 100644
--- a/safehttp/mux.go
+++ b/safehttp/mux.go
@@ -72,6 +72,7 @@ type ServeMux struct {
 
 func registerHandlers(mux *http.ServeMux, handlers map[string]map[string]HandlerConfig) {
 	for pattern, handlersPerMethod := range handlers {
+		handlersPerMethod := handlersPerMethod
 		mux.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
 			cfg, ok := handlersPerMethod[r.Method]
 			if !ok {


Test patch:
diff --git a/safehttp/mux_test.go b/safehttp/mux_test.go
index 68dcd0c..d2571ed 100644
--- a/safehttp/mux_test.go
+++ b/safehttp/mux_test.go
@@ -145,6 +145,47 @@ func TestMuxServeTwoHandlers(t *testing.T) {
 	}
 }
 
+func TestMuxRegisterCorrectHandlerAllPaths(t *testing.T) {
+	var tests = []struct {
+		name     string
+		req      *http.Request
+		hf       safehttp.Handler
+		wantBody string
+	}{
+		{
+			name: "GET Handler",
+			req:  httptest.NewRequest(safehttp.MethodGet, "http://foo.com/get", nil),
+			hf: safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
+				return w.Write(safehtml.HTMLEscaped("GET handler for /get"))
+			}),
+			wantBody: "GET handler for /get",
+		},
+		{
+			name: "GET Handler #2",
+			req:  httptest.NewRequest(safehttp.MethodGet, "http://foo.com/get2", nil),
+			hf: safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
+				return w.Write(safehtml.HTMLEscaped("GET handler for /get2"))
+			}),
+			wantBody: "GET handler for /get2",
+		},
+	}
+
+	mb := &safehttp.ServeMuxConfig{}
+	mb.Handle("/get", safehttp.MethodGet, tests[0].hf)
+	mb.Handle("/get2", safehttp.MethodGet, tests[1].hf)
+	mux := mb.Mux()
+
+	for _, test := range tests {
+		b := &strings.Builder{}
+		rw := safehttptest.NewTestResponseWriter(b)
+		mux.ServeHTTP(rw, test.req)
+
+		if got, want := b.String(), test.wantBody; got != want {
+			t.Errorf("response body: got %q want %q", got, want)
+		}
+	}
+}
+
 func TestMuxHandleSameMethodTwice(t *testing.T) {
 	mb := &safehttp.ServeMuxConfig{}