summaryrefslogtreecommitdiff
path: root/lib/dialyzer
diff options
context:
space:
mode:
authorTom Davies <todavies5@gmail.com>2023-01-23 09:00:01 -0800
committerTom Davies <todavies5@gmail.com>2023-02-13 06:42:00 -0800
commitc2661efb0bdbf54ee288f50fc49be85ff1714fa8 (patch)
tree3971276e3586257654b178f4d4938eaacaf79da3 /lib/dialyzer
parent95501583d5b105373c56e9d7466dbbbb25185408 (diff)
downloaderlang-c2661efb0bdbf54ee288f50fc49be85ff1714fa8.tar.gz
dialyzer: Fix crash when adding multiple PLTs to a PLT
The code previously assumed that multiple PLTs would only be used in combination with an analysis, but adding multiple PLTs to another without analysis was not considered. The existing logic for merging PLTs was used in the context of an analysis, with different data to hand, so here we just validate the merge, then sequentially add each PLT.
Diffstat (limited to 'lib/dialyzer')
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl19
-rw-r--r--lib/dialyzer/test/dialyzer_cl_SUITE.erl28
2 files changed, 41 insertions, 6 deletions
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index dd235d9025..a46336617c 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -105,7 +105,16 @@ init_opts_for_build(Opts) ->
add_to_plt(Opts) ->
Opts1 = init_opts_for_add(Opts),
AddFiles = get_files_from_opts(Opts1),
- plt_common(Opts1, [], AddFiles).
+ case Opts1#options.init_plts of
+ [] -> plt_common(Opts1, [], AddFiles);
+ [_] -> plt_common(Opts1, [], AddFiles);
+ PltFiles ->
+ Plts = [dialyzer_cplt:from_file(F) || F <- PltFiles],
+ % Check merge safety
+ _ = dialyzer_cplt:merge_plts_or_report_conflicts(PltFiles, Plts),
+ _ = [plt_common(Opts#options{init_plts=[Plt]}, [], AddFiles) || Plt <- PltFiles],
+ {{?RET_NOTHING_SUSPICIOUS, []}, [], []}
+ end.
init_opts_for_add(Opts) ->
case Opts#options.output_plt =:= none of
@@ -229,19 +238,19 @@ plt_common(#options{init_plts = [InitPlt]} = Opts, RemoveFiles, AddFiles) ->
enrich_with_modules_changed(do_analysis(AnalFiles, Opts, Plt, #plt_info{files=Md5, mod_deps=ModDeps1}), ChangedOrRemovedMods)
end;
{error, no_such_file} ->
- Msg = io_lib:format("Could not find the PLT: ~ts\n~s",
+ Msg = io_lib:format("Could not find the PLT: ~ts~n~s",
[InitPlt, default_plt_error_msg()]),
cl_error(Msg);
{error, not_valid} ->
- Msg = io_lib:format("The file: ~ts is not a valid PLT file\n~s",
+ Msg = io_lib:format("The file: ~ts is not a valid PLT file~n~s",
[InitPlt, default_plt_error_msg()]),
cl_error(Msg);
{error, read_error} ->
- Msg = io_lib:format("Could not read the PLT: ~ts\n~s",
+ Msg = io_lib:format("Could not read the PLT: ~ts~n~s",
[InitPlt, default_plt_error_msg()]),
cl_error(Msg);
{error, {no_file_to_remove, F}} ->
- Msg = io_lib:format("Could not remove the file ~ts from the PLT: ~ts\n",
+ Msg = io_lib:format("Could not remove the file ~ts from the PLT: ~ts~n",
[F, InitPlt]),
cl_error(Msg)
end.
diff --git a/lib/dialyzer/test/dialyzer_cl_SUITE.erl b/lib/dialyzer/test/dialyzer_cl_SUITE.erl
index ed84fc6068..a639b1cae4 100644
--- a/lib/dialyzer/test/dialyzer_cl_SUITE.erl
+++ b/lib/dialyzer/test/dialyzer_cl_SUITE.erl
@@ -9,14 +9,16 @@
%% Test cases must be exported.
-export([
+ can_add_multiple_plts_to_another_plt/1,
unknown_function_warning_includes_callsite/1,
call_to_missing_warning_includes_callsite/1
]).
-suite() -> [{timetrap, {minutes, 1}}].
+suite() -> [{timetrap, {minutes, 3}}].
all() ->
[
+ can_add_multiple_plts_to_another_plt,
unknown_function_warning_includes_callsite,
call_to_missing_warning_includes_callsite
].
@@ -119,6 +121,30 @@ unknown_function_warning_includes_callsite(Config) when is_list(Config) ->
ok.
+% See GitHub issue erlang/OTP #6850
+can_add_multiple_plts_to_another_plt(Config) when is_list(Config) ->
+
+ PrivDir = proplists:get_value(priv_dir,Config),
+
+ StdlibPlt = filename:join(PrivDir, "stdlib.plt"),
+ ErtsPlt = filename:join(PrivDir, "erts.plt"),
+ OutputPlt = filename:join(PrivDir, "merged.plt"),
+
+ _ = dialyzer:run([{analysis_type, plt_build},
+ {apps, [stdlib]},
+ {output_plt, StdlibPlt}]),
+ _ = dialyzer:run([{analysis_type, plt_build},
+ {apps, [erts]},
+ {output_plt, ErtsPlt}]),
+ ?assertEqual(
+ [],
+ dialyzer:run([{analysis_type, plt_add},
+ {apps, [erts, stdlib]},
+ {plts, [ErtsPlt, StdlibPlt]},
+ {output_plt, OutputPlt}])),
+
+ ok.
+
compile(Config, Module, CompileOpts) ->
Source = lists:concat([Module, ".erl"]),
PrivDir = proplists:get_value(priv_dir,Config),