diff options
author | Raimo Niskanen <raimo@erlang.org> | 2021-08-18 11:45:46 +0200 |
---|---|---|
committer | Raimo Niskanen <raimo@erlang.org> | 2021-08-30 14:27:36 +0200 |
commit | acf515e4cb20808276e5698fb3c2d582f5ce90c8 (patch) | |
tree | c0e94aa958a85d740358ab46d58a03271c4fc26b /erts/preloaded/src | |
parent | 241dcfe89f37092dd6a6f48726c390703d00de7b (diff) | |
download | erlang-acf515e4cb20808276e5698fb3c2d582f5ce90c8.tar.gz |
Validate sockaddr tighter
Check that all fields in the sockaddr() value are part
of the address for the address family.
I have myself once too many used #{family =>inet, address => loopback}
and then gotten #{family => inet, addr => any} since the address
field is named 'addr' so 'address' is ignored and the default
for 'addr' is 'any' ({0,0,0,0}).
Diffstat (limited to 'erts/preloaded/src')
-rw-r--r-- | erts/preloaded/src/prim_socket.erl | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/erts/preloaded/src/prim_socket.erl b/erts/preloaded/src/prim_socket.erl index 5ad8cdffd3..272f6ae032 100644 --- a/erts/preloaded/src/prim_socket.erl +++ b/erts/preloaded/src/prim_socket.erl @@ -58,13 +58,15 @@ %% Defaults %% --define(ESOCK_SOCKADDR_IN4_DEFAULTS, - (#{port => 0, addr => any})). +-define(ESOCK_SOCKADDR_IN_DEFAULTS, + (#{family => inet, port => 0, addr => any})). -define(ESOCK_SOCKADDR_IN6_DEFAULTS, - (#{port => 0, addr => any, + (#{family => inet6, port => 0, addr => any, flowinfo => 0, scope_id => 0})). +-define(ESOCK_SOCKADDR_LOCAL_DEFAULTS, + (#{family => local, path => <<"">>})). -define(ESOCK_SOCKADDR_NATIVE_DEFAULTS, - (#{addr => <<>>})). + (#{family => 0, addr => <<>>})). %% =========================================================================== %% @@ -820,31 +822,50 @@ enc_protocol(Proto) -> enc_sockaddr(#{family := inet} = SockAddr) -> - maps:merge(?ESOCK_SOCKADDR_IN4_DEFAULTS, SockAddr); + merge_sockaddr(?ESOCK_SOCKADDR_IN_DEFAULTS, SockAddr); enc_sockaddr(#{family := inet6} = SockAddr) -> - maps:merge(?ESOCK_SOCKADDR_IN6_DEFAULTS, SockAddr); + merge_sockaddr(?ESOCK_SOCKADDR_IN6_DEFAULTS, SockAddr); enc_sockaddr(#{family := local, path := Path} = SockAddr) -> if is_list(Path), 0 =< length(Path), length(Path) =< 255 -> BinPath = enc_path(Path), enc_sockaddr(SockAddr#{path => BinPath}); is_binary(Path), 0 =< byte_size(Path), byte_size(Path) =< 255 -> - SockAddr; + merge_sockaddr(?ESOCK_SOCKADDR_LOCAL_DEFAULTS, SockAddr); true -> %% Neater than an if clause - erlang:error({invalid, {sockaddr, path, SockAddr}}) + throw({invalid, {sockaddr, path, SockAddr}}) end; enc_sockaddr(#{family := local} = SockAddr) -> %% Neater than a function clause - erlang:error({invalid, {sockaddr, path, SockAddr}}); + throw({invalid, {sockaddr, path, SockAddr}}); enc_sockaddr(#{family := Native} = SockAddr) when is_integer(Native) -> - maps:merge(?ESOCK_SOCKADDR_NATIVE_DEFAULTS, SockAddr); + merge_sockaddr(?ESOCK_SOCKADDR_NATIVE_DEFAULTS, SockAddr); enc_sockaddr(#{family := _} = SockAddr) -> SockAddr; +enc_sockaddr(#{} = SockAddr) -> + throw({invalid, {sockaddr, family, SockAddr}}); enc_sockaddr(SockAddr) -> %% Neater than a function clause - erlang:error({invalid, {sockaddr, map_or_family, SockAddr}}). + erlang:error({invalid, {sockaddr, SockAddr}}). +merge_sockaddr(Default, SockAddr) -> + case + maps:fold( + fun (Key, _, Acc) -> + if + is_map_key(Key, Default) -> + Acc; + true -> + [Key | Acc] + end + end, [], SockAddr) + of + [] -> + maps:merge(Default, SockAddr); + InvalidKeys -> + throw({invalid, {sockaddr, {keys,InvalidKeys}, SockAddr}}) + end. %% File names has to be encoded according to %% the native file encoding @@ -896,6 +917,7 @@ enc_msg(#{} = M) -> end, M); enc_msg(M) -> + %% Neater than a function clause erlang:error({invalid, {msg, M}}). enc_cmsgs(Cmsgs, Protocols) -> |