Skip to content

Commit 24d0a69

Browse files
committed
Be prepared for broken UTF-8
1 parent 102a007 commit 24d0a69

2 files changed

Lines changed: 42 additions & 6 deletions

File tree

lib/kernel/src/inet_dns.erl

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,11 @@ decode_characters(Data, Encoding) ->
787787
?MATCH_ELSE_DECODE_ERROR(
788788
Data,
789789
<<Len,Bin:Len/binary,Rest/binary>>,
790-
{Rest,unicode:characters_to_list(Bin, Encoding)}).
790+
?MATCH_ELSE_DECODE_ERROR(
791+
unicode:characters_to_list(Bin, Encoding),
792+
String,
793+
is_list(String),
794+
{Rest,String})).
791795

792796
%% One domain name only, there must be nothing after
793797
%%
@@ -974,11 +978,15 @@ encode_data(Comp, Pos, ?S_NAPTR, Data) ->
974978
B0 = <<Order:16,Preference:16>>,
975979
B1 = encode_string(B0, iolist_to_binary(Flags)),
976980
B2 = encode_string(B1, iolist_to_binary(Services)),
977-
B3 = encode_string(B2, unicode:characters_to_binary(Regexp,
978-
unicode, utf8)),
979-
%% Bypass name compression (RFC 2915: section 2)
980-
{B,_} = encode_name(B3, gb_trees:empty(), Pos+byte_size(B3), Replacement),
981-
{B,Comp};
981+
case unicode:characters_to_binary(Regexp, unicode, utf8) of
982+
EncRegexp when is_binary(EncRegexp) ->
983+
B3 = encode_string(B2, EncRegexp),
984+
%% Bypass name compression (RFC 2915: section 2)
985+
{B,_} =
986+
encode_name(
987+
B3, gb_trees:empty(), Pos+byte_size(B3), Replacement),
988+
{B,Comp}
989+
end;
982990
encode_data(Comp, _, ?S_TXT, Data) -> {encode_txt(Data),Comp};
983991
encode_data(Comp, _, ?S_SPF, Data) -> {encode_txt(Data),Comp};
984992
encode_data(Comp, _, ?S_URI, Data) ->

lib/kernel/test/inet_res_SUITE.erl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2004,6 +2004,34 @@ bad_decode_2(Config) when is_list(Config) ->
20042004
id = ID, qr = QR, opcode = 'query', rd = 1 },
20052005
qdlist = [#dns_query{ domain = "", type = 'a', class = 'in'}] },
20062006
{error, formerr} = inet_dns:decode_reply(Buffer, Q, false),
2007+
2008+
%% NAPTR with broken UTF-8
2009+
2010+
%% Encode should fail
2011+
Replacement = "Replacement",
2012+
ReplBin = list_to_binary(Replacement),
2013+
RR1_NAPTR =
2014+
#dns_rr{
2015+
type = 'naptr',
2016+
data = {100,10,"Flags","Services",<<"Regex",255>>,Replacement}},
2017+
try inet_dns:encode(Q#dns_rec{ anlist = [RR1_NAPTR] }) of
2018+
Result -> error({should_not_encode, Result})
2019+
catch error : _ -> ok
2020+
end,
2021+
2022+
%% Decode should return proper error
2023+
RR_NAPTR =
2024+
#dns_rr{
2025+
type = 'naptr',
2026+
data = {100,10,"Flags","Services","Regexp",Replacement}},
2027+
Buffer_NAPTR = inet_dns:encode(Q#dns_rec{ anlist = [RR_NAPTR] }),
2028+
Tail_NAPTR = << (byte_size(ReplBin)), ReplBin/binary, 0 >>,
2029+
<< Start_NAPTR:(byte_size(Buffer_NAPTR)-byte_size(Tail_NAPTR)-1)/binary,
2030+
_,
2031+
Tail_NAPTR/binary >> = Buffer_NAPTR,
2032+
{error,formerr} =
2033+
inet_dns:decode(<< Start_NAPTR/binary, 255, Tail_NAPTR/binary >>),
2034+
20072035
ok.
20082036

20092037
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

0 commit comments

Comments
 (0)