java-topology/defects/erlang/patch/erlang-0003-merge-path1-sets.patch

30 lines
1.2 KiB
Diff

# UNDF: UNDF-2026-000000065
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -598,14 +598,19 @@ merge_path(Path,IPath,Acc) ->
merge_path1(Path,IPath,Acc).
-merge_path1([P|Path],IPath,Acc) ->
- case lists:member(P,Acc) of
+%% CWE-407 fix: merge_path1 used a plain list (Acc) as a seen-set.
+%% lists:member/2 is O(|Acc|); called once per element of Path, total cost
+%% is O(|Path|²) when all paths are unique. On a system with N library
+%% directories (common in large OTP/Elixir/Erlang deployments), this
+%% runs at startup and every code:add_paths/1 call.
+%% Fix: carry a sets:set() alongside the accumulator list for O(1) membership.
+merge_path1([P|Path],IPath,Acc) ->
+ merge_path1([P|Path],IPath,Acc,sets:new()).
+
+merge_path1([P|Path],IPath,Acc,Seen) ->
+ case sets:is_element(P,Seen) of
true ->
- merge_path1(Path,IPath,Acc); % Already added
+ merge_path1(Path,IPath,Acc,Seen); % Already added
false ->
IPath1 = exclude(P,IPath),
- merge_path1(Path,IPath1,[P|Acc])
+ merge_path1(Path,IPath1,[P|Acc],sets:add_element(P,Seen))
end;
-merge_path1(_,IPath,Acc) ->
+merge_path1(_,IPath,Acc,_Seen) ->
lists:reverse(Acc) ++ IPath.