Skip to content

Commit 59f85bf

Browse files
Merge pull request #12327 from rabbitmq/modified-anns-fix
Fix modified annotations
2 parents c593d70 + 7ada1b8 commit 59f85bf

File tree

12 files changed

+65
-49
lines changed

12 files changed

+65
-49
lines changed

deps/amqp10_client/src/amqp10_client_session.erl

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,16 +1171,13 @@ make_link_ref(Role, Session, Handle) ->
11711171
#link_ref{role = Role, session = Session, link_handle = Handle}.
11721172

11731173
translate_message_annotations(MA)
1174-
when is_map(MA) andalso
1175-
map_size(MA) > 0 ->
1176-
Content = maps:fold(fun (K, V, Acc) ->
1177-
[{sym(K), wrap_map_value(V)} | Acc]
1178-
end, [], MA),
1179-
#'v1_0.message_annotations'{content = Content};
1174+
when map_size(MA) > 0 ->
1175+
{map, maps:fold(fun(K, V, Acc) ->
1176+
[{sym(K), wrap_map_value(V)} | Acc]
1177+
end, [], MA)};
11801178
translate_message_annotations(_MA) ->
11811179
undefined.
11821180

1183-
11841181
wrap_map_value(true) ->
11851182
{boolean, true};
11861183
wrap_map_value(false) ->

deps/amqp10_client/test/system_SUITE.erl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,8 @@ roundtrip(OpenConf, Body) ->
348348
Msg0 = amqp10_msg:new(<<"my-tag">>, Body, true),
349349
Msg1 = amqp10_msg:set_application_properties(#{"a_key" => "a_value"}, Msg0),
350350
Msg2 = amqp10_msg:set_properties(Props, Msg1),
351-
Msg = amqp10_msg:set_message_annotations(#{<<"x-key">> => "x-value",
352-
<<"x_key">> => "x_value"}, Msg2),
351+
Msg = amqp10_msg:set_message_annotations(#{<<"x-key 1">> => "value 1",
352+
<<"x-key 2">> => "value 2"}, Msg2),
353353
ok = amqp10_client:send_msg(Sender, Msg),
354354
ok = amqp10_client:detach_link(Sender),
355355
await_link(Sender, {detached, normal}, link_detach_timeout),
@@ -364,8 +364,8 @@ roundtrip(OpenConf, Body) ->
364364
% ct:pal(?LOW_IMPORTANCE, "roundtrip message Out: ~tp~nIn: ~tp~n", [OutMsg, Msg]),
365365
?assertMatch(Props, amqp10_msg:properties(OutMsg)),
366366
?assertEqual(#{<<"a_key">> => <<"a_value">>}, amqp10_msg:application_properties(OutMsg)),
367-
?assertMatch(#{<<"x-key">> := <<"x-value">>,
368-
<<"x_key">> := <<"x_value">>}, amqp10_msg:message_annotations(OutMsg)),
367+
?assertMatch(#{<<"x-key 1">> := <<"value 1">>,
368+
<<"x-key 2">> := <<"value 2">>}, amqp10_msg:message_annotations(OutMsg)),
369369
?assertEqual([Body], amqp10_msg:body(OutMsg)),
370370
ok.
371371

deps/amqp10_common/src/amqp10_framing.erl

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ decode({described, Descriptor, {map, Fields} = Type}) ->
122122
#'v1_0.application_properties'{} ->
123123
#'v1_0.application_properties'{content = decode_map(Fields)};
124124
#'v1_0.delivery_annotations'{} ->
125-
#'v1_0.delivery_annotations'{content = decode_map(Fields)};
125+
#'v1_0.delivery_annotations'{content = decode_annotations(Fields)};
126126
#'v1_0.message_annotations'{} ->
127-
#'v1_0.message_annotations'{content = decode_map(Fields)};
127+
#'v1_0.message_annotations'{content = decode_annotations(Fields)};
128128
#'v1_0.footer'{} ->
129-
#'v1_0.footer'{content = decode_map(Fields)};
129+
#'v1_0.footer'{content = decode_annotations(Fields)};
130130
#'v1_0.amqp_value'{} ->
131131
#'v1_0.amqp_value'{content = Type};
132132
Else ->
@@ -149,6 +149,16 @@ decode(Other) ->
149149
decode_map(Fields) ->
150150
[{decode(K), decode(V)} || {K, V} <- Fields].
151151

