aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/include
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2015-02-16 11:32:53 +0100
committerAnders Svensson <[email protected]>2015-03-04 08:56:33 +0100
commita63a93e6f16368fb82d24b8efd8f8ff9aabf8013 (patch)
tree841a0c6b99971b5b7931dbc1e0a8d6bcb4da256f /lib/diameter/include
parentebe60da137dafe659d9577e1c6411bcc1ea431af (diff)
downloadotp-a63a93e6f16368fb82d24b8efd8f8ff9aabf8013.tar.gz
otp-a63a93e6f16368fb82d24b8efd8f8ff9aabf8013.tar.bz2
otp-a63a93e6f16368fb82d24b8efd8f8ff9aabf8013.zip
Fix handling of length errors on Grouped AVPs
The decode of a Grouped AVP ignored the case that extracting component AVPs with diameter_codec:collect_avps/1 returned a tuple, in the case of a truncated AVP header.
Diffstat (limited to 'lib/diameter/include')
-rw-r--r--lib/diameter/include/diameter_gen.hrl36
1 files changed, 28 insertions, 8 deletions
diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl
index 8916286275..8272904856 100644
--- a/lib/diameter/include/diameter_gen.hrl
+++ b/lib/diameter/include/diameter_gen.hrl
@@ -334,8 +334,9 @@ d(Name, Avp, Acc) ->
{[H | Avps], pack_avp(Name, A, T)}
catch
throw: {?TAG, {grouped, RC, ComponentAvps}} ->
- {Avps, {Rec, Failed}} = Acc,
- {[[Avp | ComponentAvps] | Avps], {Rec, [{RC, Avp} | Failed]}};
+ {Avps, {Rec, Errors}} = Acc,
+ A = trim(Avp),
+ {[[A | trim(ComponentAvps)] | Avps], {Rec, [{RC, A} | Errors]}};
error: Reason ->
d(undefined == Failed orelse is_failed(),
Reason,
@@ -355,6 +356,10 @@ d(Name, Avp, Acc) ->
trim(#diameter_avp{data = <<0:1, Bin/binary>>} = Avp) ->
Avp#diameter_avp{data = Bin};
+trim(Avps)
+ when is_list(Avps) ->
+ lists:map(fun trim/1, Avps);
+
trim(Avp) ->
Avp.
@@ -599,22 +604,37 @@ value(_, Avp) ->
%% # grouped_avp/3
%% ---------------------------------------------------------------------------
--spec grouped_avp(decode, avp_name(), binary())
+-spec grouped_avp(decode, avp_name(), bitstring())
-> {avp_record(), [avp()]};
(encode, avp_name(), avp_record() | avp_values())
-> binary()
| no_return().
+%% Length error induced by diameter_codec:collect_avps/1.
+grouped_avp(decode, _Name, <<0:1, _/binary>>) ->
+ throw({?TAG, {grouped, 5014, []}});
+
grouped_avp(decode, Name, Data) ->
- {Rec, Avps, Es} = decode_avps(Name, diameter_codec:collect_avps(Data)),
- [] == Es orelse throw({?TAG, {grouped, 5004, Avps}}), %% decode failure
- {Rec, Avps};
-%% Note that this is the only AVP type that doesn't just return the
-%% decoded record, also returning the list of component AVP's.
+ grouped_decode(Name, diameter_codec:collect_avps(Data));
grouped_avp(encode, Name, Data) ->
encode_avps(Name, Data).
+%% grouped_decode/2
+%%
+%% Note that Grouped is the only AVP type that doesn't just return a
+%% decoded value, also returning the list of component diameter_avp
+%% records.
+
+grouped_decode(_Name, {Error, Acc}) ->
+ {RC, Avp} = Error,
+ throw({?TAG, {grouped, RC, [Avp | Acc]}});
+
+grouped_decode(Name, ComponentAvps) ->
+ {Rec, Avps, Es} = decode_avps(Name, ComponentAvps),
+ [] == Es orelse throw({?TAG, {grouped, 5004, Avps}}), %% decode failure
+ {Rec, Avps}.
+
%% ---------------------------------------------------------------------------
%% # empty_group/1
%% ---------------------------------------------------------------------------