Merge pull request #9286 from lafirest/fix/list_to_atom

fix: use list_to_existing_atom to replace some risky list_to_atom
This commit is contained in:
lafirest 2022-11-04 09:46:58 +08:00 committed by GitHub
commit 1580f02045
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 115 additions and 70 deletions

View File

@ -49,7 +49,8 @@
-export([ -export([
listener_id/2, listener_id/2,
parse_listener_id/1, parse_listener_id/1,
ensure_override_limiter_conf/2 ensure_override_limiter_conf/2,
esockd_access_rules/1
]). ]).
-export([pre_config_update/3, post_config_update/5]). -export([pre_config_update/3, post_config_update/5]).
@ -497,17 +498,28 @@ ip_port({Addr, Port}) ->
[{ip, Addr}, {port, Port}]. [{ip, Addr}, {port, Port}].
esockd_access_rules(StrRules) -> esockd_access_rules(StrRules) ->
Access = fun(S) -> Access = fun(S, Acc) ->
[A, CIDR] = string:tokens(S, " "), [A, CIDR] = string:tokens(S, " "),
%% esockd rules only use words 'allow' and 'deny', both are existing
%% comparison of strings may be better, but there is a loss of backward compatibility
case emqx_misc:safe_to_existing_atom(A) of
{ok, Action} ->
[
{ {
list_to_atom(A), Action,
case CIDR of case CIDR of
"all" -> all; "all" -> all;
_ -> CIDR _ -> CIDR
end end
} }
| Acc
];
_ ->
?SLOG(warning, #{msg => "invalid esockd access rule", rule => S}),
Acc
end
end, end,
[Access(R) || R <- StrRules]. lists:foldr(Access, [], StrRules).
merge_default(Options) -> merge_default(Options) ->
case lists:keytake(tcp_options, 1, Options) of case lists:keytake(tcp_options, 1, Options) of

View File

@ -469,9 +469,9 @@ safe_to_existing_atom(In) ->
safe_to_existing_atom(In, utf8). safe_to_existing_atom(In, utf8).
safe_to_existing_atom(Bin, Encoding) when is_binary(Bin) -> safe_to_existing_atom(Bin, Encoding) when is_binary(Bin) ->
try_to_existing_atom(fun erlang:binary_to_existing_atom/2, [Bin, Encoding]); try_to_existing_atom(fun erlang:binary_to_existing_atom/2, Bin, Encoding);
safe_to_existing_atom(List, _Encoding) when is_list(List) -> safe_to_existing_atom(List, Encoding) when is_list(List) ->
try_to_existing_atom(fun erlang:list_to_existing_atom/1, [List]); try_to_existing_atom(fun(In, _) -> erlang:list_to_existing_atom(In) end, List, Encoding);
safe_to_existing_atom(Atom, _Encoding) when is_atom(Atom) -> safe_to_existing_atom(Atom, _Encoding) when is_atom(Atom) ->
{ok, Atom}; {ok, Atom};
safe_to_existing_atom(_Any, _Encoding) -> safe_to_existing_atom(_Any, _Encoding) ->
@ -547,8 +547,8 @@ readable_error_msg(Error) ->
end end
end. end.
try_to_existing_atom(Fun, Args) -> try_to_existing_atom(Convert, Data, Encoding) ->
try erlang:apply(Fun, Args) of try Convert(Data, Encoding) of
Atom -> Atom ->
{ok, Atom} {ok, Atom}
catch catch

View File

@ -121,13 +121,7 @@ apply_publish_opts(Msg, MQTTMsg) ->
maps:fold( maps:fold(
fun fun
(<<"retain">>, V, Acc) -> (<<"retain">>, V, Acc) ->
Val = Val = V =:= <<"true">>,
case emqx_misc:safe_to_existing_atom(V) of
{ok, true} ->
true;
_ ->
false
end,
emqx_message:set_flag(retain, Val, Acc); emqx_message:set_flag(retain, Val, Acc);
(<<"expiry">>, V, Acc) -> (<<"expiry">>, V, Acc) ->
Val = erlang:binary_to_integer(V), Val = erlang:binary_to_integer(V),

View File

@ -70,6 +70,8 @@
default_subopts/0 default_subopts/0
]). ]).
-import(emqx_listeners, [esockd_access_rules/1]).
-define(ACTIVE_N, 100). -define(ACTIVE_N, 100).
-define(DEFAULT_IDLE_TIMEOUT, 30000). -define(DEFAULT_IDLE_TIMEOUT, 30000).
-define(DEFAULT_GC_OPTS, #{count => 1000, bytes => 1024 * 1024}). -define(DEFAULT_GC_OPTS, #{count => 1000, bytes => 1024 * 1024}).
@ -443,19 +445,6 @@ esockd_opts(Type, Opts0) ->
end end
). ).
esockd_access_rules(StrRules) ->
Access = fun(S) ->
[A, CIDR] = string:tokens(S, " "),
{
list_to_atom(A),
case CIDR of
"all" -> all;
_ -> CIDR
end
}
end,
[Access(R) || R <- StrRules].
ssl_opts(Name, Opts) -> ssl_opts(Name, Opts) ->
Type = Type =
case Name of case Name of