152+
%% "The annotations type is a map where the keys are restricted to be of type symbol
153+
%% or of type ulong. All ulong keys, and all symbolic keys except those beginning
154+
%% with "x-" are reserved." [3.2.10]
155+
%% Since we already parse annotations here and neither the client nor server uses
156+
%% reserved keys, we perform strict validation and crash if any reserved keys are used.
157+
decode_annotations(Fields) ->
158+
lists:map(fun({{symbol, <<"x-", _/binary>>} = K, V}) ->
159+
{K, decode(V)}
160+
end, Fields).
161+
152162
-spec encode_described(list | map | binary | annotations | '*',
153163
non_neg_integer(),
154164
amqp10_frame()) ->
@@ -216,7 +226,7 @@ pprint(Other) -> Other.
216226
-include_lib("eunit/include/eunit.hrl").
217227

218228
encode_decode_test_() ->
219-
Data = [{{utf8, <<"k">>}, {binary, <<"v">>}}],
229+
Data = [{{symbol, <<"x-my key">>}, {binary, <<"my value">>}}],
220230
Test = fun(M) -> [M] = decode_bin(iolist_to_binary(encode_bin(M))) end,
221231
[
222232
fun() -> Test(#'v1_0.application_properties'{content = Data}) end,

deps/amqp10_common/test/prop_SUITE.erl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,14 +412,21 @@ footer_section() ->
412412

413413
annotations() ->
414414
?LET(KvList,
415-
list({oneof([amqp_symbol(),
416-
amqp_ulong()]),
415+
list({non_reserved_annotation_key(),
417416
prefer_simple_type()}),
418417
begin
419418
KvList1 = lists:uniq(fun({K, _V}) -> K end, KvList),
420419
lists:filter(fun({_K, V}) -> V =/= null end, KvList1)
421420
end).
422421

422+
non_reserved_annotation_key() ->
423+
{symbol, ?LET(L,
424+
?SIZED(Size, resize(Size * 10, list(ascii_char()))),
425+
begin
426+
Bin = list_to_binary(L) ,
427+
<<"x-", Bin/binary>>
428+
end)}.
429+
423430
sequence_no() ->
424431
amqp_uint().
425432

deps/rabbit/src/rabbit_amqp_session.erl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,13 +1912,15 @@ settle_op_from_outcome(#'v1_0.modified'{delivery_failed = DelFailed,
19121912
undeliverable_here = UndelHere,
19131913
message_annotations = Anns0}) ->
19141914
Anns = case Anns0 of
1915-
#'v1_0.message_annotations'{content = C} ->
1916-
Anns1 = lists:map(fun({{symbol, K}, V}) ->
1917-
{K, unwrap(V)}
1918-
end, C),
1919-
maps:from_list(Anns1);
1920-
_ ->
1921-
#{}
1915+
undefined ->
1916+
#{};
1917+
{map, KVList} ->
1918+
Anns1 = lists:map(
1919+
%% "all symbolic keys except those beginning with "x-" are reserved." [3.2.10]
1920+
fun({{symbol, <<"x-", _/binary>> = K}, V}) ->
1921+
{K, unwrap(V)}
1922+
end, KVList),
1923+
maps:from_list(Anns1)
19221924
end,
19231925
{modify,
19241926
default(DelFailed, false),

deps/rabbit/test/amqp_client_SUITE.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ reliable_send_receive_with_outcomes(QType, Config) ->
355355
Outcomes = [
356356
accepted,
357357
modified,
358-
{modified, true, false, #{<<"fruit">> => <<"banana">>}},
358+
{modified, true, false, #{<<"x-fruit">> => <<"banana">>}},
359359
{modified, false, true, #{}},
360360
rejected,
361361
released
@@ -1124,7 +1124,7 @@ amqp_amqpl(QType, Config) ->
11241124
#{"my int" => -2},
11251125
amqp10_msg:new(<<>>, Body1, true)))),
11261126
%% Send with footer
1127-
Footer = #'v1_0.footer'{content = [{{symbol, <<"my footer">>}, {ubyte, 255}}]},
1127+
Footer = #'v1_0.footer'{content = [{{symbol, <<"x-my footer">>}, {ubyte, 255}}]},
11281128
ok = amqp10_client:send_msg(
11291129
Sender,
11301130
amqp10_msg:from_amqp_records(
@@ -5155,7 +5155,7 @@ footer_checksum(FooterOpt, Config) ->
51555155
priority => 7,
51565156
ttl => 100_000},
51575157
amqp10_msg:set_delivery_annotations(
5158-
#{"a" => "b"},
5158+
#{"x-a" => "b"},
51595159
amqp10_msg:set_message_annotations(
51605160
#{"x-string" => "string-value",
51615161
"x-int" => 3,

deps/rabbit/test/amqp_system_SUITE_data/fsharp-tests/Program.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,10 @@ module Test =
298298
use c = connectAnon uri
299299
let sender, receiver = senderReceiver c "test" "/queues/message_annotations"
300300
let ann = MessageAnnotations()
301-
let k1 = Symbol "key1"
302-
let k2 = Symbol "key2"
303-
ann.[Symbol "key1"] <- "value1"
304-
ann.[Symbol "key2"] <- "value2"
301+
let k1 = Symbol "x-key1"
302+
let k2 = Symbol "x-key2"
303+
ann.[Symbol "x-key1"] <- "value1"
304+
ann.[Symbol "x-key2"] <- "value2"
305305
let m = new Message("testing annotations", MessageAnnotations = ann)
306306
sender.Send m
307307
let m' = receive receiver

deps/rabbit/test/mc_unit_SUITE.erl

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,6 @@ amqp_amqpl(_Config) ->
524524
durable = true},
525525
MAC = [
526526
{{symbol, <<"x-stream-filter">>}, {utf8, <<"apple">>}},
527-
thead2(list, [utf8(<<"l">>)]),
528-
thead2(map, [{utf8(<<"k">>), utf8(<<"v">>)}]),
529527
thead2('x-list', list, [utf8(<<"l">>)]),
530528
thead2('x-map', map, [{utf8(<<"k">>), utf8(<<"v">>)}])
531529
],
@@ -591,9 +589,6 @@ amqp_amqpl(_Config) ->
591589
?assertMatch(#'P_basic'{expiration = <<"20000">>}, Props),
592590

593591
?assertMatch({_, longstr, <<"apple">>}, header(<<"x-stream-filter">>, HL)),
594-
%% these are not coverted as not x- headers
595-
?assertEqual(undefined, header(<<"list">>, HL)),
596-
?assertEqual(undefined, header(<<"map">>, HL)),
597592
?assertMatch({_ ,array, [{longstr,<<"l">>}]}, header(<<"x-list">>, HL)),
598593
?assertMatch({_, table, [{<<"k">>,longstr,<<"v">>}]}, header(<<"x-map">>, HL)),
599594

deps/rabbitmq_consistent_hash_exchange/test/rabbit_exchange_type_consistent_hash_SUITE.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,21 +244,21 @@ amqp_dead_letter(Config) ->
244244
Msg1 = case Seq rem 2 of
245245
0 ->
246246
amqp10_msg:set_message_annotations(
247-
#{<<"k1">> => Seq}, Msg0);
247+
#{<<"x-k1">> => Seq}, Msg0);
248248
1 ->
249249
Msg0
250250
end,
251251
Msg2 = case Seq rem 3 of
252252
0 ->
253253
amqp10_msg:set_application_properties(
254-
#{<<"k2">> => Seq}, Msg1);
254+
#{<<"x-k2">> => Seq}, Msg1);
255255
_ ->
256256
Msg1
257257
end,
258258
Msg = case Seq rem 4 of
259259
0 ->
260260
amqp10_msg:set_delivery_annotations(
261-
#{<<"k3">> => Seq}, Msg2);
261+
#{<<"x-k3">> => Seq}, Msg2);
262262
_ ->
263263
Msg2
264264
end,

deps/rabbitmq_mqtt/test/mc_mqtt_SUITE.erl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ amqp_to_mqtt_reply_to(_Config) ->
265265

266266
amqp_to_mqtt_footer(_Config) ->
267267
Body = <<"hey">>,
268-
Footer = #'v1_0.footer'{content = [{{symbol, <<"key">>}, {utf8, <<"value">>}}]},
268+
Footer = #'v1_0.footer'{content = [{{symbol, <<"x-key">>}, {utf8, <<"value">>}}]},
269269
%% We can translate, but lose the footer.
270270
#mqtt_msg{payload = Payload} = amqp_to_mqtt([#'v1_0.data'{content = Body}, Footer]),
271271
?assertEqual(<<"hey">>, iolist_to_binary(Payload)).
@@ -404,8 +404,6 @@ amqp_mqtt(_Config) ->
404404
durable = true},
405405
MAC = [
406406
{{symbol, <<"x-stream-filter">>}, {utf8, <<"apple">>}},
407-
thead2(list, [utf8(<<"l">>)]),
408-
thead2(map, [{utf8(<<"k">>), utf8(<<"v">>)}]),
409407
thead2('x-list', list, [utf8(<<"l">>)]),
410408
thead2('x-map', map, [{utf8(<<"k">>), utf8(<<"v">>)}])
411409
],

0 commit comments

Comments
 (0)