46 lines
1.8 KiB
Diff
46 lines
1.8 KiB
Diff
From 2db25de Phoenix HEAD (2026-03-27)
|
|
Subject: [PATCH phoenix-0002] Fix CWE-407: use MapSet for router scope pipes accumulation
|
|
|
|
The Scope struct's `pipes` field is a plain list. `pipe_through/2` does
|
|
`Enum.find(new_pipes, &(&1 in pipes))` — O(n*m) — for duplicate detection,
|
|
then `pipes ++ new_pipes` — O(n) — for accumulation.
|
|
|
|
Change the `pipes` field default to `MapSet.new()`. Use `MapSet.member?/2`
|
|
for the duplicate check and `Enum.reduce/MapSet.put` for accumulation.
|
|
|
|
This is compile-time only so the practical impact is small, but the pattern
|
|
is wrong and MapSet is the correct data structure.
|
|
|
|
CWE-407: Algorithmic Complexity (Inefficient Algorithmic Complexity)
|
|
---
|
|
lib/phoenix/router/scope.ex | 8 +++++---
|
|
1 file changed, 5 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/lib/phoenix/router/scope.ex b/lib/phoenix/router/scope.ex
|
|
index xxxxxxx..yyyyyyy 100644
|
|
--- a/lib/phoenix/router/scope.ex
|
|
+++ b/lib/phoenix/router/scope.ex
|
|
@@ -9,7 +9,7 @@ defmodule Phoenix.Router.Scope do
|
|
defstruct path: [],
|
|
alias: [],
|
|
as: [],
|
|
- pipes: [],
|
|
+ pipes: MapSet.new(),
|
|
hosts: [],
|
|
private: %{},
|
|
assigns: %{},
|
|
@@ -121,10 +121,12 @@ defmodule Phoenix.Router.Scope do
|
|
def pipe_through(module, new_pipes) do
|
|
new_pipes = List.wrap(new_pipes)
|
|
%{pipes: pipes} = top = get_top(module)
|
|
|
|
- if pipe = Enum.find(new_pipes, &(&1 in pipes)) do
|
|
+ if pipe = Enum.find(new_pipes, &MapSet.member?(pipes, &1)) do
|
|
raise ArgumentError,
|
|
"duplicate pipe_through for #{inspect(pipe)}. " <>
|
|
"A plug may only be used once inside a scoped pipe_through"
|
|
end
|
|
|
|
- put_top(module, %{top | pipes: pipes ++ new_pipes})
|
|
+ put_top(module, %{top | pipes: Enum.reduce(new_pipes, pipes, &MapSet.put(&2, &1))})
|
|
end
|