Skip to content

Commit 7a86828

Browse files
Validate sort keys against fixed set of allowed values
1 parent 9892338 commit 7a86828

2 files changed

Lines changed: 132 additions & 1 deletion

File tree

deps/rabbitmq_top/src/rabbit_top_util.erl

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,34 @@ toplist(Key, Info) ->
2525
sort_by_param(ReqData, Default) ->
2626
case rabbit_mgmt_util:qs_val(<<"sort">>, ReqData) of
2727
undefined -> Default;
28-
Bin -> rabbit_data_coercion:to_atom(Bin)
28+
Bin -> known_sort_key(Bin, Default)
2929
end.
3030

31+
%% Validate the sort key against known column names to prevent atom table
32+
%% exhaustion from arbitrary user-supplied sort parameters.
33+
known_sort_key(<<"reduction_delta">>, _) -> reduction_delta;
34+
known_sort_key(<<"memory">>, _) -> memory;
35+
known_sort_key(<<"message_queue_len">>, _) -> message_queue_len;
36+
known_sort_key(<<"reductions">>, _) -> reductions;
37+
known_sort_key(<<"status">>, _) -> status;
38+
known_sort_key(<<"buffer_len">>, _) -> buffer_len;
39+
known_sort_key(<<"pid">>, _) -> pid;
40+
%% ETS table sort keys
41+
known_sort_key(<<"size">>, _) -> size;
42+
known_sort_key(<<"name">>, _) -> name;
43+
known_sort_key(<<"owner">>, _) -> owner;
44+
known_sort_key(<<"owner_name">>, _) -> owner_name;
45+
known_sort_key(<<"type">>, _) -> type;
46+
known_sort_key(<<"protection">>, _) -> protection;
47+
known_sort_key(<<"node">>, _) -> node;
48+
known_sort_key(<<"keypos">>, _) -> keypos;
49+
known_sort_key(<<"compressed">>, _) -> compressed;
50+
known_sort_key(<<"named_table">>, _) -> named_table;
51+
known_sort_key(<<"write_concurrency">>, _) -> write_concurrency;
52+
known_sort_key(<<"read_concurrency">>, _) -> read_concurrency;
53+
known_sort_key(<<"decentralized_counters">>, _) -> decentralized_counters;
54+
known_sort_key(<<_/binary>>, Default) -> Default.
55+
3156
sort_order_param(ReqData) ->
3257
case rabbit_mgmt_util:qs_val(<<"sort_reverse">>, ReqData) of
3358
<<"true">> -> asc;
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2026 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
6+
%%
7+
8+
-module(rabbit_top_util_SUITE).
9+
10+
-compile(export_all).
11+
12+
-include_lib("common_test/include/ct.hrl").
13+
-include_lib("eunit/include/eunit.hrl").
14+
15+
all() ->
16+
[
17+
{group, unit_tests}
18+
].
19+
20+
groups() ->
21+
[
22+
{unit_tests, [parallel],
23+
[
24+
sort_by_param_known_process_keys,
25+
sort_by_param_known_ets_table_keys,
26+
sort_by_param_missing_uses_default,
27+
sort_by_param_unknown_uses_default,
28+
sort_by_param_unknown_does_not_create_atoms
29+
]}
30+
].
31+
32+
init_per_suite(Config) ->
33+
Config.
34+
35+
end_per_suite(_Config) ->
36+
ok.
37+
38+
init_per_group(_, Config) ->
39+
Config.
40+
41+
end_per_group(_, _Config) ->
42+
ok.
43+
44+
init_per_testcase(_Testcase, Config) ->
45+
Config.
46+
47+
end_per_testcase(_Testcase, _Config) ->
48+
ok.
49+
50+
%%
51+
%% Tests
52+
%%
53+
54+
sort_by_param_known_process_keys(_Config) ->
55+
KnownKeys = [
56+
{<<"reduction_delta">>, reduction_delta},
57+
{<<"memory">>, memory},
58+
{<<"message_queue_len">>, message_queue_len},
59+
{<<"reductions">>, reductions},
60+
{<<"status">>, status},
61+
{<<"buffer_len">>, buffer_len},
62+
{<<"pid">>, pid}
63+
],
64+
[?assertEqual(Atom, rabbit_top_util:sort_by_param(req(Bin), some_default))
65+
|| {Bin, Atom} <- KnownKeys].
66+
67+
sort_by_param_known_ets_table_keys(_Config) ->
68+
KnownKeys = [
69+
{<<"size">>, size},
70+
{<<"name">>, name},
71+
{<<"owner">>, owner},
72+
{<<"owner_name">>, owner_name},
73+
{<<"type">>, type},
74+
{<<"protection">>, protection},
75+
{<<"node">>, node},
76+
{<<"keypos">>, keypos},
77+
{<<"compressed">>, compressed},
78+
{<<"named_table">>, named_table},
79+
{<<"write_concurrency">>, write_concurrency},
80+
{<<"read_concurrency">>, read_concurrency},
81+
{<<"decentralized_counters">>, decentralized_counters}
82+
],
83+
[?assertEqual(Atom, rabbit_top_util:sort_by_param(req(Bin), some_default))
84+
|| {Bin, Atom} <- KnownKeys].
85+
86+
sort_by_param_missing_uses_default(_Config) ->
87+
?assertEqual(my_default, rabbit_top_util:sort_by_param(#{qs => <<>>}, my_default)).
88+
89+
sort_by_param_unknown_uses_default(_Config) ->
90+
?assertEqual(my_default, rabbit_top_util:sort_by_param(req(<<"unknown_column">>), my_default)).
91+
92+
sort_by_param_unknown_does_not_create_atoms(_Config) ->
93+
Key = <<"nonexistent_sort_key_for_rabbitmq_top_12345">>,
94+
%% Confirm the atom does not exist before the call.
95+
?assertError(badarg, binary_to_existing_atom(Key, utf8)),
96+
%% An unknown sort key must not create a new atom.
97+
_ = rabbit_top_util:sort_by_param(req(Key), reduction_delta),
98+
%% The atom must still not exist after the call.
99+
?assertError(badarg, binary_to_existing_atom(Key, utf8)).
100+
101+
%%
102+
%% Helpers
103+
%%
104+
105+
req(SortValue) ->
106+
#{qs => <<"sort=", SortValue/binary>>}.

0 commit comments

Comments
 (0)