diff --git a/modules/reitit-core/java-src/reitit/Trie.java b/modules/reitit-core/java-src/reitit/Trie.java index b7af4c1f..dcfecd0e 100644 --- a/modules/reitit-core/java-src/reitit/Trie.java +++ b/modules/reitit-core/java-src/reitit/Trie.java @@ -38,8 +38,8 @@ public class Trie { return decode(new String(chars, begin, end - begin), hasPercent, hasPlus); } - public static class Match { - public IPersistentMap params; + public final static class Match { + public final IPersistentMap params; public final Object data; public Match(IPersistentMap params, Object data) { @@ -47,6 +47,10 @@ public class Trie { this.data = data; } + Match assoc(Object key, Object value) { + return new Match(params.assoc(key, value), data); + } + @Override public String toString() { Map m = new HashMap<>(); @@ -174,10 +178,7 @@ public class Trie { } } final Match m = child.match(stop, max, path); - if (m != null) { - m.params = m.params.assoc(key, decode(new String(path, i, stop - i), hasPercent, hasPlus)); - } - return m; + return m != null ? m.assoc(key, decode(new String(path, i, stop - i), hasPercent, hasPlus)) : null; } return null; } @@ -216,7 +217,7 @@ public class Trie { @Override public Match match(int i, int max, char[] path) { if (i <= max) { - return new Match(params.assoc(parameter, decode(path, i, max)), data); + return new Match(params, data).assoc(parameter, decode(path, i, max)); } return null; } diff --git a/test/cljc/reitit/ring_test.cljc b/test/cljc/reitit/ring_test.cljc index b23d41b7..a907fcc4 100644 --- a/test/cljc/reitit/ring_test.cljc +++ b/test/cljc/reitit/ring_test.cljc @@ -3,7 +3,8 @@ [clojure.set :as set] [reitit.middleware :as middleware] [reitit.ring :as ring] - [reitit.core :as r]) + [reitit.core :as r] + [reitit.trie :as trie]) #?(:clj (:import (clojure.lang ExceptionInfo)))) @@ -577,3 +578,19 @@ (fn [{:keys [::r/router]} _ _] (is router))) {} ::respond ::raise))) + +#?(:clj + (deftest invalid-path-parameters-parsing-concurrent-requests-277-test + (testing "in enough concurrent system, path-parameters can bleed" + (doseq [compiler [trie/java-trie-compiler trie/clojure-trie-compiler]] + (let [app (ring/ring-handler + (ring/router + ["/:id" (fn [request] + {:status 200 + :body (-> request :path-params :id)})]) + {::trie/trie-compiler compiler})] + (dotimes [_ 10] + (future + (dotimes [n 100000] + (let [body (:body (app {:request-method :get, :uri (str "/" n)}))] + (is (= body (str n))))))))))))