Skip to content

Commit 97512b0

Browse files
authored
Merge pull request #12549 from rabbitmq/amqp-filtex-errors
Prevent crash for invalid application-properties filter
2 parents 17dd95a + c5b6e7f commit 97512b0

File tree

4 files changed

+85
-10
lines changed

4 files changed

+85
-10
lines changed

deps/rabbit/app.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,4 +2217,5 @@ def test_suite_beam_files(name = "test_suite_beam_files"):
22172217
outs = ["test/amqp_utils.beam"],
22182218
app_name = "rabbit",
22192219
erlc_opts = "//:test_erlc_opts",
2220+
deps = ["//deps/amqp10_common:erlang_app"],
22202221
)

deps/rabbit/src/rabbit_amqp_filtex.erl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,11 @@ validate0(Descriptor, KVList) when
112112
Descriptor =:= {ulong, ?DESCRIPTOR_CODE_PROPERTIES_FILTER}) andalso
113113
KVList =/= [] ->
114114
validate_props(KVList, []);
115-
validate0(Descriptor, KVList0) when
115+
validate0(Descriptor, KVList) when
116116
(Descriptor =:= {symbol, ?DESCRIPTOR_NAME_APPLICATION_PROPERTIES_FILTER} orelse
117117
Descriptor =:= {ulong, ?DESCRIPTOR_CODE_APPLICATION_PROPERTIES_FILTER}) andalso
118-
KVList0 =/= [] ->
119-
KVList = lists:map(fun({{utf8, Key}, {utf8, String}}) ->
120-
{Key, parse_string_modifier_prefix(String)};
121-
({{utf8, Key}, TaggedVal}) ->
122-
{Key, unwrap(TaggedVal)}
123-
end, KVList0),
124-
{ok, {application_properties, KVList}};
118+
KVList =/= [] ->
119+
validate_app_props(KVList, []);
125120
validate0(_, _) ->
126121
error.
127122

@@ -177,6 +172,15 @@ parse_message_id({utf8, Val}) ->
177172
parse_message_id(_) ->
178173
error.
179174

175+
validate_app_props([], Acc) ->
176+
{ok, {application_properties, lists:reverse(Acc)}};
177+
validate_app_props([{{utf8, Key}, {utf8, String}} | Rest], Acc) ->
178+
validate_app_props(Rest, [{Key, parse_string_modifier_prefix(String)} | Acc]);
179+
validate_app_props([{{utf8, Key}, TaggedVal} | Rest], Acc) ->
180+
validate_app_props(Rest, [{Key, unwrap(TaggedVal)} | Acc]);
181+
validate_app_props(_, _) ->
182+
error.
183+
180184
%% [filtex-v1.0-wd09 4.1.1]
181185
parse_string_modifier_prefix(<<"$s:", Suffix/binary>>) ->
182186
{suffix, size(Suffix), Suffix};

deps/rabbit/test/amqp_filtex_SUITE.erl

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
-include_lib("eunit/include/eunit.hrl").
1313
-include_lib("amqp10_common/include/amqp10_filtex.hrl").
14+
-include_lib("amqp10_common/include/amqp10_framing.hrl").
1415

