java-topology/defects/rabbitmq/patch/rmq-0001-classic-queue-pending-map.patch

61 lines
3.6 KiB
Diff

# UNDF: UNDF-2026-000000239
--- a/deps/rabbit/src/rabbit_classic_queue.erl
+++ b/deps/rabbit/src/rabbit_classic_queue.erl
@@ -9,7 +9,7 @@
%% TODO possible to use sets / maps instead of lists?
%% Check performance with QoS 1 and 1 million target queues.
--record(msg_status, {pending :: [pid()],
- confirmed = [] :: [pid()]}).
+-record(msg_status, {pending :: #{pid() => true}, %% CWE-407 fix: O(1) membership via map
+ confirmed = [] :: [pid()]}).
-define(STATE, ?MODULE).
-record(?STATE, {
@@ -406,8 +406,8 @@ handle_event(QName, {down, Pid, Info}, #?STATE{monitored = Monitored,
false ->
MsgSeqNos = maps:keys(
maps:filter(fun (_, #msg_status{pending = Pids}) ->
- lists:member(Pid, Pids)
+ maps:is_key(Pid, Pids) %% CWE-407 fix: O(1) map lookup
end, U0)),
{Unconfirmed, Settled, Rejected} = settle_seq_nos(MsgSeqNos, Pid, U0, down),
@@ -428,8 +428,8 @@ handle_event(QName, {down, Pid, Info}, #?STATE{monitored = Monitored,
true ->
MsgIds = maps:fold(
fun (SeqNo, Status, Acc) ->
- case lists:member(Pid, Status#msg_status.pending) of
+ case maps:is_key(Pid, Status#msg_status.pending) of %% CWE-407 fix: O(1) map lookup
true ->
[SeqNo | Acc];
false ->
@@ -591,7 +591,7 @@ qpids(Qs, Confirm, MsgNo) ->
#?STATE{unconfirmed = U0} ->
- Rec = [QPid],
+ Rec = #{QPid => true}, %% CWE-407 fix: initialise pending as map/set
U = case Confirm of
false ->
U0;
@@ -683,10 +683,10 @@ settle_seq_nos(MsgSeqNos, Pid, U0, Reason) ->
#{SeqNo := Status0} ->
case update_msg_status(Reason, Pid, Status0) of
- #msg_status{pending = [],
- confirmed = []} ->
+ #msg_status{pending = P, confirmed = []} when map_size(P) =:= 0 -> %% CWE-407 fix: empty-map guard
%% no pending left and nothing confirmed
%% then we reject it
{maps:remove(SeqNo, U), C0, [SeqNo | R0]};
- #msg_status{pending = [],
- confirmed = _} ->
+ #msg_status{pending = P2, confirmed = _} when map_size(P2) =:= 0 -> %% CWE-407 fix: empty-map guard
%% this can be confirmed as there are no pending
%% and confirmed isn't empty
{maps:remove(SeqNo, U), [SeqNo | C0], R0};
@@ -704,9 +704,9 @@ settle_seq_nos(MsgSeqNos, Pid, U0, Reason) ->
update_msg_status(confirm, Pid, #msg_status{pending = P,
confirmed = C} = S) ->
- Rem = lists:delete(Pid, P),
+ Rem = maps:remove(Pid, P), %% CWE-407 fix: O(log N) map remove vs O(P) list scan
S#msg_status{pending = Rem, confirmed = [Pid | C]};
update_msg_status(down, Pid, #msg_status{pending = P} = S) ->
- S#msg_status{pending = lists:delete(Pid, P)}.
+ S#msg_status{pending = maps:remove(Pid, P)}. %% CWE-407 fix: O(log N) map remove vs O(P) list scan