Explorar o código

Merge pull request #7810 from zhongwencool/bad-plugin-file-500-crash

fix: bad plugin file upload crash
zhongwencool %!s(int64=3) %!d(string=hai) anos
pai
achega
bd2abd9ce0

+ 23 - 14
apps/emqx_management/src/emqx_mgmt_api_plugins.erl

@@ -100,7 +100,9 @@ schema("/plugins/install") ->
             },
             responses => #{
                 200 => <<"OK">>,
-                400 => emqx_dashboard_swagger:error_codes(['UNEXPECTED_ERROR', 'ALREADY_INSTALLED'])
+                400 => emqx_dashboard_swagger:error_codes(
+                    ['UNEXPECTED_ERROR', 'ALREADY_INSTALLED', 'BAD_PLUGIN_INFO']
+                )
             }
         }
     };
@@ -319,20 +321,27 @@ upload_install(post, #{body := #{<<"plugin">> := Plugin}}) when is_map(Plugin) -
     %% emqx_plugins_monitor should copy plugins from other core node when boot-up.
     case emqx_plugins:describe(string:trim(FileName, trailing, ".tar.gz")) of
         {error, #{error := "bad_info_file", return := {enoent, _}}} ->
-            {AppName, _Vsn} = emqx_plugins:parse_name_vsn(FileName),
-            AppDir = filename:join(emqx_plugins:install_dir(), AppName),
-            case filelib:wildcard(AppDir ++ "*.tar.gz") of
-                [] ->
-                    do_install_package(FileName, Bin);
-                OtherVsn ->
+            case emqx_plugins:parse_name_vsn(FileName) of
+                {ok, AppName, _Vsn} ->
+                    AppDir = filename:join(emqx_plugins:install_dir(), AppName),
+                    case filelib:wildcard(AppDir ++ "*.tar.gz") of
+                        [] ->
+                            do_install_package(FileName, Bin);
+                        OtherVsn ->
+                            {400, #{
+                                code => 'ALREADY_INSTALLED',
+                                message => iolist_to_binary(
+                                    io_lib:format(
+                                        "~p already installed",
+                                        [OtherVsn]
+                                    )
+                                )
+                            }}
+                    end;
+                {error, Reason} ->
                     {400, #{
-                        code => 'ALREADY_INSTALLED',
-                        message => iolist_to_binary(
-                            io_lib:format(
-                                "~p already installed",
-                                [OtherVsn]
-                            )
-                        )
+                        code => 'BAD_PLUGIN_INFO',
+                        message => iolist_to_binary([Reason, ":", FileName])
                     }}
             end;
         {ok, _} ->

+ 8 - 6
apps/emqx_plugins/src/emqx_plugins.erl

@@ -386,7 +386,7 @@ plugins_readme(_NameVsn, _Options, Info) ->
     Info.
 
 plugin_status(NameVsn, Info) ->
-    {AppName, _AppVsn} = parse_name_vsn(NameVsn),
+    {ok, AppName, _AppVsn} = parse_name_vsn(NameVsn),
     RunningSt =
         case application:get_key(AppName, vsn) of
             {ok, _} ->
@@ -437,7 +437,7 @@ check_plugin(
                 %% assert
                 [_ | _] = Apps,
                 %% validate if the list is all <app>-<vsn> strings
-                lists:foreach(fun parse_name_vsn/1, Apps)
+                lists:foreach(fun(App) -> {ok, _, _} = parse_name_vsn(App) end, Apps)
             catch
                 _:_ ->
                     throw(#{
@@ -471,7 +471,7 @@ load_code_start_apps(RelNameVsn, #{<<"rel_apps">> := Apps}) ->
     AppNames =
         lists:map(
             fun(AppNameVsn) ->
-                {AppName, AppVsn} = parse_name_vsn(AppNameVsn),
+                {ok, AppName, AppVsn} = parse_name_vsn(AppNameVsn),
                 EbinDir = filename:join([LibDir, AppNameVsn, "ebin"]),
                 ok = load_plugin_app(AppName, AppVsn, EbinDir, RunningApps),
                 AppName
@@ -559,7 +559,7 @@ ensure_apps_stopped(#{<<"rel_apps">> := Apps}) ->
     AppsToStop =
         lists:map(
             fun(NameVsn) ->
-                {AppName, _AppVsn} = parse_name_vsn(NameVsn),
+                {ok, AppName, _AppVsn} = parse_name_vsn(NameVsn),
                 AppName
             end,
             Apps
@@ -686,8 +686,10 @@ for_plugin(#{name_vsn := NameVsn, enable := false}, _Fun) ->
 parse_name_vsn(NameVsn) when is_binary(NameVsn) ->
     parse_name_vsn(binary_to_list(NameVsn));
 parse_name_vsn(NameVsn) when is_list(NameVsn) ->
-    {AppName, [$- | Vsn]} = lists:splitwith(fun(X) -> X =/= $- end, NameVsn),
-    {list_to_atom(AppName), Vsn}.
+    case lists:splitwith(fun(X) -> X =/= $- end, NameVsn) of
+        {AppName, [$- | Vsn]} -> {ok, list_to_atom(AppName), Vsn};
+        _ -> {error, "bad_name_vsn"}
+    end.
 
 pkg_file(NameVsn) ->
     filename:join([install_dir(), bin([NameVsn, ".tar.gz"])]).