1516
-compile([nowarn_export_all,
1617
export_all]).
@@ -21,6 +22,7 @@
2122
[eventually/1]).
2223
-import(amqp_utils,
2324
[init/1,
25+
connection_config/1,
2426
flush/1,
2527
wait_for_credit/1,
2628
wait_for_accepts/1,
@@ -85,7 +87,12 @@ end_per_testcase(Testcase, Config) ->
8587
properties_section(Config) ->
8688
Stream = atom_to_binary(?FUNCTION_NAME),
8789
Address = rabbitmq_amqp_address:queue(Stream),
88-
{Connection, Session, LinkPair} = init(Config),
90+
91+
OpnConf0 = connection_config(Config),
92+
OpnConf = OpnConf0#{notify_with_performative => true},
93+
{ok, Connection} = amqp10_client:open_connection(OpnConf),
94+
{ok, Session} = amqp10_client:begin_session_sync(Connection),
95+
{ok, LinkPair} = rabbitmq_amqp_client:attach_management_link_pair_sync(Session, <<"my link pair">>),
8996
{ok, #{}} = rabbitmq_amqp_client:declare_queue(
9097
LinkPair,
9198
Stream,
@@ -189,6 +196,14 @@ properties_section(Config) ->
189196
{ok, Receiver4} = amqp10_client:attach_receiver_link(
190197
Session, <<"receiver 4">>, Address,
191198
unsettled, configuration, Filter4),
199+
receive {amqp10_event,
200+
{link, Receiver4,
201+
{attached, #'v1_0.attach'{
202+
source = #'v1_0.source'{filter = {map, ActualFilter}}}}}} ->
203+
?assertMatch([{{symbol,<<"rabbitmq:stream-offset-spec">>}, _}],
204+
ActualFilter)
205+
after 5000 -> ct:fail({missing_event, ?LINE})
206+
end,
192207
{ok, R4M1} = amqp10_client:get_msg(Receiver4),
193208
{ok, R4M2} = amqp10_client:get_msg(Receiver4),
194209
{ok, R4M3} = amqp10_client:get_msg(Receiver4),
@@ -208,7 +223,11 @@ properties_section(Config) ->
208223
application_properties_section(Config) ->
209224
Stream = atom_to_binary(?FUNCTION_NAME),
210225
Address = rabbitmq_amqp_address:queue(Stream),
211-
{Connection, Session, LinkPair} = init(Config),
226+
OpnConf0 = connection_config(Config),
227+
OpnConf = OpnConf0#{notify_with_performative => true},
228+
{ok, Connection} = amqp10_client:open_connection(OpnConf),
229+
{ok, Session} = amqp10_client:begin_session_sync(Connection),
230+
{ok, LinkPair} = rabbitmq_amqp_client:attach_management_link_pair_sync(Session, <<"my link pair">>),
212231
{ok, #{}} = rabbitmq_amqp_client:declare_queue(
213232
LinkPair,
214233
Stream,
@@ -264,6 +283,20 @@ application_properties_section(Config) ->
264283
{ok, Receiver1} = amqp10_client:attach_receiver_link(
265284
Session, <<"receiver 1">>, Address,
266285
settled, configuration, Filter1),
286+
receive {amqp10_event,
287+
{link, Receiver1,
288+
{attached, #'v1_0.attach'{
289+
source = #'v1_0.source'{filter = {map, ActualFilter1}}}}}} ->
290+
?assertMatch(
291+
{described, _Type, {map, [
292+
{{utf8, <<"k1">>}, {int, -2}},
293+
{{utf8, <<"k5">>}, {symbol, <<"hey">>}},
294+
{{utf8, <<"k4">>}, true},
295+
{{utf8, <<"k3">>}, false}
296+
]}},
297+
proplists:get_value({symbol, ?DESCRIPTOR_NAME_APPLICATION_PROPERTIES_FILTER}, ActualFilter1))
298+
after 5000 -> ct:fail({missing_event, ?LINE})
299+
end,
267300
ok = amqp10_client:flow_link_credit(Receiver1, 10, never),
268301
receive {amqp10_msg, Receiver1, R1M1} ->
269302
?assertEqual([<<"m1">>], amqp10_msg:body(R1M1))
@@ -306,6 +339,38 @@ application_properties_section(Config) ->
306339
?assertEqual([<<"m4">>], amqp10_msg:body(R3M3)),
307340
ok = detach_link_sync(Receiver3),
308341

342+
%% Wrong type should fail validation in the server.
343+
%% RabbitMQ should exclude this filter in its reply attach frame because
344+
%% "the sending endpoint [RabbitMQ] sets the filter actually in place".
345+
%% Hence, no filter expression is actually in place and we should receive all messages.
346+
AppPropsFilter4 = [{{symbol, <<"k2">>}, {uint, 10}}],
347+
Filter4 = #{<<"rabbitmq:stream-offset-spec">> => <<"first">>,
348+
?DESCRIPTOR_NAME_APPLICATION_PROPERTIES_FILTER => {map, AppPropsFilter4}},
349+
{ok, Receiver4} = amqp10_client:attach_receiver_link(
350+
Session, <<"receiver 4">>, Address,
351+
unsettled, configuration, Filter4),
352+
receive {amqp10_event,
353+
{link, Receiver4,
354+
{attached, #'v1_0.attach'{
355+
source = #'v1_0.source'{filter = {map, ActualFilter4}}}}}} ->
356+
?assertMatch([{{symbol,<<"rabbitmq:stream-offset-spec">>}, _}],
357+
ActualFilter4)
358+
after 5000 -> ct:fail({missing_event, ?LINE})
359+
end,
360+
{ok, R4M1} = amqp10_client:get_msg(Receiver4),
361+
{ok, R4M2} = amqp10_client:get_msg(Receiver4),
362+
{ok, R4M3} = amqp10_client:get_msg(Receiver4),
363+
{ok, R4M4} = amqp10_client:get_msg(Receiver4),
364+
ok = amqp10_client:accept_msg(Receiver4, R4M1),
365+
ok = amqp10_client:accept_msg(Receiver4, R4M2),
366+
ok = amqp10_client:accept_msg(Receiver4, R4M3),
367+
ok = amqp10_client:accept_msg(Receiver4, R4M4),
368+
?assertEqual([<<"m1">>], amqp10_msg:body(R4M1)),
369+
?assertEqual([<<"m2">>], amqp10_msg:body(R4M2)),
370+
?assertEqual([<<"m3">>], amqp10_msg:body(R4M3)),
371+
?assertEqual([<<"m4">>], amqp10_msg:body(R4M4)),
372+
ok = detach_link_sync(Receiver4),
373+
309374
{ok, _} = rabbitmq_amqp_client:delete_queue(LinkPair, Stream),
310375
ok = rabbitmq_amqp_client:detach_management_link_pair_sync(LinkPair),
311376
ok = end_session_sync(Session),

deps/rabbit/test/amqp_utils.erl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
-module(amqp_utils).
99

10+
-include_lib("amqp10_common/include/amqp10_framing.hrl").
11+
1012
-export([init/1, init/2,
1113
connection_config/1, connection_config/2,
1214
flush/1,
@@ -101,6 +103,9 @@ detach_link_sync(Link) ->
101103
wait_for_link_detach(Link) ->
102104
receive
103105
{amqp10_event, {link, Link, {detached, normal}}} ->
106+
flush(?FUNCTION_NAME),
107+
ok;
108+
{amqp10_event, {link, Link, {detached, #'v1_0.detach'{}}}} ->
104109
flush(?FUNCTION_NAME),
105110
ok
106111
after 5000 ->

0 commit comments

Comments
 (0)