View File

@ -356,15 +356,26 @@ mnesia(_) ->
%% @doc Logger Command %% @doc Logger Command
log(["set-level", Level]) -> log(["set-level", Level]) ->
case emqx_logger:set_log_level(list_to_atom(Level)) of case emqx_misc:safe_to_existing_atom(Level) of
{ok, Level1} ->
case emqx_logger:set_log_level(Level1) of
ok -> emqx_ctl:print("~ts~n", [Level]); ok -> emqx_ctl:print("~ts~n", [Level]);
Error -> emqx_ctl:print("[error] set overall log level failed: ~p~n", [Error]) Error -> emqx_ctl:print("[error] set overall log level failed: ~p~n", [Error])
end; end;
_ ->
emqx_ctl:print("[error] invalid level: ~p~n", [Level])
end;
log(["primary-level"]) -> log(["primary-level"]) ->
Level = emqx_logger:get_primary_log_level(), Level = emqx_logger:get_primary_log_level(),
emqx_ctl:print("~ts~n", [Level]); emqx_ctl:print("~ts~n", [Level]);
log(["primary-level", Level]) -> log(["primary-level", Level]) ->
_ = emqx_logger:set_primary_log_level(list_to_atom(Level)), case emqx_misc:safe_to_existing_atom(Level) of
{ok, Level1} ->
_ = emqx_logger:set_primary_log_level(Level1),
ok;
_ ->
emqx_ctl:print("[error] invalid level: ~p~n", [Level])
end,
emqx_ctl:print("~ts~n", [emqx_logger:get_primary_log_level()]); emqx_ctl:print("~ts~n", [emqx_logger:get_primary_log_level()]);
log(["handlers", "list"]) -> log(["handlers", "list"]) ->
_ = [ _ = [
@ -381,27 +392,51 @@ log(["handlers", "list"]) ->
], ],
ok; ok;
log(["handlers", "start", HandlerId]) -> log(["handlers", "start", HandlerId]) ->
case emqx_logger:start_log_handler(list_to_atom(HandlerId)) of case emqx_misc:safe_to_existing_atom(HandlerId) of
{ok, HandlerId1} ->
case emqx_logger:start_log_handler(HandlerId1) of
ok -> ok ->
emqx_ctl:print("log handler ~ts started~n", [HandlerId]); emqx_ctl:print("log handler ~ts started~n", [HandlerId]);
{error, Reason} -> {error, Reason} ->
emqx_ctl:print("[error] failed to start log handler ~ts: ~p~n", [HandlerId, Reason]) emqx_ctl:print("[error] failed to start log handler ~ts: ~p~n", [
HandlerId, Reason
])
end;
_ ->
emqx_ctl:print("[error] invalid handler:~ts~n", [HandlerId])
end; end;
log(["handlers", "stop", HandlerId]) -> log(["handlers", "stop", HandlerId]) ->
case emqx_logger:stop_log_handler(list_to_atom(HandlerId)) of case emqx_misc:safe_to_existing_atom(HandlerId) of
{ok, HandlerId1} ->
case emqx_logger:stop_log_handler(HandlerId1) of
ok -> ok ->
emqx_ctl:print("log handler ~ts stopped~n", [HandlerId]); emqx_ctl:print("log handler ~ts stopped~n", [HandlerId1]);
{error, Reason} -> {error, Reason} ->
emqx_ctl:print("[error] failed to stop log handler ~ts: ~p~n", [HandlerId, Reason]) emqx_ctl:print("[error] failed to stop log handler ~ts: ~p~n", [
HandlerId1, Reason
])
end;
_ ->
emqx_ctl:print("[error] invalid handler:~ts~n", [HandlerId])
end; end;
log(["handlers", "set-level", HandlerId, Level]) -> log(["handlers", "set-level", HandlerId, Level]) ->
case emqx_logger:set_log_handler_level(list_to_atom(HandlerId), list_to_atom(Level)) of case emqx_misc:safe_to_existing_atom(HandlerId) of
{ok, HandlerId1} ->
case emqx_misc:safe_to_existing_atom(Level) of
{ok, Level1} ->
case emqx_logger:set_log_handler_level(HandlerId1, Level1) of
ok -> ok ->
#{level := NewLevel} = emqx_logger:get_log_handler(list_to_atom(HandlerId)), #{level := NewLevel} = emqx_logger:get_log_handler(HandlerId1),
emqx_ctl:print("~ts~n", [NewLevel]); emqx_ctl:print("~ts~n", [NewLevel]);
{error, Error} -> {error, Error} ->
emqx_ctl:print("[error] ~p~n", [Error]) emqx_ctl:print("[error] ~p~n", [Error])
end; end;
_ ->
emqx_ctl:print("[error] invalid level:~p~n", [Level])
end;
_ ->
emqx_ctl:print("[error] invalid handler:~ts~n", [HandlerId])
end;
log(_) -> log(_) ->
emqx_ctl:usage( emqx_ctl:usage(
[ [
@ -593,26 +628,41 @@ listeners([]) ->
emqx_listeners:list() emqx_listeners:list()
); );
listeners(["stop", ListenerId]) -> listeners(["stop", ListenerId]) ->
case emqx_listeners:stop_listener(list_to_atom(ListenerId)) of case emqx_misc:safe_to_existing_atom(ListenerId) of
{ok, ListenerId1} ->
case emqx_listeners:stop_listener(ListenerId1) of
ok -> ok ->
emqx_ctl:print("Stop ~ts listener successfully.~n", [ListenerId]); emqx_ctl:print("Stop ~ts listener successfully.~n", [ListenerId]);
{error, Error} -> {error, Error} ->
emqx_ctl:print("Failed to stop ~ts listener: ~0p~n", [ListenerId, Error]) emqx_ctl:print("Failed to stop ~ts listener: ~0p~n", [ListenerId, Error])
end; end;
_ ->
emqx_ctl:print("Invalid listener: ~0p~n", [ListenerId])
end;
listeners(["start", ListenerId]) -> listeners(["start", ListenerId]) ->
case emqx_listeners:start_listener(list_to_atom(ListenerId)) of case emqx_misc:safe_to_existing_atom(ListenerId) of
{ok, ListenerId1} ->
case emqx_listeners:start_listener(ListenerId1) of
ok -> ok ->
emqx_ctl:print("Started ~ts listener successfully.~n", [ListenerId]); emqx_ctl:print("Started ~ts listener successfully.~n", [ListenerId]);
{error, Error} -> {error, Error} ->
emqx_ctl:print("Failed to start ~ts listener: ~0p~n", [ListenerId, Error]) emqx_ctl:print("Failed to start ~ts listener: ~0p~n", [ListenerId, Error])
end; end;
_ ->
emqx_ctl:print("Invalid listener: ~0p~n", [ListenerId])
end;
listeners(["restart", ListenerId]) -> listeners(["restart", ListenerId]) ->
case emqx_listeners:restart_listener(list_to_atom(ListenerId)) of case emqx_misc:safe_to_existing_atom(ListenerId) of
{ok, ListenerId1} ->
case emqx_listeners:restart_listener(ListenerId1) of
ok -> ok ->
emqx_ctl:print("Restarted ~ts listener successfully.~n", [ListenerId]); emqx_ctl:print("Restarted ~ts listener successfully.~n", [ListenerId]);
{error, Error} -> {error, Error} ->
emqx_ctl:print("Failed to restart ~ts listener: ~0p~n", [ListenerId, Error]) emqx_ctl:print("Failed to restart ~ts listener: ~0p~n", [ListenerId, Error])
end; end;
_ ->
emqx_ctl:print("Invalid listener: ~0p~n", [ListenerId])
end;
listeners(_) -> listeners(_) ->
emqx_ctl:usage([ emqx_ctl:usage([
{"listeners", "List listeners"}, {"listeners", "List listeners"},