File fix-CVE-2021-22116.patch of Package rabbitmq-server.26419
From 626d5219115d087a2695c0eb243c7ddb7e154563 Mon Sep 17 00:00:00 2001
From: Michael Klishin <klishinm@vmware.com>
Date: Wed, 7 Apr 2021 13:42:20 +0300
Subject: [PATCH] Merge pull request #2953 from
rabbitmq/mk-amqp10-parser-infinite-loop
AMQP 1.0 binary parser: treat arrays with extra or missing input as fatal errors
(cherry picked from commit f37a31de55229e6c763215500e376fa16803390b)
---
.../src/amqp10_binary_parser.erl | 26 +++++---
.../test/binary_parser_SUITE.erl | 59 +++++++++++++++++++
2 files changed, 78 insertions(+), 7 deletions(-)
create mode 100644 deps/amqp10_common/test/binary_parser_SUITE.erl
diff --git a/deps/amqp10_common/src/amqp10_binary_parser.erl b/deps/amqp10_common/src/amqp10_binary_parser.erl
index b936f9f4ca8..376ac47aed5 100644
--- a/deps/amqp10_common/src/amqp10_binary_parser.erl
+++ b/deps/amqp10_common/src/amqp10_binary_parser.erl
@@ -31,15 +31,15 @@ parse_described(Bin) ->
{Value, Rest2} = parse(Rest1),
{{described, Descriptor, Value}, Rest2}.
-parse_primitive0(<<Type,Rest/binary>>) ->
+parse_primitive0(<<Type, Rest/binary>>) ->
parse_primitive(Type, Rest).
%% Constants
-parse_primitive(16#40, Rest) -> {null, Rest};
-parse_primitive(16#41, Rest) -> {true, Rest};
-parse_primitive(16#42, Rest) -> {false, Rest};
-parse_primitive(16#43, Rest) -> {{uint, 0}, Rest};
-parse_primitive(16#44, Rest) -> {{ulong, 0}, Rest};
+parse_primitive(16#40, R) -> {null, R};
+parse_primitive(16#41, R) -> {true, R};
+parse_primitive(16#42, R) -> {false, R};
+parse_primitive(16#43, R) -> {{uint, 0}, R};
+parse_primitive(16#44, R) -> {{ulong, 0}, R};
%% Fixed-widths. Most integral types have a compact encoding as a byte.
parse_primitive(16#50, <<V:8/unsigned, R/binary>>) -> {{ubyte, V}, R};
@@ -122,6 +122,14 @@ parse_compound1(Count, Bin, Acc) ->
{Value, Rest} = parse(Bin),
parse_compound1(Count - 1, Rest, [Value | Acc]).
+parse_array_primitive(16#40, <<_:8/unsigned, R/binary>>) -> {null, R};
+parse_array_primitive(16#41, <<_:8/unsigned, R/binary>>) -> {true, R};
+parse_array_primitive(16#42, <<_:8/unsigned, R/binary>>) -> {false, R};
+parse_array_primitive(16#43, <<_:8/unsigned, R/binary>>) -> {{uint, 0}, R};
+parse_array_primitive(16#44, <<_:8/unsigned, R/binary>>) -> {{ulong, 0}, R};
+parse_array_primitive(ElementType, Data) ->
+ parse_primitive(ElementType, Data).
+
%% array structure is {array, Ctor, [Data]}
%% e.g. {array, symbol, [<<"amqp:accepted:list">>]}
parse_array(UnitSize, Bin) ->
@@ -141,8 +149,12 @@ parse_array1(Count, <<Type, ArrayBin/binary>>) ->
parse_array2(0, Type, <<>>, Acc) ->
{array, parse_constructor(Type), lists:reverse(Acc)};
+parse_array2(0, Type, Bin, Acc) ->
+ exit({failed_to_parse_array_extra_input_remaining, Type, Bin, Acc});
+parse_array2(Count, Type, <<>>, Acc) when Count > 0 ->
+ exit({failed_to_parse_array_insufficient_input, Type, Count, Acc});
parse_array2(Count, Type, Bin, Acc) ->
- {Value, Rest} = parse_primitive(Type, Bin),
+ {Value, Rest} = parse_array_primitive(Type, Bin),
parse_array2(Count - 1, Type, Rest, [Value | Acc]).
parse_constructor(16#a3) -> symbol;
diff --git a/deps/amqp10_common/test/binary_parser_SUITE.erl b/deps/amqp10_common/test/binary_parser_SUITE.erl
new file mode 100644
index 00000000000..7c1b2322e38
--- /dev/null
+++ b/deps/amqp10_common/test/binary_parser_SUITE.erl
@@ -0,0 +1,59 @@
+-module(binary_parser_SUITE).
+
+-compile(export_all).
+
+-export([
+ ]).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+%%%===================================================================
+%%% Common Test callbacks
+%%%===================================================================
+
+all() ->
+ [
+ {group, tests}
+ ].
+
+
+all_tests() ->
+ [
+ array_with_extra_input
+ ].
+
+groups() ->
+ [
+ {tests, [], all_tests()}
+ ].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%%===================================================================
+%%% Test cases
+%%%===================================================================
+
+array_with_extra_input(_Config) ->
+ Bin = <<83,16,192,85,10,177,0,0,0,1,48,161,12,114,97,98,98,105,116, 109,113,45,98,111,120,112,255,255,0,0,96,0,50,112,0,0,19,136,163,5,101,110,45,85,83,224,14,2,65,5,102,105,45,70,73,5,101,110,45,85,83,64,64,193,24,2,163,20,68,69,70,69,78,83,73,67,83,46,84,69,83,84,46,83,85,73,84,69,65>>,
+ ?assertExit({failed_to_parse_array_extra_input_remaining,
+ %% element type, input, accumulated result
+ 65, <<105,45,70,73,5,101,110,45,85,83>>, [true,true]},
+ amqp10_binary_parser:parse_all(Bin)),
+ ok.