Skip to content

Commit d5186e6

Browse files
committed
Match exact symbol length when detecting AMQP 1.0 body sections
In server_mode, the parser recognised the symbolic message body descriptors (amqp:data:binary, amqp:amqp-sequence:list and amqp:amqp-value:*) by their textual prefix only, ignoring the encoded symbol length. A described value whose descriptor merely started with one of these names was therefore classified as the corresponding standard body section. (cherry picked from commit c9b4b10)
1 parent cb6d233 commit d5186e6

2 files changed

Lines changed: 50 additions & 6 deletions

File tree

deps/amqp10_common/src/amqp10_binary_parser.erl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -274,17 +274,17 @@ pm(<<?DESCRIBED, ?CODE_ULONG, ?DESCRIPTOR_CODE_AMQP_SEQUENCE:64, _Rest/binary>>,
274274
reached_body(B, ?DESCRIPTOR_CODE_AMQP_SEQUENCE);
275275
pm(<<?DESCRIBED, ?CODE_ULONG, ?DESCRIPTOR_CODE_AMQP_VALUE:64, _Rest/binary>>, true, B) ->
276276
reached_body(B, ?DESCRIPTOR_CODE_AMQP_VALUE);
277-
pm(<<?DESCRIBED, ?CODE_SYM_8, _S:8, "amqp:data:binary", _Rest/binary>>, true, B) ->
277+
pm(<<?DESCRIBED, ?CODE_SYM_8, 16:8, "amqp:data:binary", _Rest/binary>>, true, B) ->
278278
reached_body(B, ?DESCRIPTOR_CODE_DATA);
279-
pm(<<?DESCRIBED, ?CODE_SYM_8, _S:8, "amqp:amqp-sequence:list", _Rest/binary>>, true, B) ->
279+
pm(<<?DESCRIBED, ?CODE_SYM_8, 23:8, "amqp:amqp-sequence:list", _Rest/binary>>, true, B) ->
280280
reached_body(B, ?DESCRIPTOR_CODE_AMQP_SEQUENCE);
281-
pm(<<?DESCRIBED, ?CODE_SYM_8, _S:8, "amqp:amqp-value:*", _Rest/binary>>, true, B) ->
281+
pm(<<?DESCRIBED, ?CODE_SYM_8, 17:8, "amqp:amqp-value:*", _Rest/binary>>, true, B) ->
282282
reached_body(B, ?DESCRIPTOR_CODE_AMQP_VALUE);
283-
pm(<<?DESCRIBED, ?CODE_SYM_32, _S:32, "amqp:data:binary", _Rest/binary>>, true, B) ->
283+
pm(<<?DESCRIBED, ?CODE_SYM_32, 16:32, "amqp:data:binary", _Rest/binary>>, true, B) ->
284284
reached_body(B, ?DESCRIPTOR_CODE_DATA);
285-
pm(<<?DESCRIBED, ?CODE_SYM_32, _S:32, "amqp:amqp-sequence:list", _Rest/binary>>, true, B) ->
285+
pm(<<?DESCRIBED, ?CODE_SYM_32, 23:32, "amqp:amqp-sequence:list", _Rest/binary>>, true, B) ->
286286
reached_body(B, ?DESCRIPTOR_CODE_AMQP_SEQUENCE);
287-
pm(<<?DESCRIBED, ?CODE_SYM_32, _S:32, "amqp:amqp-value:*", _Rest/binary>>, true, B) ->
287+
pm(<<?DESCRIBED, ?CODE_SYM_32, 17:32, "amqp:amqp-value:*", _Rest/binary>>, true, B) ->
288288
reached_body(B, ?DESCRIPTOR_CODE_AMQP_VALUE);
289289
pm(<<?DESCRIBED, ?CODE_ULONG, ?DESCRIPTOR_CODE_PROPERTIES:64, Rest0/binary>>, O = true, B) ->
290290
[Value | Rest] = pm(Rest0, O, B+10),

deps/amqp10_common/test/binary_parser_SUITE.erl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ all_tests() ->
2525
array_of_zero_width_elements,
2626
array_of_described_zero_width_elements_unsupported,
2727
unsupported_type,
28+
server_mode_symbolic_body_descriptors,
29+
server_mode_body_descriptor_prefix_collision,
2830
peek_described_section_total_sizes,
2931
peek_described_section,
3032
peek_non_described_throws,
@@ -166,6 +168,48 @@ unsupported_type(_Config) ->
166168
Expected = {primitive_type_unsupported, UnsupportedType, {position, 0}},
167169
?assertThrow(Expected, amqp10_binary_parser:parse_many(Bin, [])).
168170

171+
%% A symbolic body descriptor of the exact registered length is classified as
172+
%% the corresponding standard body section in server_mode.
173+
server_mode_symbolic_body_descriptors(_Config) ->
174+
Data8 = <<0, 16#a3, 16, "amqp:data:binary", 16#a0, 1, "x">>,
175+
Seq8 = <<0, 16#a3, 23, "amqp:amqp-sequence:list", 16#45>>,
176+
Value8 = <<0, 16#a3, 17, "amqp:amqp-value:*", 16#a1, 1, "x">>,
177+
?assertEqual([{{pos, 0}, {body, 16#75}}],
178+
amqp10_binary_parser:parse_many(Data8, [server_mode])),
179+
?assertEqual([{{pos, 0}, {body, 16#76}}],
180+
amqp10_binary_parser:parse_many(Seq8, [server_mode])),
181+
?assertEqual([{{pos, 0}, {body, 16#77}}],
182+
amqp10_binary_parser:parse_many(Value8, [server_mode])),
183+
%% The sym32 forms must be classified identically.
184+
Data32 = <<0, 16#b3, 16:32, "amqp:data:binary", 16#a0, 1, "x">>,
185+
Seq32 = <<0, 16#b3, 23:32, "amqp:amqp-sequence:list", 16#45>>,
186+
Value32 = <<0, 16#b3, 17:32, "amqp:amqp-value:*", 16#a1, 1, "x">>,
187+
?assertEqual([{{pos, 0}, {body, 16#75}}],
188+
amqp10_binary_parser:parse_many(Data32, [server_mode])),
189+
?assertEqual([{{pos, 0}, {body, 16#76}}],
190+
amqp10_binary_parser:parse_many(Seq32, [server_mode])),
191+
?assertEqual([{{pos, 0}, {body, 16#77}}],
192+
amqp10_binary_parser:parse_many(Value32, [server_mode])).
193+
194+
server_mode_body_descriptor_prefix_collision(_Config) ->
195+
%% Well-formed but unknown descriptor "amqp:data:binary@" (length 17).
196+
Collision8 = <<0, 16#a3, 17, "amqp:data:binary", $@, 16#a0, 3, "abc">>,
197+
?assertEqual(
198+
[{described, {symbol, <<"amqp:data:binary@">>}, {binary, <<"abc">>}}],
199+
amqp10_binary_parser:parse_many(Collision8, [server_mode])),
200+
201+
%% The same collision via the sym32 constructor.
202+
Collision32 = <<0, 16#b3, 17:32, "amqp:data:binary", $@, 16#a0, 3, "abc">>,
203+
?assertEqual(
204+
[{described, {symbol, <<"amqp:data:binary@">>}, {binary, <<"abc">>}}],
205+
amqp10_binary_parser:parse_many(Collision32, [server_mode])),
206+
207+
%% A prefix collision on the amqp-value descriptor.
208+
ValueCollision = <<0, 16#a3, 18, "amqp:amqp-value:*!", 16#a1, 1, "x">>,
209+
?assertEqual(
210+
[{described, {symbol, <<"amqp:amqp-value:*!">>}, {utf8, <<"x">>}}],
211+
amqp10_binary_parser:parse_many(ValueCollision, [server_mode])).
212+
169213
%%%===================================================================
170214
%%% peek/1 (exercises peek_value_size internally via described types)
171215
%%%===================================================================

0 commit comments

Comments
 (0)