diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam index 3ec9475324e6..df105cb9ebcf 100644 Binary files a/bootstrap/lib/stdlib/ebin/otp_internal.beam and b/bootstrap/lib/stdlib/ebin/otp_internal.beam differ diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index a84bab19a32b..6ff89e1974c7 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -86,6 +86,12 @@ in the description of each individual BIF. "use the new try/catch syntax for retrieving the " "stack backtrace"}]). +-unsafe([{list_to_atom, 1, possibly}, + {binary_to_atom, '_', possibly}, + {binary_to_term, '_', possibly}]). + +-compile([{nowarn_unsafe_function, {erlang, binary_to_atom, 2}}]). + %% Get rid of autoimports of spawn to avoid clashes with ourselves. -compile({no_auto_import,[spawn_link/1]}). -compile({no_auto_import,[spawn_link/4]}). diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl index 183c2bc41f98..9bf753fd0d7c 100644 --- a/lib/asn1/src/asn1_db.erl +++ b/lib/asn1/src/asn1_db.erl @@ -23,6 +23,8 @@ -module(asn1_db). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([dbstart/1,dbnew/3,dbload/1,dbload/4,dbsave/2,dbput/2, dbput/3,dbget/2]). -export([dbstop/0]). diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 1301572e3494..39b7f6130ecb 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -47,6 +47,8 @@ ASN.1 data (encoded as `BER` or `PER`). > `legacy_erlang_types`. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Compile Time functions for ASN.1 (e.g ASN.1 compiler). %% Public exports diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index ebfd25b7c620..8c163c47b784 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -24,6 +24,8 @@ -module(asn1ct_check). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Main Module for ASN.1 compile time functions -export([check/2,storeindb/2,format_error/1]). diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl index 99a78cd2441a..2e2d31b3fa88 100644 --- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl @@ -23,6 +23,8 @@ -module(asn1ct_constructed_ber_bin_v2). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([gen_encode_sequence/3]). -export([gen_decode_sequence/3]). -export([gen_encode_set/3]). diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index 6907478bd3b9..2da1e909a590 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -23,6 +23,8 @@ -module(asn1ct_constructed_per). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([gen_encode_sequence/3]). -export([gen_decode_sequence/3]). -export([gen_encode_set/3]). diff --git a/lib/asn1/src/asn1ct_func.erl b/lib/asn1/src/asn1ct_func.erl index 80a6fc2d149d..76df6a2e0cef 100644 --- a/lib/asn1/src/asn1ct_func.erl +++ b/lib/asn1/src/asn1ct_func.erl @@ -23,6 +23,9 @@ -module(asn1ct_func). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start_link/0,need/1,call/3,call_gen/3,call_gen/4, generate/1,is_used/1]). -export([init/1,handle_call/3,handle_cast/2,terminate/2]). diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index 02e72a47c0c2..36ece90db1ad 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -23,6 +23,8 @@ -module(asn1ct_gen). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("asn1_records.hrl"). -export([emit/1, diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index 7390f9709928..08c57c04ae85 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -23,6 +23,8 @@ -module(asn1ct_gen_ber_bin_v2). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Generate erlang module which handles (PER) encode and decode for %% all types in an ASN.1 module diff --git a/lib/asn1/src/asn1ct_gen_jer.erl b/lib/asn1/src/asn1ct_gen_jer.erl index d0b350e29eb2..baf98b366e17 100644 --- a/lib/asn1/src/asn1ct_gen_jer.erl +++ b/lib/asn1/src/asn1ct_gen_jer.erl @@ -23,6 +23,9 @@ -module(asn1ct_gen_jer). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_atom, 1}}]). + %% Generate erlang module which handles (PER) encode and decode for %% all types in an ASN.1 module diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 1e9f8635cb36..c59d7b034b48 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -23,6 +23,8 @@ -module(asn1ct_gen_per). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Generate erlang module which handles (PER) encode and decode for %% all types in an ASN.1 module diff --git a/lib/asn1/src/asn1ct_name.erl b/lib/asn1/src/asn1ct_name.erl index 28ee226a8595..80606e7407fc 100644 --- a/lib/asn1/src/asn1ct_name.erl +++ b/lib/asn1/src/asn1ct_name.erl @@ -23,6 +23,8 @@ -module(asn1ct_name). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/0, curr/1, clear/0, diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl index 23994167a25b..6cb332746b0f 100644 --- a/lib/asn1/src/asn1ct_parser2.erl +++ b/lib/asn1/src/asn1ct_parser2.erl @@ -24,6 +24,8 @@ -module(asn1ct_parser2). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([parse/2,format_error/1]). -include("asn1_records.hrl"). diff --git a/lib/asn1/src/asn1ct_tok.erl b/lib/asn1/src/asn1ct_tok.erl index a4da6aa93e20..b9d56ea2dba2 100644 --- a/lib/asn1/src/asn1ct_tok.erl +++ b/lib/asn1/src/asn1ct_tok.erl @@ -23,6 +23,8 @@ -module(asn1ct_tok). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Tokenize ASN.1 code (input to parser generated with yecc) -export([file/1,format_error/1]). diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl index 3e051df156ad..f79ca6e75ad1 100644 --- a/lib/asn1/src/asn1ct_value.erl +++ b/lib/asn1/src/asn1ct_value.erl @@ -23,6 +23,8 @@ -module(asn1ct_value). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Generate Erlang values for ASN.1 types. %% The value is randomized within it's constraints diff --git a/lib/asn1/src/asn1rtt_jer.erl b/lib/asn1/src/asn1rtt_jer.erl index 5437a7f0149c..a9c3365cf728 100644 --- a/lib/asn1/src/asn1rtt_jer.erl +++ b/lib/asn1/src/asn1rtt_jer.erl @@ -21,6 +21,9 @@ %% -module(asn1rtt_jer). + +-compile([{nowarn_unsafe_function, {erlang, binary_to_atom, 1}}]). + %% encoding / decoding of BER -ifdef(DEBUG). -compile(export_all). diff --git a/lib/asn1/src/prepare_templates.erl b/lib/asn1/src/prepare_templates.erl index b72e4d70fea2..0dbd8222c334 100644 --- a/lib/asn1/src/prepare_templates.erl +++ b/lib/asn1/src/prepare_templates.erl @@ -21,6 +21,9 @@ %% -module(prepare_templates). + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([gen_asn1ct_rtt/1,gen_asn1ct_eval/1]). gen_asn1ct_rtt(Ms) -> diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 74fde123386b..35280f931614 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -46,6 +46,8 @@ Possible configuration variables include: > instead. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("ct.hrl"). -include("ct_util.hrl"). diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl index 2d42b3d8ee84..f56fa72b4e49 100644 --- a/lib/common_test/src/ct_config.erl +++ b/lib/common_test/src/ct_config.erl @@ -28,7 +28,8 @@ -module(ct_config). -moduledoc false. -compile([{nowarn_deprecated_function,{crypto,block_decrypt,4}}, - {nowarn_deprecated_function,{crypto,block_encrypt,4}}]). + {nowarn_deprecated_function,{crypto,block_encrypt,4}}, + {nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). -export([start/1, stop/0]). diff --git a/lib/common_test/src/ct_config_xml.erl b/lib/common_test/src/ct_config_xml.erl index bdbb0226c972..cfcf25d4115f 100644 --- a/lib/common_test/src/ct_config_xml.erl +++ b/lib/common_test/src/ct_config_xml.erl @@ -26,6 +26,9 @@ %%---------------------------------------------------------------------- -module(ct_config_xml). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([read_config/1, check_parameter/1]). % read config file diff --git a/lib/common_test/src/ct_cover.erl b/lib/common_test/src/ct_cover.erl index 77379dc37e60..190c7995e56c 100644 --- a/lib/common_test/src/ct_cover.erl +++ b/lib/common_test/src/ct_cover.erl @@ -27,6 +27,8 @@ This module exports help functions for performing code coverage analysis. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([get_spec/1, add_nodes/1, remove_nodes/1, cross_cover_analyse/2]). -include("ct_util.hrl"). diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 242fd3ce1e06..879c920cb85e 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -28,6 +28,8 @@ -module(ct_framework). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, get_all_cases/1]). -export([report/2, warn/1, error_notification/4]). diff --git a/lib/common_test/src/ct_groups.erl b/lib/common_test/src/ct_groups.erl index ab970eada8e5..13161d59f61b 100644 --- a/lib/common_test/src/ct_groups.erl +++ b/lib/common_test/src/ct_groups.erl @@ -27,6 +27,8 @@ -module(ct_groups). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([find_groups/4]). -export([make_all_conf/3, make_all_conf/4, make_conf/5]). -export([delete_subs/2]). diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 10b9718eefe7..2162223ce9d4 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -30,6 +30,8 @@ -module(ct_logs). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init/3, close/3, init_tc/1, end_tc/1]). -export([register_groupleader/2, unregister_groupleader/1]). -export([get_log_dir/0, get_log_dir/1]). diff --git a/lib/common_test/src/ct_master.erl b/lib/common_test/src/ct_master.erl index 642200427763..3c233beaf705 100644 --- a/lib/common_test/src/ct_master.erl +++ b/lib/common_test/src/ct_master.erl @@ -28,6 +28,8 @@ This module exports functions for running `Common Test` nodes on multiple hosts in parallel. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([run/1,run/3,run/4]). -export([run_on_node/2,run_on_node/3]). -export([run_test/1,run_test/2]). diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index abd3ea58e466..096e27fd0ac0 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -214,6 +214,7 @@ logging of all NETCONF connections in to the test case HTML log. """. -moduledoc(#{since => "OTP R15B02"}). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). -dialyzer(no_improper_lists). -include("ct_netconfc.hrl"). diff --git a/lib/common_test/src/ct_property_test.erl b/lib/common_test/src/ct_property_test.erl index e0f86e65b758..f567bcd2d5d3 100644 --- a/lib/common_test/src/ct_property_test.erl +++ b/lib/common_test/src/ct_property_test.erl @@ -78,6 +78,8 @@ prop_ftp() -> """. -moduledoc(#{since => "OTP 17.3"}). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%% API %% Main functions -export([init_per_suite/1, diff --git a/lib/common_test/src/ct_release_test.erl b/lib/common_test/src/ct_release_test.erl index 109a1b514471..0e63a9aa35ec 100644 --- a/lib/common_test/src/ct_release_test.erl +++ b/lib/common_test/src/ct_release_test.erl @@ -120,6 +120,8 @@ -module(ct_release_test). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init/1, upgrade/4, cleanup/1, get_app_vsns/2, get_appup/2]). -include_lib("kernel/include/file.hrl"). diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 43a535230f73..382c02175930 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -23,6 +23,8 @@ -module(ct_run). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Script interface -export([script_start/0,script_usage/0]). diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl index e29c074f4c4f..215fc410519a 100644 --- a/lib/common_test/src/ct_slave.erl +++ b/lib/common_test/src/ct_slave.erl @@ -36,6 +36,8 @@ term in the Test Specification. """. -moduledoc(#{since => "OTP R14B"}). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/1, start/2, start/3, stop/1, stop/2]). -export([slave_started/2, slave_ready/2, monitor_master/1]). diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index 5033bd13d6e2..6bb378de1b4b 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -28,6 +28,8 @@ This module exports help functions for parsing of test specifications. """. -moduledoc(#{since => "OTP 19.3"}). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([prepare_tests/1, prepare_tests/2, collect_tests_from_list/2, collect_tests_from_list/3, collect_tests_from_file/2, collect_tests_from_file/3, diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl index 8ec234e8fcd5..dd4d7abb48a8 100644 --- a/lib/common_test/src/test_server.erl +++ b/lib/common_test/src/test_server.erl @@ -21,6 +21,8 @@ -module(test_server). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -define(DEFAULT_TIMETRAP_SECS, 60). %%% TEST_SERVER_CTRL INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl index 6a2411790481..bd8175242865 100644 --- a/lib/common_test/src/test_server_ctrl.erl +++ b/lib/common_test/src/test_server_ctrl.erl @@ -21,6 +21,9 @@ %% -module(test_server_ctrl). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% The Erlang Test Server %% diff --git a/lib/common_test/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl index 2d7d3fabc5ed..b8e020080d0e 100644 --- a/lib/common_test/src/test_server_node.erl +++ b/lib/common_test/src/test_server_node.erl @@ -22,12 +22,7 @@ -module(test_server_node). -moduledoc false. -%% Prior to OTP 26, maybe_expr used to require runtime support. As it's now -%% enabled by default, all modules are tagged with the feature even when they -%% don't use it. Therefore, we explicitly disable it until OTP 25 is out of -%% support. --feature(maybe_expr, disable). --compile(r25). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). %% Test Controller interface -export([is_release_available/1, find_release/1]). diff --git a/lib/common_test/src/test_server_sup.erl b/lib/common_test/src/test_server_sup.erl index f666cc3efbaf..6b8139a5cfa1 100644 --- a/lib/common_test/src/test_server_sup.erl +++ b/lib/common_test/src/test_server_sup.erl @@ -25,6 +25,9 @@ %%%------------------------------------------------------------------- -module(test_server_sup). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([timetrap/2, timetrap/3, timetrap/4, timetrap_cancel/1, capture_get/1, messages_get/1, timecall/3, call_crash/5, app_test/2, check_new_crash_dumps/0, diff --git a/lib/common_test/test_server/ts.erl b/lib/common_test/test_server/ts.erl index b3b6078430bd..c82fff6cb98d 100644 --- a/lib/common_test/test_server/ts.erl +++ b/lib/common_test/test_server/ts.erl @@ -27,6 +27,9 @@ -module(ts). +-compile([{nowarn_unsafe_function, {file, consult, 1}}, + {nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([cl_run/1, run/0, run/1, run/2, run/3, run/4, run/5, run_category/1, run_category/2, run_category/3, diff --git a/lib/common_test/test_server/ts_erl_config.erl b/lib/common_test/test_server/ts_erl_config.erl index 16477f17d902..f0b415bd98fa 100644 --- a/lib/common_test/test_server/ts_erl_config.erl +++ b/lib/common_test/test_server/ts_erl_config.erl @@ -25,6 +25,7 @@ -module(ts_erl_config). +-compile([{nowarn_unsafe_function, {os, cmd, 1}}]). -export([variables/2]). diff --git a/lib/common_test/test_server/ts_install.erl b/lib/common_test/test_server/ts_install.erl index b4ea435a2de9..b0c39a6aced7 100644 --- a/lib/common_test/test_server/ts_install.erl +++ b/lib/common_test/test_server/ts_install.erl @@ -23,6 +23,10 @@ -export([install/2, platform_id/1]). +-compile([{nowarn_unsafe_function, {file, consult, 1}}, + {nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {os, cmd, 1}}]). + -include("ts.hrl"). -include_lib("kernel/include/file.hrl"). diff --git a/lib/common_test/test_server/ts_install_cth.erl b/lib/common_test/test_server/ts_install_cth.erl index cc48be34f09a..3f5e7bbccf1e 100644 --- a/lib/common_test/test_server/ts_install_cth.erl +++ b/lib/common_test/test_server/ts_install_cth.erl @@ -28,6 +28,10 @@ -module(ts_install_cth). +-compile([{nowarn_unsafe_function, {file, consult, 1}}, + {nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {os, cmd, 1}}]). + %% Suite Callbacks -export([id/1]). -export([init/2]). diff --git a/lib/common_test/test_server/ts_lib.erl b/lib/common_test/test_server/ts_lib.erl index a3c7cbc36d6d..a96f9e78bea5 100644 --- a/lib/common_test/test_server/ts_lib.erl +++ b/lib/common_test/test_server/ts_lib.erl @@ -21,6 +21,9 @@ %% -module(ts_lib). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {os, cmd, 1}}]). + -include_lib("kernel/include/file.hrl"). -include("ts.hrl"). diff --git a/lib/common_test/test_server/ts_run.erl b/lib/common_test/test_server/ts_run.erl index 44129e07135c..2521925c4642 100644 --- a/lib/common_test/test_server/ts_run.erl +++ b/lib/common_test/test_server/ts_run.erl @@ -26,6 +26,9 @@ -export([run/4,ct_run_test/2]). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {os, cmd, 1}}]). + -define(DEFAULT_MAKE_TIMETRAP_MINUTES, 60). -define(DEFAULT_UNMAKE_TIMETRAP_MINUTES, 15). diff --git a/lib/compiler/src/beam_core_to_ssa.erl b/lib/compiler/src/beam_core_to_ssa.erl index 84489f5cc215..11ec28a5a454 100644 --- a/lib/compiler/src/beam_core_to_ssa.erl +++ b/lib/compiler/src/beam_core_to_ssa.erl @@ -62,6 +62,8 @@ -module(beam_core_to_ssa). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/2,format_error/1]). -import(lists, [all/2,append/1,droplast/1, diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl index ef6de4a8693e..adfa1627c75c 100644 --- a/lib/compiler/src/beam_disasm.erl +++ b/lib/compiler/src/beam_disasm.erl @@ -40,6 +40,8 @@ -include("beam_disasm.hrl"). -include("beam_asm.hrl"). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}]). + %%----------------------------------------------------------------------- -type index() :: non_neg_integer(). diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl index 1b971a50269e..7d842a8e3ba2 100644 --- a/lib/compiler/src/beam_ssa_opt.erl +++ b/lib/compiler/src/beam_ssa_opt.erl @@ -38,6 +38,9 @@ -module(beam_ssa_opt). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/2]). -include("beam_ssa_opt.hrl"). diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl index 7df950a98005..6d200e223dac 100644 --- a/lib/compiler/src/cerl.erl +++ b/lib/compiler/src/cerl.erl @@ -62,6 +62,8 @@ function `type/1`. > trees. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([abstract/1, add_ann/2, alias_pat/1, alias_var/1, ann_abstract/2, ann_c_alias/3, ann_c_apply/3, ann_c_atom/2, ann_c_bitstr/5, ann_c_bitstr/6, diff --git a/lib/compiler/src/cerl_inline.erl b/lib/compiler/src/cerl_inline.erl index 08b39d07e7e7..6d8e8e3a9cee 100644 --- a/lib/compiler/src/cerl_inline.erl +++ b/lib/compiler/src/cerl_inline.erl @@ -40,6 +40,8 @@ -module(cerl_inline). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([core_transform/2, transform/1, transform/2]). -import(cerl, [abstract/1, alias_pat/1, alias_var/1, apply_args/1, diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 7bfe1f737f56..d0d62c7eaf16 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -159,6 +159,9 @@ See `m:erl_id_trans` for an example and an explanation of the function `m:epp`, `m:erl_expand_records`, `m:erl_id_trans`, `m:erl_lint`, `m:beam_lib` """. +-compile([{nowarn_unsafe_function, {file, consult, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_term, 1}}]). + %% High-level interface. -export([file/1,file/2,noenv_file/2,format_error/1]). -export([forms/1,forms/2,noenv_forms/2]). diff --git a/lib/compiler/src/core_scan.erl b/lib/compiler/src/core_scan.erl index 1b88d7bed896..afec28b9482d 100644 --- a/lib/compiler/src/core_scan.erl +++ b/lib/compiler/src/core_scan.erl @@ -48,7 +48,9 @@ -module(core_scan). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_atom, 2}}, + nowarn_deprecated_catch]). -export([string/1, string/2, format_error/1]). diff --git a/lib/compiler/src/rec_env.erl b/lib/compiler/src/rec_env.erl index 76a7d4854be9..0a83789444c2 100644 --- a/lib/compiler/src/rec_env.erl +++ b/lib/compiler/src/rec_env.erl @@ -32,6 +32,8 @@ -module(rec_env). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([bind/3, bind_list/3, bind_recursive/4, delete/2, empty/0, get/2, is_defined/2, is_empty/1, keys/1, lookup/2, new_key/1, new_key/2, new_keys/2, new_keys/3, size/1, to_list/1]). diff --git a/lib/compiler/src/sys_core_alias.erl b/lib/compiler/src/sys_core_alias.erl index 3ac5b99d054c..d481c11bf2e1 100644 --- a/lib/compiler/src/sys_core_alias.erl +++ b/lib/compiler/src/sys_core_alias.erl @@ -41,6 +41,8 @@ -module(sys_core_alias). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/2]). -include("core_parse.hrl"). diff --git a/lib/compiler/src/sys_core_prepare.erl b/lib/compiler/src/sys_core_prepare.erl index 04336b33ee8f..ef0a4b110d46 100644 --- a/lib/compiler/src/sys_core_prepare.erl +++ b/lib/compiler/src/sys_core_prepare.erl @@ -23,6 +23,9 @@ -module(sys_core_prepare). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/2]). -include("core_parse.hrl"). diff --git a/lib/compiler/src/sys_coverage.erl b/lib/compiler/src/sys_coverage.erl index 596b7a7e1189..fb3e63b67c51 100644 --- a/lib/compiler/src/sys_coverage.erl +++ b/lib/compiler/src/sys_coverage.erl @@ -23,6 +23,9 @@ -module(sys_coverage). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/2,cover_transform/2,beam_debug_info/1]). -import(lists, [duplicate/2,member/2,reverse/1,reverse/2]). diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 98b4f26cbcc9..b981c5f629e3 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -82,6 +82,8 @@ -module(v3_core). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/2,format_error/1]). -import(lists, [all/2,any/2,append/1,droplast/1,duplicate/2, diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 675d7d4b745c..0f8194e29333 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -182,6 +182,20 @@ end {enable_fips_mode, 1, "use config parameter fips_mode"} ]). +%%%---------------------------------------------------------------- +%% Unsafe functions +-unsafe([{start, 0, "use application:start(crypto) instead"}, + {stop, 0, "use application:stop(crypto) instead"}, + {enable_fips_mode, 1, "use config parameter fips_mode"}, + + {rand_uniform, 2, + "use rand:uniform_s/2 with a cryptographically strong generator"}, + + {public_encrypt, 4, possibly}, + {public_decrypt, 4, possibly}, + {private_encrypt, 4, possibly}, + {private_decrypt, 4, possibly}]). + %%%---------------------------------------------------------------- %% Removed functions. %% diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl index d58ea18445b5..e07fc494b990 100644 --- a/lib/debugger/src/dbg_iload.erl +++ b/lib/debugger/src/dbg_iload.erl @@ -22,6 +22,8 @@ -module(dbg_iload). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([load_mod/4]). %%==================================================================== diff --git a/lib/debugger/src/dbg_wx_break_win.erl b/lib/debugger/src/dbg_wx_break_win.erl index 9964e5681f8e..f73cddeb560b 100644 --- a/lib/debugger/src/dbg_wx_break_win.erl +++ b/lib/debugger/src/dbg_wx_break_win.erl @@ -24,6 +24,8 @@ -module(dbg_wx_break_win). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% External exports -export([create_win/5, update_functions/2, diff --git a/lib/debugger/src/dbg_wx_mon_win.erl b/lib/debugger/src/dbg_wx_mon_win.erl index a241e0c3e5ae..13180f759954 100644 --- a/lib/debugger/src/dbg_wx_mon_win.erl +++ b/lib/debugger/src/dbg_wx_mon_win.erl @@ -24,6 +24,8 @@ -module(dbg_wx_mon_win). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% External exports -export([init/0]). -export([create_win/3, get_window/1, diff --git a/lib/debugger/src/dbg_wx_trace_win.erl b/lib/debugger/src/dbg_wx_trace_win.erl index eb1e855b9774..cac823fffe2c 100644 --- a/lib/debugger/src/dbg_wx_trace_win.erl +++ b/lib/debugger/src/dbg_wx_trace_win.erl @@ -24,6 +24,8 @@ -module(dbg_wx_trace_win). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% External exports -export([init/0, stop/1]). -export([create_win/4, diff --git a/lib/debugger/src/i.erl b/lib/debugger/src/i.erl index 3b2abae0e12c..36aaa85e0847 100644 --- a/lib/debugger/src/i.erl +++ b/lib/debugger/src/i.erl @@ -47,6 +47,8 @@ true ``` """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([help/0,ia/1,ia/2,ia/3,ia/4,iaa/1,iaa/2, ib/2,ib/3,ib/4,ibd/2,ibe/2,iba/3,ibc/3,ic/0,ii/1,ii/2, il/0,im/0,ini/1,ini/2,inq/1,ip/0,ipb/0,ipb/1,iq/1, diff --git a/lib/debugger/src/int.erl b/lib/debugger/src/int.erl index ac4f43debfab..467e8a94e87e 100644 --- a/lib/debugger/src/int.erl +++ b/lib/debugger/src/int.erl @@ -73,6 +73,8 @@ Windows](debugger_chapter.md#breakpoints-and-break-dialog-windows) in the User's Guide for Debugger. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% External exports -export([i/1, i/2, ni/1, ni/2, n/1, nn/1, interpreted/0, file/1, interpretable/1]). diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index d0fa981ef78b..f59c542beee6 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -32,6 +32,8 @@ -module(dialyzer_analysis_callgraph). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/3]). %%% Export for dialyzer_coordinator... diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 839c526076cc..d0ea64553b73 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -33,6 +33,8 @@ -module(dialyzer_cl). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/1, start_report_modules_analyzed/1, start_report_modules_changed_and_analyzed/1]). diff --git a/lib/dialyzer/src/dialyzer_cl_parse.erl b/lib/dialyzer/src/dialyzer_cl_parse.erl index 497cb02c4071..728678b9a2a8 100644 --- a/lib/dialyzer/src/dialyzer_cl_parse.erl +++ b/lib/dialyzer/src/dialyzer_cl_parse.erl @@ -22,6 +22,8 @@ -module(dialyzer_cl_parse). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/0]). -include("dialyzer.hrl"). diff --git a/lib/dialyzer/src/dialyzer_cplt.erl b/lib/dialyzer/src/dialyzer_cplt.erl index cbf6402dac1f..45e4818c6203 100644 --- a/lib/dialyzer/src/dialyzer_cplt.erl +++ b/lib/dialyzer/src/dialyzer_cplt.erl @@ -38,6 +38,8 @@ -module(dialyzer_cplt). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([check_plt/3, compute_md5_from_files/1, included_files/1, diff --git a/lib/dialyzer/src/dialyzer_incremental.erl b/lib/dialyzer/src/dialyzer_incremental.erl index 5ad81e44fc2e..30aa8b4afb37 100644 --- a/lib/dialyzer/src/dialyzer_incremental.erl +++ b/lib/dialyzer/src/dialyzer_incremental.erl @@ -23,6 +23,8 @@ -module(dialyzer_incremental). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/1, start_report_modules_analyzed/1, start_report_modules_changed_and_analyzed/1]). -include("dialyzer.hrl"). diff --git a/lib/dialyzer/src/dialyzer_iplt.erl b/lib/dialyzer/src/dialyzer_iplt.erl index fe094afad479..2dd7083bccce 100644 --- a/lib/dialyzer/src/dialyzer_iplt.erl +++ b/lib/dialyzer/src/dialyzer_iplt.erl @@ -33,6 +33,8 @@ -module(dialyzer_iplt). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([check_incremental_plt/3, included_modules/1, from_file/1, diff --git a/lib/dialyzer/src/dialyzer_options.erl b/lib/dialyzer/src/dialyzer_options.erl index f878ee8e0e3a..993875e318c8 100644 --- a/lib/dialyzer/src/dialyzer_options.erl +++ b/lib/dialyzer/src/dialyzer_options.erl @@ -27,6 +27,8 @@ -module(dialyzer_options). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([build/1, build_warnings/2, get_default_config_filename/0]). -include("dialyzer.hrl"). diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 973057256ab5..4ef38e9c29b6 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -32,6 +32,8 @@ -module(dialyzer_typesig). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([analyze_scc/7]). -export([get_safe_underapprox/2]). diff --git a/lib/dialyzer/src/typer.erl b/lib/dialyzer/src/typer.erl index 4f5e648fde55..d266a57127b0 100644 --- a/lib/dialyzer/src/typer.erl +++ b/lib/dialyzer/src/typer.erl @@ -37,6 +37,8 @@ -module(typer). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/0]). %%----------------------------------------------------------------------- diff --git a/lib/dialyzer/src/typer_core.erl b/lib/dialyzer/src/typer_core.erl index 496aab01483a..ee5d5cb845cb 100644 --- a/lib/dialyzer/src/typer_core.erl +++ b/lib/dialyzer/src/typer_core.erl @@ -38,6 +38,8 @@ -module(typer_core). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([run/1]). %%----------------------------------------------------------------------- diff --git a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl index 086df3464b87..601c07160ca7 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl @@ -4,6 +4,8 @@ %%----------------------------------------------------------------------- -module(file_open_encoding). +-compile([{nowarn_unsafe_function, {erlang, binary_to_atom, 2}}]). + -export([parse/1]). -spec parse(string()) -> proplists:proplist(). diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl index 55959319178c..1f8bc81c0e2c 100644 --- a/lib/edoc/src/edoc.erl +++ b/lib/edoc/src/edoc.erl @@ -59,6 +59,8 @@ -module(edoc). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([files/1, files/2, application/1, application/2, application/3, toc/1, toc/2, toc/3, diff --git a/lib/edoc/src/edoc_cli.erl b/lib/edoc/src/edoc_cli.erl index dd3ad7aad561..04ecd51292a7 100644 --- a/lib/edoc/src/edoc_cli.erl +++ b/lib/edoc/src/edoc_cli.erl @@ -31,6 +31,9 @@ %% @private %% @doc EDoc command line interface -module(edoc_cli). + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([main/1]). %% TODO: accept `private'/`hidden' and forward accordingly diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl index 099314051cd9..f56c7f37db3f 100644 --- a/lib/edoc/src/edoc_data.erl +++ b/lib/edoc/src/edoc_data.erl @@ -40,7 +40,8 @@ -module(edoc_data). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([module/4, overview/4, type/3]). diff --git a/lib/edoc/src/edoc_extract.erl b/lib/edoc/src/edoc_extract.erl index 6cbd48695390..17b3d94cf116 100644 --- a/lib/edoc/src/edoc_extract.erl +++ b/lib/edoc/src/edoc_extract.erl @@ -39,7 +39,8 @@ -module(edoc_extract). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([source/3, source/4, source/5, header/3, header/4, header/5, diff --git a/lib/edoc/src/edoc_html_to_markdown.erl b/lib/edoc/src/edoc_html_to_markdown.erl index dfdb5861688b..aaa4acf61d43 100644 --- a/lib/edoc/src/edoc_html_to_markdown.erl +++ b/lib/edoc/src/edoc_html_to_markdown.erl @@ -39,7 +39,9 @@ -include_lib("kernel/include/eep48.hrl"). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_atom, 1}}, + nowarn_deprecated_catch]). -export([convert_html/2, convert_xml/2, convert_html/3, convert_xml/3]). diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl index d3b21effe856..21309cb7c982 100644 --- a/lib/edoc/src/edoc_layout.erl +++ b/lib/edoc/src/edoc_layout.erl @@ -42,6 +42,8 @@ -module(edoc_layout). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/2, overview/2, type/1]). -export([copyright/1, version/1, since/1, authors/1, references/1, sees/1, todos/1]). diff --git a/lib/edoc/src/edoc_layout_chunks.erl b/lib/edoc/src/edoc_layout_chunks.erl index 4ca20e8eedfe..689f3845c0c4 100644 --- a/lib/edoc/src/edoc_layout_chunks.erl +++ b/lib/edoc/src/edoc_layout_chunks.erl @@ -50,7 +50,8 @@ %% @end -module(edoc_layout_chunks). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_atom, 2}}, + nowarn_deprecated_catch]). % -behaviour(edoc_layout). -export([module/2, overview/2]). diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl index 92fe4ba5f653..595e022c32b9 100644 --- a/lib/edoc/src/edoc_lib.erl +++ b/lib/edoc/src/edoc_lib.erl @@ -39,7 +39,8 @@ -module(edoc_lib). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([count/2, lines/1, split_at/2, split_at_stop/1, split_at_space/1, filename/1, transpose/1, segment/2, diff --git a/lib/edoc/src/edoc_macros.erl b/lib/edoc/src/edoc_macros.erl index de2c8253eb43..f12b5c8542b0 100644 --- a/lib/edoc/src/edoc_macros.erl +++ b/lib/edoc/src/edoc_macros.erl @@ -40,7 +40,8 @@ -module(edoc_macros). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([expand_tags/3, std_macros/1, check_defs/1]). diff --git a/lib/edoc/src/edoc_scanner.erl b/lib/edoc/src/edoc_scanner.erl index bb29eff04869..b70061da727d 100644 --- a/lib/edoc/src/edoc_scanner.erl +++ b/lib/edoc/src/edoc_scanner.erl @@ -47,7 +47,8 @@ %% `tokens' function *always* returns `{more, Continuation}' unless an %% error occurs. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([string/1,string/2,format_error/1]). diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index 607b17cc1307..13721b8a2182 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -33,6 +33,8 @@ -module(edoc_specs). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([type/2, spec/1, dummy_spec/1, docs/2]). -export([add_type_data/4, tag/1, is_tag/1]). diff --git a/lib/edoc/src/edoc_tags.erl b/lib/edoc/src/edoc_tags.erl index 0c84a8e20402..268de082acbc 100644 --- a/lib/edoc/src/edoc_tags.erl +++ b/lib/edoc/src/edoc_tags.erl @@ -43,7 +43,8 @@ -module(edoc_tags). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([tags/0, tags/1, tag_names/0, tag_parsers/0, scan_lines/2, filter_tags/2, filter_tags/3, check_tags/4, parse_tags/4, diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl index 72be36166f65..d8b0552d5fe1 100644 --- a/lib/eunit/src/eunit_data.erl +++ b/lib/eunit/src/eunit_data.erl @@ -38,6 +38,8 @@ -module(eunit_data). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("eunit.hrl"). -include("eunit_internal.hrl"). diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl index 25c31c522f25..0a72cb92f0f5 100644 --- a/lib/eunit/src/eunit_lib.erl +++ b/lib/eunit/src/eunit_lib.erl @@ -39,6 +39,8 @@ -module(eunit_lib). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("eunit.hrl"). -include("eunit_internal.hrl"). diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl index 6a5a297afe19..fe08f62a3c32 100644 --- a/lib/inets/src/http_lib/http_uri.erl +++ b/lib/inets/src/http_lib/http_uri.erl @@ -40,6 +40,8 @@ For more information about URI, see -export([encode/1, decode/1]). +-unsafe([{'_', '_', "use uri_string instead"}]). + -deprecated({encode, 1, "use uri_string:quote function instead"}). -deprecated({decode, 1, "use uri_string:unquote function instead"}). -removed({parse, 1, "use uri_string functions instead"}). diff --git a/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl b/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl index 1ebc856c7c07..ddd17f7c5c41 100644 --- a/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl +++ b/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl @@ -21,6 +21,8 @@ %% -module(gen_tcp_dist). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% %% This is an example of how to plug in an arbitrary distribution %% carrier for Erlang using distribution processes. diff --git a/lib/kernel/examples/uds_dist/src/uds.erl b/lib/kernel/examples/uds_dist/src/uds.erl index ae1a78c44b9d..3c2ba46de9e2 100644 --- a/lib/kernel/examples/uds_dist/src/uds.erl +++ b/lib/kernel/examples/uds_dist/src/uds.erl @@ -1,5 +1,7 @@ -module(uds). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([listen/1, connect/1, accept/1, send/2, recv/1, close/1, get_port/1, get_status_counters/1, set_mode/2, controlling_process/2, tick/1, get_creation/1]). diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl index 5b94880eecb2..34507c6e68dc 100644 --- a/lib/kernel/src/application_controller.erl +++ b/lib/kernel/src/application_controller.erl @@ -22,7 +22,8 @@ -module(application_controller). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %% External exports -export([start/1, diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl index 7b5bb774e0c8..4f5b47d5db62 100644 --- a/lib/kernel/src/auth.erl +++ b/lib/kernel/src/auth.erl @@ -30,7 +30,8 @@ Manual. -moduledoc(#{ deprecated => ~"See each function for what to use instead" }). -behaviour(gen_server). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([start_link/0]). diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index cd06a6da1196..ae77212a1d69 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -345,7 +345,9 @@ common reasons. - **`sticky_directory`** - The object code resides in a sticky directory. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). -include_lib("kernel/include/logger.hrl"). -include("eep48.hrl"). diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index d8f57c4dac63..1df9d98d5b39 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -22,7 +22,8 @@ -module(code_server). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %% This file holds the server part of the code_server. diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 05a67346278c..56ff1debb3ac 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -135,7 +135,8 @@ Nothing is said about whether the disk log files exist or not. `m:file`, `m:wrap_log_reader` """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). %% Efficient file based log - process part diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl index 7e2365bb0c5e..69df5da7033e 100644 --- a/lib/kernel/src/disk_log_1.erl +++ b/lib/kernel/src/disk_log_1.erl @@ -22,7 +22,8 @@ -module(disk_log_1). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). %% Efficient file based log - implementation part diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 4128e59985a6..caab40869b7f 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -28,6 +28,9 @@ -module(dist_util). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_atom, 2}}]). + %%-compile(export_all). -export([handshake_we_started/1, handshake_other_started/1, strict_order_flags/0, rejectable_flags/0, diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl index ba039649fbe0..c4bae23c5bd6 100644 --- a/lib/kernel/src/erl_boot_server.erl +++ b/lib/kernel/src/erl_boot_server.erl @@ -54,7 +54,8 @@ and `m:erl_prim_loader` in ERTS. [`erts:init`](`m:init`), [`erts:erl_prim_loader`](`m:erl_prim_loader`) """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). -include("inet_boot.hrl"). diff --git a/lib/kernel/src/erl_distribution.erl b/lib/kernel/src/erl_distribution.erl index c552e54c4295..cfeef6ef571d 100644 --- a/lib/kernel/src/erl_distribution.erl +++ b/lib/kernel/src/erl_distribution.erl @@ -22,6 +22,8 @@ -module(erl_distribution). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(supervisor). -include_lib("kernel/include/logger.hrl"). diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 27bc7594bea8..55e230f8fa54 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -22,6 +22,8 @@ -module(erts_debug). -moduledoc false. +-compile([{nowarn_unsafe_function, {file, consult, 1}}]). + %% Low-level debugging support. EXPERIMENTAL! -export([size/1,df/1,df/2,df/3,dis_to_file/2,ic/1]). diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 2b364756d50d..a3ee89326ec7 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -190,6 +190,8 @@ operating system kernel. -removed([{pid2name,1,"this functionality is no longer supported"}]). +-unsafe([{consult, '_'}, {path_consult, '_'}]). + %% Interface module for the file server and the file io servers. diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl index d392fe0c84ad..44fdf7f7fff1 100644 --- a/lib/kernel/src/file_server.erl +++ b/lib/kernel/src/file_server.erl @@ -30,7 +30,8 @@ -module(file_server). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -behaviour(gen_server). diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl index 146250bcd069..4086bd5c149b 100644 --- a/lib/kernel/src/group.erl +++ b/lib/kernel/src/group.erl @@ -22,7 +22,8 @@ -module(group). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([nowarn_deprecated_catch, + {nowarn_unsafe_function, {os, cmd, 1}}]). -include_lib("kernel/include/logger.hrl"). diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl index 270ba28b79df..82ce4af02dec 100644 --- a/lib/kernel/src/heart.erl +++ b/lib/kernel/src/heart.erl @@ -106,7 +106,8 @@ In the following descriptions, all functions fail with reason `badarg` if `heart` is not started. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %%%-------------------------------------------------------------------- %%% This is a rewrite of pre_heart from BS.3. diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 073e16633c88..5c30eb1690b0 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -246,6 +246,8 @@ Function `parse_address/1` can be useful: - `nxdomain` - Hostname or domain name cannot be found """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("inet.hrl"). -include("inet_int.hrl"). -include("inet_sctp.hrl"). diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl index bd718635f319..f8ae457bb912 100644 --- a/lib/kernel/src/inet_db.erl +++ b/lib/kernel/src/inet_db.erl @@ -23,7 +23,9 @@ -module(inet_db). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([nowarn_deprecated_catch, + {nowarn_unsafe_function, {file, consult, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_term, 1}}]). %% Store info about ip addresses, names, aliases host files resolver %% options. diff --git a/lib/kernel/src/inet_epmd_dist.erl b/lib/kernel/src/inet_epmd_dist.erl index bb12752ea49e..dec92ceb4ec1 100644 --- a/lib/kernel/src/inet_epmd_dist.erl +++ b/lib/kernel/src/inet_epmd_dist.erl @@ -23,6 +23,8 @@ -module(inet_epmd_dist). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% DistMod API - own inet_tcp_dist equivalence implementation -export([net_address/0, listen_open/2, listen_port/3, listen_close/1, accept_open/2, accept_controller/3, accepted/3, diff --git a/lib/kernel/src/inet_gethost_native.erl b/lib/kernel/src/inet_gethost_native.erl index e8c3a7ef084e..4f369ebb79ec 100644 --- a/lib/kernel/src/inet_gethost_native.erl +++ b/lib/kernel/src/inet_gethost_native.erl @@ -23,7 +23,8 @@ -moduledoc false. -behaviour(supervisor_bridge). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %% Supervisor bridge exports -export([start_link/0, init/1, terminate/2]). diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl index 557668760ddc..2b13790e4ddf 100644 --- a/lib/kernel/src/inet_parse.erl +++ b/lib/kernel/src/inet_parse.erl @@ -22,7 +22,8 @@ -module(inet_parse). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %% Parser for all kinds of ineternet configuration files diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl index 6ed4182f926a..b8e9610bf319 100644 --- a/lib/kernel/src/inet_res.erl +++ b/lib/kernel/src/inet_res.erl @@ -101,6 +101,7 @@ example_lookup(Name, Class, Type) -> ``` """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). %-compile(export_all). -export([gethostbyname/1, gethostbyname/2, gethostbyname/3, gethostbyname/4, diff --git a/lib/kernel/src/logger_h_common.erl b/lib/kernel/src/logger_h_common.erl index dc5379c1c692..6fd85e95a21b 100644 --- a/lib/kernel/src/logger_h_common.erl +++ b/lib/kernel/src/logger_h_common.erl @@ -23,6 +23,8 @@ -moduledoc false. -behaviour(gen_server). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("logger_h_common.hrl"). -include("logger_internal.hrl"). diff --git a/lib/kernel/src/logger_olp.erl b/lib/kernel/src/logger_olp.erl index bdbc75f93f2e..ced2ea5648b3 100644 --- a/lib/kernel/src/logger_olp.erl +++ b/lib/kernel/src/logger_olp.erl @@ -23,6 +23,8 @@ -moduledoc false. -behaviour(gen_server). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("logger_olp.hrl"). -include("logger_internal.hrl"). diff --git a/lib/kernel/src/net_adm.erl b/lib/kernel/src/net_adm.erl index dcb603e6ae35..2a3fb30c2143 100644 --- a/lib/kernel/src/net_adm.erl +++ b/lib/kernel/src/net_adm.erl @@ -45,7 +45,9 @@ _Example:_ ``` """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {file, path_consult, 2}}, + nowarn_deprecated_catch]). -export([host_file/0, localhost/0, diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index b798949dfc59..3ac5ca028352 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -70,7 +70,8 @@ in the Erlang Reference Manual. > for details on how to setup a secure distributed node. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -behaviour(gen_server). diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 6418c5f4d06e..3db995157692 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -52,6 +52,8 @@ a program to run on most platforms. perf_counter/1, set_signal/2, system_time/0, system_time/1, timestamp/0]). +-unsafe([{cmd, '_', "use open_port/2 with {spawn_executable, _} argument"}]). + -doc """ All characters needs to be valid characters on the specific OS using [`file:native_name_encoding()`](`file:native_name_encoding/0`) encoding. Null diff --git a/lib/kernel/src/prim_tty.erl b/lib/kernel/src/prim_tty.erl index f438f9f81637..f24e2b3dbf78 100644 --- a/lib/kernel/src/prim_tty.erl +++ b/lib/kernel/src/prim_tty.erl @@ -21,6 +21,8 @@ -module(prim_tty). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Todo: %% * Try to move buffer handling logic to Erlang %% * This may not be possible for performance reasons, but should be tried diff --git a/lib/kernel/src/ram_file.erl b/lib/kernel/src/ram_file.erl index 43a8cc4028f9..44bd58588760 100644 --- a/lib/kernel/src/ram_file.erl +++ b/lib/kernel/src/ram_file.erl @@ -22,6 +22,8 @@ -module(ram_file). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Binary RAM file interface %% Generic file contents operations diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl index 6d76f62de5dc..5f47cfa03143 100644 --- a/lib/kernel/src/user_drv.erl +++ b/lib/kernel/src/user_drv.erl @@ -22,6 +22,9 @@ -module(user_drv). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {os, cmd, 1}}]). + %% Basic interface to stdin/stdout. %% %% This is responsible for a couple of things: diff --git a/lib/kernel/src/user_sup.erl b/lib/kernel/src/user_sup.erl index 5e9e299bdaf7..0b59e00e4538 100644 --- a/lib/kernel/src/user_sup.erl +++ b/lib/kernel/src/user_sup.erl @@ -22,6 +22,8 @@ -module(user_sup). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% --------------------------------------------- %% This is a supervisor bridge hiding the process %% details of the user/group implementation. diff --git a/lib/mnesia/src/mnesia_frag.erl b/lib/mnesia/src/mnesia_frag.erl index 4a7b8ba908d3..20c5226bd34a 100644 --- a/lib/mnesia/src/mnesia_frag.erl +++ b/lib/mnesia/src/mnesia_frag.erl @@ -31,6 +31,8 @@ -module(mnesia_frag). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Callback functions when accessed within an activity -export([ lock/4, diff --git a/lib/mnesia/test/ext_test_server.erl b/lib/mnesia/test/ext_test_server.erl index 14296011b1be..60b4545f2b33 100644 --- a/lib/mnesia/test/ext_test_server.erl +++ b/lib/mnesia/test/ext_test_server.erl @@ -22,6 +22,8 @@ -module(ext_test_server). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("ext_test_server.hrl"). %% This process is supposed to emulate external database process, it should not be linked diff --git a/lib/mnesia/test/mnesia_atomicity_test.erl b/lib/mnesia/test/mnesia_atomicity_test.erl index 21fc285ff38f..bbd0205406b6 100644 --- a/lib/mnesia/test/mnesia_atomicity_test.erl +++ b/lib/mnesia/test/mnesia_atomicity_test.erl @@ -26,6 +26,8 @@ -author('rossi@erix.ericsson.se'). -include("mnesia_test_lib.hrl"). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init_per_testcase/2, end_per_testcase/2, init_per_group/2, end_per_group/2, all/0, groups/0]). diff --git a/lib/mnesia/test/mnesia_config_test.erl b/lib/mnesia/test/mnesia_config_test.erl index be90fb446cf5..7dab99f03e81 100644 --- a/lib/mnesia/test/mnesia_config_test.erl +++ b/lib/mnesia/test/mnesia_config_test.erl @@ -24,8 +24,10 @@ -module(mnesia_config_test). -author('hakan@erix.ericsson.se'). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("mnesia_test_lib.hrl"). - + -record(test_table,{i,a1,a2,a3}). -record(test_table2,{i, b}). diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl index d4ee73913a3e..5359db6bd362 100644 --- a/lib/mnesia/test/mnesia_evil_coverage_test.erl +++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl @@ -25,6 +25,8 @@ -author('hakan@erix.ericsson.se'). -include("mnesia_test_lib.hrl"). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init_per_testcase/2, end_per_testcase/2, init_per_group/2, end_per_group/2, all/0, groups/0]). diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl index 247479b595f0..b55c61b89ad0 100644 --- a/lib/mnesia/test/mnesia_isolation_test.erl +++ b/lib/mnesia/test/mnesia_isolation_test.erl @@ -24,6 +24,8 @@ -module(mnesia_isolation_test). -author('hakan@erix.ericsson.se'). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init_per_testcase/2, end_per_testcase/2, init_per_group/2, end_per_group/2, all/0, groups/0]). diff --git a/lib/mnesia/test/mnesia_qlc_test.erl b/lib/mnesia/test/mnesia_qlc_test.erl index db154471484b..7c57706983f0 100644 --- a/lib/mnesia/test/mnesia_qlc_test.erl +++ b/lib/mnesia/test/mnesia_qlc_test.erl @@ -23,6 +23,8 @@ %% -module(mnesia_qlc_test). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init_per_testcase/2, end_per_testcase/2, init_per_group/2, end_per_group/2, all/0, groups/0]). diff --git a/lib/mnesia/test/mnesia_recovery_test.erl b/lib/mnesia/test/mnesia_recovery_test.erl index f87cd580fc57..fd0dc6ae3768 100644 --- a/lib/mnesia/test/mnesia_recovery_test.erl +++ b/lib/mnesia/test/mnesia_recovery_test.erl @@ -24,6 +24,8 @@ -module(mnesia_recovery_test). -author('hakan@erix.ericsson.se'). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init_per_testcase/2, end_per_testcase/2, init_per_group/2, end_per_group/2, all/0, groups/0]). diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl index 2c227bbb24d8..5315f2999604 100644 --- a/lib/mnesia/test/mnesia_test_lib.erl +++ b/lib/mnesia/test/mnesia_test_lib.erl @@ -139,6 +139,8 @@ -include("mnesia_test_lib.hrl"). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% included for test server compatibility diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl index b44668015850..d223599edaff 100644 --- a/lib/mnesia/test/mnesia_trans_access_test.erl +++ b/lib/mnesia/test/mnesia_trans_access_test.erl @@ -24,6 +24,8 @@ -module(mnesia_trans_access_test). -author('hakan@erix.ericsson.se'). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([init_per_testcase/2, end_per_testcase/2, init_per_group/2, end_per_group/2, all/0, groups/0]). diff --git a/lib/mnesia/test/mt.erl b/lib/mnesia/test/mt.erl index 937e03414b58..8427eaf887f5 100644 --- a/lib/mnesia/test/mt.erl +++ b/lib/mnesia/test/mt.erl @@ -41,7 +41,8 @@ read_config/0, write_config/1 % Config admin ]). --compile({no_auto_import,[alias/1]}). +-compile([{no_auto_import,[alias/1]}, + {nowarn_unsafe_function, {file, consult, 1}}]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Aliases for the (sub) test suites diff --git a/lib/observer/src/cdv_virtual_list_wx.erl b/lib/observer/src/cdv_virtual_list_wx.erl index f39e30e1d7f6..d9cdee0f4ee4 100644 --- a/lib/observer/src/cdv_virtual_list_wx.erl +++ b/lib/observer/src/cdv_virtual_list_wx.erl @@ -21,6 +21,8 @@ -module(cdv_virtual_list_wx). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(wx_object). -export([start_link/2, start_link/3, diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index 72c14b989d3a..5368431eed55 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -27,6 +27,9 @@ For details about how to get started with the Crashdump Viewer, see the [User's Guide](crashdump_ug.md). """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_atom, 2}}]). + %% %% This module is the main module in the crashdump viewer. It implements %% the server backend for the crashdump viewer tool. diff --git a/lib/observer/src/etop.erl b/lib/observer/src/etop.erl index 7c6b5c8e2947..c33871216ac3 100644 --- a/lib/observer/src/etop.erl +++ b/lib/observer/src/etop.erl @@ -87,6 +87,8 @@ For details about Erlang Top, see the [User's Guide](etop_ug.md). """. -author('siri@erix.ericsson.se'). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/0, start/1, config/2, stop/0, dump/1, help/0]). %% Internal -export([update/1]). diff --git a/lib/observer/src/observer.erl b/lib/observer/src/observer.erl index 38d7dd4af57b..37e027ae7728 100644 --- a/lib/observer/src/observer.erl +++ b/lib/observer/src/observer.erl @@ -32,6 +32,8 @@ For details about how to get started, see the [`User's Guide`](observer_ug.md). """. -moduledoc(#{since => "OTP R15B"}). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start/0, start/1, start_and_wait/0, start_and_wait/1, stop/0]). -doc """ diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl index 6abf2f2da327..a41c20d3b0df 100644 --- a/lib/observer/src/observer_app_wx.erl +++ b/lib/observer/src/observer_app_wx.erl @@ -21,6 +21,8 @@ -module(observer_app_wx). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start_link/3]). %% wx_object callbacks diff --git a/lib/observer/src/observer_trace_wx.erl b/lib/observer/src/observer_trace_wx.erl index 8fbb1e41b4fa..cd01db3f6aca 100644 --- a/lib/observer/src/observer_trace_wx.erl +++ b/lib/observer/src/observer_trace_wx.erl @@ -22,6 +22,8 @@ -module(observer_trace_wx). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([start_link/3, add_processes/1, add_ports/1]). -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3, handle_event/2, handle_cast/2]). diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl index a16620a4e556..dfa338e707f7 100644 --- a/lib/observer/src/observer_wx.erl +++ b/lib/observer/src/observer_wx.erl @@ -21,6 +21,8 @@ -module(observer_wx). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(wx_object). -export([start/0, stop/0]). diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl index 84af62f40936..536320d737ff 100644 --- a/lib/parsetools/src/leex.erl +++ b/lib/parsetools/src/leex.erl @@ -250,6 +250,8 @@ Floats (\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)? > current version of `leex` and generates a parse error. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([compile/3,file/1,file/2,format_error/1]). -import(lists, [member/2,reverse/1,sort/1,keysort/2, diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl index e4d6d3b8cc5f..bc56d21af456 100644 --- a/lib/parsetools/src/yecc.erl +++ b/lib/parsetools/src/yecc.erl @@ -487,6 +487,8 @@ lib/parsetools/include/yeccpre.hrl * Kernighan & Pike: The UNIX programming environment, 1984. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([compile/3, file/1, file/2, format_error/1]). -export_type([option/0, yecc_ret/0]). diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index fc91fa3e4f93..49f9842ef065 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -92,6 +92,16 @@ macros described here and in the User's Guide: %% Tracing -export([handle_trace/3]). +-unsafe([{encrypt_private, 2}, + {encrypt_private, 3, possibly}, + {decrypt_private, 2}, + {decrypt_private, 3, possibly}, + + {encrypt_public, 2}, + {encrypt_public, 3, possibly}, + {decrypt_public, 2}, + {decrypt_public, 3, possibly}]). + %%---------------- %% Moved to ssh -removed([{ssh_decode,2, "use ssh_file:decode/2 instead"}, diff --git a/lib/reltool/src/reltool_app_win.erl b/lib/reltool/src/reltool_app_win.erl index 2ea34d19366c..690f016ea5d8 100644 --- a/lib/reltool/src/reltool_app_win.erl +++ b/lib/reltool/src/reltool_app_win.erl @@ -22,6 +22,8 @@ -module(reltool_app_win). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Public -export([start_link/4, raise/1, refresh/1, open_mod/2]). diff --git a/lib/reltool/src/reltool_mod_win.erl b/lib/reltool/src/reltool_mod_win.erl index df0871f14427..20211b05d142 100644 --- a/lib/reltool/src/reltool_mod_win.erl +++ b/lib/reltool/src/reltool_mod_win.erl @@ -22,6 +22,8 @@ -module(reltool_mod_win). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Public -export([start_link/5, raise/1, refresh/1]). diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index e5f88580d877..23959bc4ffcc 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -22,6 +22,8 @@ -module(reltool_server). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Public -export([ start_link/0, start_link/1, diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl index b0c2b1a53ce3..fe46259e9d5e 100644 --- a/lib/reltool/src/reltool_utils.erl +++ b/lib/reltool/src/reltool_utils.erl @@ -22,6 +22,8 @@ -module(reltool_utils). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Public -export([root_dir/0, erl_libs/0, lib_dirs/1, split_app_name/1, prim_consult/1, diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl index 0527e92fa79d..396b0a3a0488 100644 --- a/lib/runtime_tools/src/system_information.erl +++ b/lib/runtime_tools/src/system_information.erl @@ -29,6 +29,9 @@ -module(system_information). -moduledoc "System Information". -moduledoc(#{since => "OTP 17.0"}). + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(gen_server). %% API diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl index 44327a1081d6..4a65126c12d0 100644 --- a/lib/ssh/src/ssh_connection.erl +++ b/lib/ssh/src/ssh_connection.erl @@ -45,6 +45,8 @@ these messages are handled by [handle_ssh_msg/2](`c:ssh_client_channel:handle_ssh_msg/2`). """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include_lib("kernel/include/logger.hrl"). -include("ssh.hrl"). diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index cda0ad97e525..a681750c0186 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -27,6 +27,8 @@ -module(ssh_transport). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, binary_to_atom, 1}}]). + -include_lib("public_key/include/public_key.hrl"). -include_lib("kernel/include/inet.hrl"). -include("ssh_transport.hrl"). diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl index 2cda800a12d5..dc1c3b8b9e07 100644 --- a/lib/ssl/src/inet_tls_dist.erl +++ b/lib/ssl/src/inet_tls_dist.erl @@ -24,6 +24,8 @@ -module(inet_tls_dist). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([childspecs/0]). -export([select/1, address/0, is_node_name/1, listen/2, accept/1, accept_connection/5, diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 4086c8cfbd67..f8ed4b786ba9 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -133,6 +133,8 @@ Special Erlang node configuration for the application can be found in "Note that in OTP 28 the 'testing' way of calling this function will no longer be supported." }]). +-unsafe([{prf, 5, "Use export_key_materials/4 instead."}]). + -deprecated_type([{prf_random, 0,"Only used in deprecated function prf/5 and will no longer be needed."}]). -removed({ssl_accept, '_', diff --git a/lib/ssl/src/ssl_client_session_cache_db.erl b/lib/ssl/src/ssl_client_session_cache_db.erl index e21bc8732d2b..93a1705b1a42 100644 --- a/lib/ssl/src/ssl_client_session_cache_db.erl +++ b/lib/ssl/src/ssl_client_session_cache_db.erl @@ -24,6 +24,8 @@ -module(ssl_client_session_cache_db). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(ssl_session_cache_api). -include("ssl_handshake.hrl"). diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl index 5cfcd7a41e1d..afc36a30e5f6 100644 --- a/lib/ssl/src/ssl_config.erl +++ b/lib/ssl/src/ssl_config.erl @@ -25,6 +25,8 @@ -module(ssl_config). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("ssl_internal.hrl"). -include("ssl_connection.hrl"). -include_lib("public_key/include/public_key.hrl"). diff --git a/lib/ssl/src/ssl_listen_tracker_sup.erl b/lib/ssl/src/ssl_listen_tracker_sup.erl index 866520b45538..fdb066f61849 100644 --- a/lib/ssl/src/ssl_listen_tracker_sup.erl +++ b/lib/ssl/src/ssl_listen_tracker_sup.erl @@ -27,6 +27,8 @@ -module(ssl_listen_tracker_sup). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(supervisor). %% API diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index 97565305ad62..87b76eee4deb 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -28,6 +28,9 @@ -module(ssl_manager). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(gen_server). %% Internal application API diff --git a/lib/ssl/src/ssl_pem_cache.erl b/lib/ssl/src/ssl_pem_cache.erl index 2a9a3d0531fa..f877c3410ee2 100644 --- a/lib/ssl/src/ssl_pem_cache.erl +++ b/lib/ssl/src/ssl_pem_cache.erl @@ -28,6 +28,9 @@ -module(ssl_pem_cache). -moduledoc false. + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(gen_server). %% Internal application API diff --git a/lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl b/lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl index df6c386e3ca7..8a7f6827bd37 100644 --- a/lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl +++ b/lib/ssl/src/ssl_upgrade_server_session_cache_sup.erl @@ -27,6 +27,8 @@ -module(ssl_upgrade_server_session_cache_sup). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(supervisor). -include("ssl_internal.hrl"). diff --git a/lib/ssl/src/tls_server_session_ticket_sup.erl b/lib/ssl/src/tls_server_session_ticket_sup.erl index 4bc90d578357..23f661b697fe 100644 --- a/lib/ssl/src/tls_server_session_ticket_sup.erl +++ b/lib/ssl/src/tls_server_session_ticket_sup.erl @@ -27,6 +27,8 @@ -module(tls_server_session_ticket_sup). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -behaviour(supervisor). %% API diff --git a/lib/stdlib/scripts/update_deprecations b/lib/stdlib/scripts/update_deprecations index d200635ab204..c9940cd1d87a 100755 --- a/lib/stdlib/scripts/update_deprecations +++ b/lib/stdlib/scripts/update_deprecations @@ -87,6 +87,10 @@ summarize_attributes([{removed, Rs} | As], Module, Acc0) -> Fs = sa_1(Rs, removed, Module, Acc0#st.functions), Acc = Acc0#st{ functions = Fs }, summarize_attributes(As, Module, Acc); +summarize_attributes([{unsafe, Rs} | As], Module, Acc0) -> + Fs = sa_1(Rs, unsafe, Module, Acc0#st.functions), + Acc = Acc0#st{ functions = Fs }, + summarize_attributes(As, Module, Acc); summarize_attributes([{deprecated_type, Ds} | As], Module, Acc0) -> Ts = sa_1(Ds, deprecated, Module, Acc0#st.types), Acc = Acc0#st{ types = Ts }, @@ -228,6 +232,9 @@ info_string(next_major_release) -> info_string(eventually) -> "will be removed in a future release. " "See the documentation for details"; +info_string(possibly) -> + "however, it is possible to use it safely under some conditions. " + "See the documentation for details"; info_string(String) when is_list(String) -> String. @@ -419,9 +426,9 @@ check_deprecations(Top, #st{functions = Fs} = St) -> [] -> St#st{deprecations = Depr}; [_|_] -> - Msg = "The following function(s) have -deprecated() or " - "-removed() attributes, but are not present in the " - "DEPRECATIONS file:\n\n", + Msg = "The following function(s) have -deprecated(), -removed(), " + "or `-unsafe()` attributes, but are not present in the " + "DEPRECATIONS file:\n\n", Bad = [io_lib:format(" ~w:~w/~w\n", [M,F,A]) || {_,M,F,A,_} <- Bad0], Loc = ["\n","Please update ",DeprFile,".\n"], @@ -437,7 +444,9 @@ read_deprecations(File) -> deprecation_file(Root) -> filename:join(Root, "system/doc/general_info/DEPRECATIONS"). -in_deprecations({Tag,M,F,A,_}, Depr) when Tag =:= deprecated; Tag =:= removed -> +in_deprecations({Tag,M,F,A,_}, Depr) when Tag =:= deprecated; + Tag =:= removed; + Tag =:= unsafe -> is_map_key({M,F,A}, Depr). parse_deprecations([<<"#",_/binary>>|Lines]) -> @@ -459,7 +468,9 @@ parse_part([<<"mfa">>,MFA]) -> parse_part([<<"since">>,Since]) -> {since,parse_release(Since)}; parse_part([<<"remove">>,Remove]) -> - {remove,parse_release(Remove)}. + {remove,parse_release(Remove)}; +parse_part([<<"unsafe">>,Unsafe]) -> + {unsafe,parse_release(Unsafe)}. parse_release(Rel) -> binary_to_integer(Rel). @@ -473,6 +484,7 @@ parse_mfa(MFA) -> end, {bin_to_atom(M0),bin_to_atom(F0),A}. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). bin_to_atom(Bin) -> list_to_atom(binary_to_list(Bin)). diff --git a/lib/stdlib/src/argparse.erl b/lib/stdlib/src/argparse.erl index c2eb43d91843..225ba8ba293a 100644 --- a/lib/stdlib/src/argparse.erl +++ b/lib/stdlib/src/argparse.erl @@ -153,6 +153,8 @@ found. -moduledoc(#{since => "OTP 26.0"}). -author("maximfca@gmail.com"). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% API Exports -export([ run/3, diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl index 884ece0b48ba..4f7bd4b1d317 100644 --- a/lib/stdlib/src/beam_lib.erl +++ b/lib/stdlib/src/beam_lib.erl @@ -147,7 +147,10 @@ providing one key for module `t` and another key for all other modules: """. -behaviour(gen_server). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_atom, 2}}, + {nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). -include_lib("kernel/include/eep48.hrl"). diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl index f61d921d0bbe..bbde8cce6f22 100644 --- a/lib/stdlib/src/c.erl +++ b/lib/stdlib/src/c.erl @@ -36,7 +36,8 @@ commands. `m:filename`, `m:compile`, `m:erlang`, `m:yecc`, `m:xref` """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -include_lib("kernel/include/eep48.hrl"). diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl index 812bae4c801b..cdcf3abc5fde 100644 --- a/lib/stdlib/src/dets.erl +++ b/lib/stdlib/src/dets.erl @@ -88,7 +88,8 @@ message. `m:ets`, `m:mnesia`, `m:qlc` """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). %% Disk based linear hashing lookup dictionary. diff --git a/lib/stdlib/src/dets_utils.erl b/lib/stdlib/src/dets_utils.erl index 6d13dd3f9ad7..6b19757e803d 100644 --- a/lib/stdlib/src/dets_utils.erl +++ b/lib/stdlib/src/dets_utils.erl @@ -24,7 +24,8 @@ -include_lib("kernel/include/logger.hrl"). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). %% Utility functions common to several dets file formats. %% To be used from modules dets and dets_v9 only. diff --git a/lib/stdlib/src/dets_v9.erl b/lib/stdlib/src/dets_v9.erl index dd0f952cd88b..21ba0da5e4cd 100644 --- a/lib/stdlib/src/dets_v9.erl +++ b/lib/stdlib/src/dets_v9.erl @@ -21,9 +21,10 @@ %% -module(dets_v9). -moduledoc false. --compile([{nowarn_deprecated_function, [{erlang,phash,2}]}]). --compile(nowarn_deprecated_catch). +-compile([{nowarn_deprecated_function, [{erlang,phash,2}]}, + {nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). %% Dets files, implementation part. This module handles version 9. %% To be called from dets.erl only. diff --git a/lib/stdlib/src/edlin_expand.erl b/lib/stdlib/src/edlin_expand.erl index a77c786196f7..fa3178617117 100644 --- a/lib/stdlib/src/edlin_expand.erl +++ b/lib/stdlib/src/edlin_expand.erl @@ -28,6 +28,9 @@ This module provides an expand_fun for the erlang shell [`io:setopts/1,2`](`io:setopts/1`). """. -moduledoc(#{since => "OTP 26.0"}). + +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% a default expand function for edlin, expanding modules, functions %% filepaths, variable binding, record names, function parameter values, %% record fields and map keys and record field values. diff --git a/lib/stdlib/src/edlin_type_suggestion.erl b/lib/stdlib/src/edlin_type_suggestion.erl index 6bd83b0f13e6..dc55e30093fd 100644 --- a/lib/stdlib/src/edlin_type_suggestion.erl +++ b/lib/stdlib/src/edlin_type_suggestion.erl @@ -22,7 +22,8 @@ -module(edlin_type_suggestion). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -include_lib("kernel/include/eep48.hrl"). -export([type_tree/4, get_arity/3, get_atoms/3, get_types/3, get_types/4, get_function_type/4, print_type/3]). diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index b23989a894fc..50948e50b4b4 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -66,7 +66,8 @@ Module:format_error(ErrorDescriptor) `m:erl_parse` """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %% An Erlang code preprocessor. diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl index a11e9a3fee09..a12f8446c975 100644 --- a/lib/stdlib/src/erl_compile.erl +++ b/lib/stdlib/src/erl_compile.erl @@ -22,6 +22,8 @@ -module(erl_compile). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include("erl_compile.hrl"). -include("file.hrl"). diff --git a/lib/stdlib/src/erl_error.erl b/lib/stdlib/src/erl_error.erl index 8bcb3e13706b..6ed8ac97924a 100644 --- a/lib/stdlib/src/erl_error.erl +++ b/lib/stdlib/src/erl_error.erl @@ -35,6 +35,8 @@ The following functions are to be exported from an Error Info handler. """. -moduledoc(#{since => "OTP 24.0"}). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Supported and documented exported functions in this module. -export([format_exception/3, format_exception/4]). diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 1b35c8da80ac..3f20cfd1fbe9 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -127,7 +127,8 @@ the local function handler argument. A possible use is to call to be called. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %% An evaluator for Erlang abstract syntax. diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 5c80aef2d946..7f3aeb553f17 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -31,6 +31,8 @@ This module expands records in a module. Section [The Abstract Format](`e:erts:absform.md`) in ERTS User's Guide. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/2]). -import(lists, [map/2,foldl/3,foldr/3,sort/1,reverse/1,duplicate/2]). diff --git a/lib/stdlib/src/erl_features.erl b/lib/stdlib/src/erl_features.erl index 4218e7cc8917..192546484ef0 100644 --- a/lib/stdlib/src/erl_features.erl +++ b/lib/stdlib/src/erl_features.erl @@ -29,6 +29,9 @@ functions that might be useful when writing tools. """. -moduledoc(#{since => "OTP 25.0"}). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_term, 1}}]). + -export([all/0, configurable/0, info/1, diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index fcbff047affe..189baed660e2 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -70,6 +70,8 @@ Module:format_error(ErrorDescriptor) `m:epp`, `m:erl_parse` """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([module/1,module/2,module/3,format_error/1]). -export([exprs/2,exprs_opt/3,used_vars/2]). % Used from erl_eval.erl. -export([is_pattern_expr/1,is_guard_test/1,is_guard_test/2,is_guard_test/3]). @@ -191,9 +193,12 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> on_load_anno=erl_anno:new(0) %Location for on_load :: erl_anno:anno(), clashes=[], %Exported functions named as BIFs - not_deprecated=[], %Not considered deprecated + not_deprecated=gb_sets:empty() %Not considered deprecated + :: gb_sets:set(module_or_mfa()), not_removed=gb_sets:empty() %Not considered removed :: gb_sets:set(module_or_mfa()), + not_unsafe=gb_sets:empty() %Not considered unsafe + :: gb_sets:set(module_or_mfa()), func=[], %Current function type_id=[], %Current type id warn_format=0, %Warn format calls @@ -306,6 +311,11 @@ format_error_1({bad_removed,{F,A}}) when F =:= '_'; A =:= '_' -> [F,A]}; format_error_1({bad_removed,{F,A}}) -> {~"removed function ~tw/~w is still exported", [F,A]}; +format_error_1({invalid_unsafe,D}) -> + {~"badly formed unsafe attribute ~tw", [D]}; +format_error_1({bad_unsafe,{F,A}}) -> + {~"unsafe function ~tw/~w undefined or not exported", + [F,A]}; format_error_1({bad_nowarn_unused_function,{F,A}}) -> {~"function ~tw/~w undefined", [F,A]}; format_error_1({bad_nowarn_unused_function,{F,A},GuessFA}) -> @@ -370,6 +380,11 @@ format_error_1({deprecated, MFA, String, Rel}) -> [format_mfa(MFA), Rel, String]}; format_error_1({deprecated, MFA, String}) when is_list(String) -> {~"~s is deprecated; ~s", [format_mfa(MFA), String]}; +format_error_1({unsafe, MFA, String, Rel}) -> + {~"~s is unsafe and will be removed in ~s; ~s", + [format_mfa(MFA), Rel, String]}; +format_error_1({unsafe, MFA, String}) when is_list(String) -> + {~"~s is unsafe; ~s", [format_mfa(MFA), String]}; format_error_1({deprecated_type, {M1, F1, A1}, String, Rel}) -> {~"the type ~p:~p~s is deprecated and will be removed in ~s; ~s", [M1, F1, gen_type_paren(A1), Rel, String]}; @@ -851,7 +866,9 @@ bool_options() -> {undefined_behaviour_callbacks,true}, {ill_defined_behaviour_callbacks,true}, {ill_defined_optional_callbacks,true}, - {unexported_function,true}]. + {unexported_function,true}, + {unsafe_function,true}, + {possibly_unsafe_function,false}]. %% is_warn_enabled(Category, St) -> boolean(). %% Check whether a warning of category Category is enabled. @@ -946,8 +963,9 @@ forms(Forms0, St0) -> St2 = bif_clashes(Forms, St1), St3 = not_deprecated(Forms, St2), St4 = not_removed(Forms, St3), - St5 = foldl(fun form/2, pre_scan(Forms, St4), Forms), - post_traversal_check(Forms, St5). + St5 = not_unsafe(Forms, St4), + St6 = foldl(fun form/2, pre_scan(Forms, St5), Forms), + post_traversal_check(Forms, St6). pre_scan([{attribute,A,compile,C} | Fs], St) -> case is_warn_enabled(export_all, St) andalso @@ -1189,7 +1207,7 @@ not_deprecated(Forms, #lint{compile=Opts}=St0) -> St1 = foldl(fun ({M,Anno}, St2) -> check_module_name(M, Anno, St2) end, St0, MAnno), - St1#lint{not_deprecated = ordsets:from_list(Nowarn)}. + St1#lint{not_deprecated = gb_sets:from_list(Nowarn)}. %% not_removed(Forms, State0) -> State @@ -1209,6 +1227,23 @@ not_removed(Forms, #lint{compile=Opts}=St0) -> end, St0, MFAsAnno), St1#lint{not_removed = gb_sets:from_list(Nowarn)}. +%% not_unsafe(Forms, State0) -> State + +not_unsafe(Forms, #lint{compile=Opts}=St0) -> + %% There are no line numbers in St0#lint.compile. + MFAsAnno = [{MFA,Anno} || + {attribute, Anno, compile, Args} <- Forms, + {nowarn_unsafe_function, MFAs0} <- lists:flatten([Args]), + MFA <- lists:flatten([MFAs0])], + Nowarn = [MFA || + {nowarn_unsafe_function, MFAs0} <- Opts, + MFA <- lists:flatten([MFAs0])], + MAnno = [{M,Anno} || {{M,_F,_A},Anno} <- MFAsAnno, is_atom(M)], + St1 = foldl(fun ({M,Anno}, St2) -> + check_module_name(M, Anno, St2) + end, St0, MAnno), + St1#lint{not_unsafe = gb_sets:from_list(Nowarn)}. + %% The nowarn_bif_clash directive is not only deprecated, it's actually an error from R14A disallowed_compile_flags(Forms, St0) -> %% There are (still) no line numbers in St0#lint.compile. @@ -1253,7 +1288,8 @@ post_traversal_check(Forms, St0) -> StH = check_callback_information(StG), StI = check_nifs(Forms, StH), StJ = check_unexported_functions(StI), - check_removed(Forms, StJ). + StK = check_removed(Forms, StJ), + check_unsafe(Forms, StK). %% check_behaviour(State0) -> State %% Check that the behaviour attribute is valid. @@ -1503,6 +1539,58 @@ removed_desc([Char | Str]) when is_integer(Char) -> removed_desc(Str); removed_desc([]) -> true; removed_desc(_) -> false. +%% check_unsafe(Forms, State0) -> State + +check_unsafe(Forms, St0) -> + Exports = exports(St0), + X = ignore_predefined_funcs(gb_sets:to_list(Exports)), + #lint{module = Mod} = St0, + Bad = [{E,Anno} || {attribute, Anno, unsafe, Us} <- Forms, + D <- lists:flatten([Us]), + E <- unsafe_cat(D, X, Mod)], + foldl(fun ({E,Anno}, St1) -> + add_error(Anno, E, St1) + end, St0, Bad). + +unsafe_cat({F, A, Flg}=D, X, Mod) -> + case unsafe_flag(Flg) of + false -> [{invalid_unsafe,D}]; + true -> unsafe_fa(F, A, X, Mod) + end; +unsafe_cat({F, A}, X, Mod) -> + unsafe_fa(F, A, X, Mod); +unsafe_cat(module, _X, _Mod) -> + []; +unsafe_cat(D, _X, _Mod) -> + [{invalid_unsafe,D}]. + +unsafe_fa('_', '_', _X, _Mod) -> + []; +unsafe_fa(F, '_', X, _Mod) when is_atom(F) -> + %% Don't use this syntax for built-in functions. + case lists:filter(fun({F1,_}) -> F1 =:= F end, X) of + [] -> [{bad_unsafe,{F,'_'}}]; + _ -> [] + end; +unsafe_fa(F, A, X, Mod) when is_atom(F), is_integer(A), A >= 0 -> + case lists:member({F,A}, X) of + true -> []; + false -> + case erlang:is_builtin(Mod, F, A) of + true -> []; + false -> [{bad_unsafe,{F,A}}] + end + end; +unsafe_fa(F, A, _X, _Mod) -> + [{invalid_unsafe,{F,A}}]. + +unsafe_flag(possibly) -> true; +unsafe_flag(String) -> unsafe_desc(String). + +unsafe_desc([Char | Str]) when is_integer(Char) -> unsafe_desc(Str); +unsafe_desc([]) -> true; +unsafe_desc(_) -> false. + %% Ignores functions added by erl_internal:add_predefined_functions/1 ignore_predefined_funcs([{behaviour_info,1} | Fs]) -> ignore_predefined_funcs(Fs); @@ -4682,35 +4770,44 @@ check_qlc_hrl(Anno, M, F, As, St) -> deprecated_function(Anno, M, F, As, St) -> Arity = length(As), MFA = {M, F, Arity}, - case otp_internal:obsolete(M, F, Arity) of - {deprecated, String} when is_list(String) -> - case not is_warn_enabled(deprecated_function, St) orelse - ordsets:is_element(MFA, St#lint.not_deprecated) of - true -> - St; - false -> - add_warning(Anno, {deprecated, MFA, String}, St) - end; - {deprecated, Replacement, Rel} -> - case not is_warn_enabled(deprecated_function, St) orelse - ordsets:is_element(MFA, St#lint.not_deprecated) of - true -> - St; - false -> - add_warning(Anno, {deprecated, MFA, Replacement, Rel}, St) - end; - {removed, String} when is_list(String) -> - add_removed_warning(Anno, MFA, {removed, MFA, String}, St); - {removed, Replacement, Rel} -> - add_removed_warning(Anno, MFA, {removed, MFA, Replacement, Rel}, St); + Obsolete = case otp_internal:obsolete(M, F, Arity) of + {deprecated, String} when is_list(String) -> + {deprecated_function, + {deprecated, MFA, String}, + St#lint.not_deprecated}; + {deprecated, Replacement, Rel} -> + {deprecated_function, + {deprecated, MFA, Replacement, Rel}, + St#lint.not_deprecated}; + {unsafe, String} when is_list(String) -> + {unsafe_function, {unsafe, MFA, String}, + St#lint.not_unsafe}; + {unsafe, Replacement, Rel} -> + {unsafe_function, + {unsafe, MFA, Replacement, Rel}, + St#lint.not_unsafe}; + {removed, String} when is_list(String) -> + {removed, + {removed, MFA, String}, + St#lint.not_removed}; + {removed, Replacement, Rel} -> + {removed, + {removed, MFA, Replacement, Rel}, + St#lint.not_removed}; + no -> + no + end, + case Obsolete of + {Flag, Warning, Filter} -> + add_usage_warning(Anno, MFA, Flag, Warning, Filter, St); no -> - St + St end. -add_removed_warning(Anno, {M, _, _}=MFA, Warning, #lint{not_removed=NotRemoved}=St) -> - case is_warn_enabled(removed, St) andalso - not gb_sets:is_element(M, NotRemoved) andalso - not gb_sets:is_element(MFA, NotRemoved) of +add_usage_warning(Anno, {M,_,_}=MFA, Flag, Warning, Filter, St) -> + case (is_warn_enabled(Flag, St) andalso + not gb_sets:is_element(M, Filter) andalso + not gb_sets:is_element(MFA, Filter)) of true -> add_warning(Anno, Warning, St); false -> diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index 688534b06445..c8362aa18579 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -46,6 +46,8 @@ expressions. `m:erl_eval`, `m:erl_parse`, `m:io` """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%% Pretty printer for Erlang code in the same format as returned from %%% the parser. It does not always produce pretty code. diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index 567344abed88..57e6808d3446 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -82,6 +82,8 @@ Armstrong, Virding and Williams: 'Concurrent Programming in Erlang', Chapter 13. `m:erl_anno`, `m:erl_parse`, `m:io` """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%% External exports -export([string/1,string/2,string/3,tokens/3,tokens/4, diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index f370b45b4c62..35e15f9b04a4 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -27,6 +27,8 @@ See the [escript](`e:erts:escript_cmd.md`) program documentation for more details on how to use escripts. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Useful functions that can be called from scripts. -export([script_name/0, create/2, extract/2]). diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl index 94f5345bd4af..372aba222ed8 100644 --- a/lib/stdlib/src/ets.erl +++ b/lib/stdlib/src/ets.erl @@ -228,7 +228,8 @@ A match specifications with excessive nesting will cause a [`system_limit`](`m:ets#ets_failures`) error exception to be raised. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). %% Interface to the Term store BIF's %% ets == Erlang Term Store diff --git a/lib/stdlib/src/file_sorter.erl b/lib/stdlib/src/file_sorter.erl index 85a038a45412..9784a8fc32b5 100644 --- a/lib/stdlib/src/file_sorter.erl +++ b/lib/stdlib/src/file_sorter.erl @@ -174,7 +174,8 @@ The possible values of `Reason` returned when an error occurs are: term. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). %% Avoid warning for local function error/2 clashing with autoimported BIF. -compile({no_auto_import,[error/2]}). diff --git a/lib/stdlib/src/io_lib_fread.erl b/lib/stdlib/src/io_lib_fread.erl index f26e81325e66..c9b0c6dfc907 100644 --- a/lib/stdlib/src/io_lib_fread.erl +++ b/lib/stdlib/src/io_lib_fread.erl @@ -22,7 +22,8 @@ -module(io_lib_fread). -moduledoc false. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %% Formatted input functions of io library. diff --git a/lib/stdlib/src/man_docs.erl b/lib/stdlib/src/man_docs.erl index 4b5bb45b6f1e..1da3b2449dd7 100644 --- a/lib/stdlib/src/man_docs.erl +++ b/lib/stdlib/src/man_docs.erl @@ -22,6 +22,8 @@ -module(man_docs). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -include_lib("kernel/include/eep48.hrl"). -export([module_to_manpage/3, module_to_manpage/4, markdown_to_manpage/3]). diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl index a196940e9d9c..a5b0a7b03686 100644 --- a/lib/stdlib/src/ms_transform.erl +++ b/lib/stdlib/src/ms_transform.erl @@ -22,7 +22,8 @@ -module(ms_transform). -moduledoc({file, "../doc/src/ms_transform.md"}). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([format_error/1,transform_from_shell/3, parse_transform/2,parse_transform_info/0]). diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index dc38a8164e91..44b17d6f092c 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -3,7 +3,7 @@ %% %% SPDX-License-Identifier: Apache-2.0 %% -%% Copyright Ericsson AB 2020-2025. All Rights Reserved. +%% Copyright Ericsson AB 2020-2026. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -59,7 +59,7 @@ obsolete(code, lib_dir, 2) -> obsolete(crypto, enable_fips_mode, 1) -> {deprecated, "use config parameter fips_mode"}; obsolete(crypto, rand_uniform, 2) -> - {deprecated, "use rand:uniform/1 instead"}; + {deprecated, "use strong_rand_range/1 instead"}; obsolete(crypto, start, 0) -> {deprecated, "use application:start(crypto) instead"}; obsolete(crypto, stop, 0) -> @@ -250,6 +250,24 @@ obsolete(zlib, inflateChunk, 2) -> {removed, "use zlib:safeInflate/2 instead"}; obsolete(zlib, setBufSize, 2) -> {removed, "this function has been removed"}; +obsolete(erlang, list_to_atom, 1) -> + {unsafe, "however, it is possible to use it safely under some conditions. See the documentation for details"}; +obsolete(public_key, decrypt_private, 2) -> + {unsafe, "see the documentation for details"}; +obsolete(public_key, decrypt_private, 3) -> + {unsafe, "however, it is possible to use it safely under some conditions. See the documentation for details"}; +obsolete(public_key, decrypt_public, 2) -> + {unsafe, "see the documentation for details"}; +obsolete(public_key, decrypt_public, 3) -> + {unsafe, "however, it is possible to use it safely under some conditions. See the documentation for details"}; +obsolete(public_key, encrypt_private, 2) -> + {unsafe, "see the documentation for details"}; +obsolete(public_key, encrypt_private, 3) -> + {unsafe, "however, it is possible to use it safely under some conditions. See the documentation for details"}; +obsolete(public_key, encrypt_public, 2) -> + {unsafe, "see the documentation for details"}; +obsolete(public_key, encrypt_public, 3) -> + {unsafe, "however, it is possible to use it safely under some conditions. See the documentation for details"}; obsolete(auth, node_cookie, _) -> {deprecated, "use erlang:set_cookie/2 and net_adm:ping/1 instead"}; obsolete(mnesia_registry, create_table, _) -> @@ -270,6 +288,16 @@ obsolete(filename, find_src, _) -> {removed, "use filelib:find_source/1,3 instead"}; obsolete(ssl, ssl_accept, _) -> {removed, "use ssl:handshake/1,2,3 instead"}; +obsolete(erlang, binary_to_atom, _) -> + {unsafe, "however, it is possible to use it safely under some conditions. See the documentation for details"}; +obsolete(erlang, binary_to_term, _) -> + {unsafe, "however, it is possible to use it safely under some conditions. See the documentation for details"}; +obsolete(file, consult, _) -> + {unsafe, "see the documentation for details"}; +obsolete(file, path_consult, _) -> + {unsafe, "see the documentation for details"}; +obsolete(os, cmd, _) -> + {unsafe, "use open_port/2 with {spawn_executable, _} argument"}; obsolete(ct_slave, _, _) -> {deprecated, "use ?CT_PEER(), or the 'peer' module instead", "OTP 29"}; obsolete(gen_fsm, _, _) -> @@ -284,6 +312,8 @@ obsolete(os_mon_mib, _, _) -> {removed, "this module was removed in OTP 22.0"}; obsolete(pg2, _, _) -> {removed, "this module was removed in OTP 24. Use 'pg' instead"}; +obsolete(http_uri, _, _) -> + {unsafe, "use uri_string instead"}; obsolete(_,_,_) -> no. -dialyzer({no_match, obsolete_type/3}). diff --git a/lib/stdlib/src/peer.erl b/lib/stdlib/src/peer.erl index 15bedb86e8f8..93e1ba7ea6c6 100644 --- a/lib/stdlib/src/peer.erl +++ b/lib/stdlib/src/peer.erl @@ -48,6 +48,8 @@ -module(peer). -author("maximfca@gmail.com"). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% This mode has to be compilable on old nodes, so we ifdef out all %% -doc attributes when compiling before 27. -if(?OTP_RELEASE < 27). @@ -59,7 +61,8 @@ -moduledoc(#{since => "OTP 25.0"}). -endif. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). %% API -export([ diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl index 041db1ee1d57..27701f053c65 100644 --- a/lib/stdlib/src/proc_lib.erl +++ b/lib/stdlib/src/proc_lib.erl @@ -62,7 +62,8 @@ processes that terminate as a result of this process terminating. `m:logger` """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). %% This module is used to set some initial information %% in each created process. diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl index 0c92302f6f28..d19cf0a88b21 100644 --- a/lib/stdlib/src/qlc.erl +++ b/lib/stdlib/src/qlc.erl @@ -22,16 +22,19 @@ -module(qlc). -moduledoc({file, "../doc/src/qlc.md"}). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch, + %% Avoid warning for local function error/1 clashing with + %% autoimported BIF. + {no_auto_import, [error/1]}]). + %%% Purpose: Main API module qlc. Functions for evaluation. %%% Other files: %%% qlc_pt. Implements the parse transform. %% External exports --compile(nowarn_deprecated_catch). - -%% Avoid warning for local function error/1 clashing with autoimported BIF. --compile({no_auto_import,[error/1]}). -export([parse_transform/2, parse_transform_info/0, transform_from_evaluator/2]). diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index f06055dbc1d2..3904c9de5de9 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -22,7 +22,9 @@ -module(shell). -moduledoc({file, "../doc/src/shell.md"}). --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + {nowarn_unsafe_function, {erlang, binary_to_term, 1}}, + nowarn_deprecated_catch]). -export([start/0, start/1, start/2, server/1, server/2, history/1, results/1]). -export([get_state/0, get_function/2]). diff --git a/lib/stdlib/src/shell_docs.erl b/lib/stdlib/src/shell_docs.erl index 2f169ea2c174..32beac05e465 100644 --- a/lib/stdlib/src/shell_docs.erl +++ b/lib/stdlib/src/shell_docs.erl @@ -51,6 +51,8 @@ be rendered as is. """. -moduledoc(#{since => "OTP 23.0"}). +-compile([{nowarn_unsafe_function, {erlang, binary_to_atom, 1}}]). + %% This module takes care of rendering and normalization of %% application/erlang+html style documentation. diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl index 7cbdf32fa77b..2eefacefbdc2 100644 --- a/lib/stdlib/src/slave.erl +++ b/lib/stdlib/src/slave.erl @@ -69,8 +69,8 @@ The master node must be alive. %% before running make (in the OTP make system) %% (the example is for tcsh) - --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([pseudo/1, pseudo/2, diff --git a/lib/stdlib/src/win32reg.erl b/lib/stdlib/src/win32reg.erl index 5a00dac76db4..17719c98af01 100644 --- a/lib/stdlib/src/win32reg.erl +++ b/lib/stdlib/src/win32reg.erl @@ -95,6 +95,8 @@ Reference. Programmer's Reference (from Microsoft) """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([open/1, close/1, current_key/1, change_key/2, change_key_create/2, sub_keys/1, delete_key/1, diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl index 95660cd6588e..1362b94b5c87 100644 --- a/lib/syntax_tools/src/epp_dodger.erl +++ b/lib/syntax_tools/src/epp_dodger.erl @@ -79,7 +79,8 @@ preprocessor [`//stdlib/epp`](`m:epp`) before the parser sees them), an extended syntax tree is created, using the `m:erl_syntax` module. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([parse_file/1, quick_parse_file/1, parse_file/2, quick_parse_file/2, parse/1, quick_parse/1, parse/2, diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl index c94633986266..ed22947b6da6 100644 --- a/lib/syntax_tools/src/erl_prettypr.erl +++ b/lib/syntax_tools/src/erl_prettypr.erl @@ -42,7 +42,8 @@ This module is a front end to the pretty-printing library module `prettypr`, for text formatting of abstract syntax trees defined by the module `erl_syntax`. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([format/1, format/2, best/1, best/2, layout/1, layout/2, get_ctxt_precedence/1, set_ctxt_precedence/2, diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 5811c7b09bd4..55eff6c9c9cb 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -70,7 +70,8 @@ list `[]`. This can be relied on when writing functions that operate on syntax trees. """. --compile(nowarn_deprecated_catch). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}, + nowarn_deprecated_catch]). -export([type/1, is_leaf/1, diff --git a/lib/syntax_tools/src/merl.erl b/lib/syntax_tools/src/merl.erl index b6b10fd3f57e..36ac52b478bf 100644 --- a/lib/syntax_tools/src/merl.erl +++ b/lib/syntax_tools/src/merl.erl @@ -371,6 +371,8 @@ Thus, the following pattern matches all possible clauses: ``` """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([term/1, var/1, print/1, show/1]). -export([quote/1, quote/2, qquote/2, qquote/3]). diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl index 28ab224f393b..acc3e58d6179 100644 --- a/lib/syntax_tools/src/merl_transform.erl +++ b/lib/syntax_tools/src/merl_transform.erl @@ -45,6 +45,8 @@ Using `-include_lib("syntax_tools/include/merl.hrl").` enables this transform, unless the macro `MERL_NO_TRANSFORM` is defined first. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([parse_transform/2]). %% NOTE: We cannot use inline metavariables or any other parse transform diff --git a/lib/tftp/src/tftp_engine.erl b/lib/tftp/src/tftp_engine.erl index c62bf992c1b9..847cc5595d5b 100644 --- a/lib/tftp/src/tftp_engine.erl +++ b/lib/tftp/src/tftp_engine.erl @@ -26,6 +26,8 @@ -module(tftp_engine). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%%------------------------------------------------------------------- %%% Interface %%%------------------------------------------------------------------- diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 55d7aa69e10f..307cbd2fb282 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -105,6 +105,8 @@ alive during the disconnected period, cover data from before and during this period will be included in the analysis. """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% %% This module implements the Erlang coverage tool. %% diff --git a/lib/tools/src/xref.erl b/lib/tools/src/xref.erl index 21de672a40a8..c9315bfda290 100644 --- a/lib/tools/src/xref.erl +++ b/lib/tools/src/xref.erl @@ -103,6 +103,12 @@ module. All unknown functions are also undefined functions; there is a [figure](xref_chapter.md#venn2) in the User's Guide that illustrates this relationship. +A _documented function_{: #documented_function } is a function that has a +corresponding `-doc()` attribute. These are further divided into two +categories: a function whose `-doc()` attribute is `false` or `hidden` is +_documented as private_{: #private_function }, and function whose `-doc()` is +not is _documented as public_{: #public_function }. + The module attribute tag `deprecated` can be used to inform Xref about _deprecated functions_{: #deprecated_function } and optionally when functions are planned to be removed. A few examples show the idea: @@ -132,6 +138,17 @@ functions are planned to be removed. A few examples show the idea: - `-deprecated({'_','_',eventually}).` - All exported functions in the module are deprecated and will eventually be removed. +Likewise, the module attribute tag `unsafe` can be used to inform +Xref about _unsafe functions_{: #unsafe_function }. + +- `-unsafe({f,1}).` - The exported function `f/1` is always unsafe. + +- `-unsafe({f,1,"Use g/1 instead"}).` - As above but with a descriptive + string. The string is currently unused by `xref` but other tools can make use + of it. + +- `-unsafe({f,1,possibly}).` - The exported function `f/1` is _possibly unsafe_ + Before any analysis can take place, module data must be _set up_. For instance, the cross reference and the unknown functions are computed when all module data are known. The functions that need complete data @@ -306,6 +323,20 @@ in `functions` mode only): - **`DF_3`** - Deprecated Functions. All deprecated functions to be removed in next version, next major release, or later. +- **`DC`** - Documented Functions. All functions with a `-doc` directive. + +- **`DC_1`** - Documented Public Functions. All functions whose `-doc` + directive is not `false` or `hidden`. + +- **`DC_2`** - Documented Private Functions. All functions whose `-doc` + directive is `false` or `hidden`. + +- **`US`** - Unsafe Functions. All unsafe functions. + +- **`US_1`** - Unsafe Functions that cannot be used safely in any way. + +- **`US_2`** - Unsafe Functions that could potentially be used safely. + These are a few [](){: #simple_facts } facts about the predefined variables (the set operators `+` (union) and `-` (difference) as well as the cast operator `(`Type`)` are described below): @@ -342,6 +373,12 @@ set operators `+` (union) and `-` (difference) as well as the cast operator - `DF_2` is a subset of `DF_3`. - `DF_3` is a subset of `DF`. - `DF` is a subset of `X + B`. +- `DC_2` is a subset of `DC`. +- `DC_1` is a subset of `DC`. +- `DC` is a subset of `X + B`. +- `US_2` is a subset of `US`. +- `US_1` is a subset of `US`. +- `US` is a subset of `X + B`. An important notion is that of _conversion_{: #conversion } of expressions. The syntax of a cast expression is: @@ -1502,6 +1539,9 @@ analyse(Name, What, Options) -> | {'deprecated_function_calls', DeprFlag :: depr_flag()} | 'deprecated_functions' | {'deprecated_functions', DeprFlag :: depr_flag()} + | 'private_function_calls' + | 'undocumented_function_calls' + | 'unsafe_function_calls' | {'call', FuncSpec :: func_spec()} | {'use', FuncSpec :: func_spec()} | {'module_call', ModSpec :: mod_spec()} @@ -1539,6 +1579,18 @@ analyses, which operate on all [analyzed modules](`m:xref#analyzed_module`), are (analyses marked with (\*) are available only in [mode `functions`](`m:xref#mode`)): +- **`private_function_calls`** - Returns a list of calls to + [private functions](`m:xref#private_function`) from applications other than + the one the callee is defined in. + +- **`undocumented_function_calls`** - Returns a list of calls to + functions _lacking_ a `-doc()` directive from applications other than the one + the callee is defined in. + +- **`unsafe_function_calls`** - Returns a list of + [unsafe functions](`m:xref#unsafe_function`). Note that this implies + `private_function_calls`. + - **`undefined_function_calls`(\*)** - Returns a list of calls to [undefined functions](`m:xref#undefined_function`). diff --git a/lib/tools/src/xref_base.erl b/lib/tools/src/xref_base.erl index 1e9d4b527b56..db383275d638 100644 --- a/lib/tools/src/xref_base.erl +++ b/lib/tools/src/xref_base.erl @@ -23,6 +23,8 @@ -module(xref_base). -moduledoc false. +-include_lib("kernel/include/eep48.hrl"). + %% Avoid warning for local function error/1 clashing with autoimported BIF. -compile({no_auto_import,[error/1]}). -export([new/0, new/1, delete/1, @@ -389,6 +391,14 @@ analysis(Analysis) -> analysis(Analysis, functions). %% -> string() | Error +analysis(private_function_calls, functions) -> + "((Fun) strict AE) || DC_2"; +analysis(undocumented_function_calls, functions) -> + "((Fun) strict AE) || (X - DC)"; +analysis(unsafe_function_calls, functions) -> + %% Cross-application calls to explicitly undocumented functions are + %% considered unsafe for the purposes of this analysis. + "(XC || US) + (((Fun) strict AE) || DC_2)"; analysis(undefined_function_calls, functions) -> "(XC - UC) || (XU - X - B)"; analysis(undefined_functions, modules) -> @@ -795,39 +805,63 @@ process_module(State) -> end. abst(File, Builtins, _Mode = functions) -> - case beam_lib:chunks(File, [abstract_code, exports, attributes]) of - {ok, {M,[{abstract_code,NoA},_X,_A]}} when NoA =:= no_abstract_code -> - {ok, M, NoA}; + case beam_lib:chunks(File, + [abstract_code, exports, attributes, documentation], + [allow_missing_chunks]) of + {ok, {M,[{abstract_code,no_abstract_code}, + _X, + _A, + {documentation,missing_chunk}]}} -> + {ok, M, no_abstract_code}; {ok, {M, [{abstract_code, {abstract_v1, Forms}}, - {exports,X0}, {attributes,A}]}} -> + {exports,X0}, {attributes,A}, + {documentation, missing_chunk}]}} -> %% R7. X = xref_utils:fa_to_mfa(X0, M), D = deprecated(A, X, M), - xref_reader:module(M, Forms, Builtins, X, D); + Documented = {[], []}, + Unsafe = {{[], []}, []}, + xref_reader:module(M, Forms, Builtins, X, D, Documented, Unsafe); {ok, {M, [{abstract_code, {abstract_v2, Forms}}, - {exports,X0}, {attributes,A}]}} -> + {exports,X0}, {attributes,A}, + {documentation, missing_chunk}]}} -> %% R8-R9B. X = xref_utils:fa_to_mfa(X0, M), D = deprecated(A, X, M), - xref_reader:module(M, Forms, Builtins, X, D); + Documented = {[], []}, + Unsafe = {{[], []}, []}, + xref_reader:module(M, Forms, Builtins, X, D, Documented, Unsafe); {ok, {M, [{abstract_code, {raw_abstract_v1, Code}}, - {exports,X0}, {attributes,A}]}} -> + {exports,X0}, {attributes,A}, + {documentation, Doc}]}} -> %% R9C- Forms0 = epp:interpret_file_attribute(Code), Forms1 = erl_expand_records:module(Forms0, []), Forms = erl_internal:add_predefined_functions(Forms1), X = mfa_exports(X0, A, M), - D = deprecated(A, X, M), - xref_reader:module(M, Forms, Builtins, X, D); + Deprecated = deprecated(A, X, M), + Documented = documented(Doc, A, M), + Unsafe = unsafe(A, X, M), + xref_reader:module(M, Forms, Builtins, X, + Deprecated, Documented, Unsafe); Error when element(1, Error) =:= error -> Error end; abst(File, Builtins, _Mode = modules) -> - case beam_lib:chunks(File, [exports, imports, attributes]) of - {ok, {Mod, [{exports,X0}, {imports,I0}, {attributes,At}]}} -> - X1 = mfa_exports(X0, At, Mod), - X = filter(fun(MFA) -> not (predef_fun())(MFA) end, X1), - D = deprecated(At, X, Mod), + case beam_lib:chunks(File, + [exports, imports, attributes, documentation], + [allow_missing_chunks]) of + {ok, {Mod, [{exports,X0}, + {imports,I0}, + {attributes,At}, + {documentation, Doc}]}} -> + X1 = mfa_exports(X0, At, Mod), + X = filter(fun(MFA) -> not (predef_fun())(MFA) end, X1), + + Deprecated = deprecated(At, X, Mod), + Documentation = documented(Doc, At, Mod), + Unsafe = unsafe(At, X, Mod), + I = case Builtins of true -> I0; @@ -837,7 +871,8 @@ abst(File, Builtins, _Mode = modules) -> end, filter(Fun, I0) end, - {ok, Mod, {X, I, D}, []}; + + {ok, Mod, {X, I, Deprecated, Documentation, Unsafe}, []}; Error when element(1, Error) =:= error -> Error end. @@ -858,6 +893,42 @@ adjust_arity(F, A) -> false -> A - 1 end. +documented(#docs_v1{docs=Entries}, Attributes, Module) -> + AdjustArity = case xref_utils:is_abstract_module(Attributes) of + true -> fun adjust_arity/2; + false -> fun(_Name, Arity) -> Arity end + end, + documented_v1(Entries, Module, AdjustArity, [], []); +documented(_Doc, _Attributes, _Module) -> + {[], []}. + +documented_v1([Entry | Entries], Module, AdjustArity, Documented, Hidden) -> + case Entry of + {{function, Name, Arity0}, _Anno, _Signature, hidden, _Metadata} -> + Arity = AdjustArity(Name, Arity0), + documented_v1(Entries, + Module, + AdjustArity, + Documented, + [{Module, Name, Arity} | Hidden]); + {{function, Name, Arity0}, _Anno, _Signature, Doc, Metadata} + when is_map(Doc); is_map_key(equiv, Metadata) -> + Arity = AdjustArity(Name, Arity0), + documented_v1(Entries, + Module, + AdjustArity, + [{Module, Name, Arity} | Documented], + Hidden); + {_KindNameArity, _Anno, _Signature, _Doc, _Metadata} -> + documented_v1(Entries, + Module, + AdjustArity, + Documented, + Hidden) + end; +documented_v1([], _Module, _AdjustArity, Documented, Hidden) -> + {Documented, Hidden}. + deprecated(A, X, M) -> DF = {[],[],[],[]}, case keysearch(deprecated, 1, A) of @@ -915,6 +986,61 @@ depr_desc([Char | Str]) when is_integer(Char) -> depr_desc(Str); depr_desc([]) -> 4; depr_desc(_) -> undefined. +unsafe(A, X, M) -> + Unsafe = {[], []}, + case keysearch(unsafe, 1, A) of + {value, {unsafe, Specs}} -> + unsafe(Specs, M, Unsafe, X, []); + false -> + {Unsafe, []} + end. + +unsafe([Spec | Rest], M, US0, X, Bad) -> + case unsafe_cat(Spec, M, X) of + {I, Ut} -> + US = setelement(I, US0, Ut ++ element(I, US0)), + unsafe(Rest, M, US, X, Bad); + undefined -> + unsafe(Rest, M, US0, X, [Spec | Bad]) + end; +unsafe([], _M, US, _X, Bad) -> + {US, reverse(Bad)}. + +unsafe_cat({F, A, Flg}, M, X) -> + case unsafe_flag(Flg) of + undefined -> undefined; + I -> unsafe_fa(F, A, X, M, I) + end; +unsafe_cat({F, A}, M, X) -> + unsafe_fa(F, A, X, M, 2); +unsafe_cat(module, M, X) -> + unsafe_fa('_', '_', X, M, 2); +unsafe_cat(_D, _M, _X) -> + undefined. + +unsafe_fa('_', '_', X, _M, I) -> + {I, X}; +unsafe_fa(F, '_', X, _M, I) when is_atom(F) -> + {I, filter(fun({_,F1,_}) -> F1 =:= F end, X)}; +unsafe_fa(F, A, _X, M, I) when is_atom(F), is_integer(A), A >= 0 -> + {I, [{M,F,A}]}; +unsafe_fa(_F, _A, _X, _M, _I) -> + undefined. + +%% unsafe_flag(Flag) -> integer() | undefined +%% Maps symbolic flags for unsafe functions to their category indexes +%% in the unsafe tuple. +%% +%% {US_1, US} + +unsafe_flag(possibly) -> 1; +unsafe_flag(String) -> unsafe_desc(String). + +%% Strings fall into the general category, index 2. +unsafe_desc([Char | Str]) when is_integer(Char) -> unsafe_desc(Str); +unsafe_desc([]) -> 2; +unsafe_desc(_) -> undefined. + %% -> {ok, Module, Bad, State} | throw(Error) %% Assumes: %% L U X is a subset of dom DefAt @@ -928,7 +1054,8 @@ do_add_module(S, XMod, Unres, Data) -> {ok, Ms, Bad, NS}. prepare_module(_Mode = functions, XMod, Unres0, Data) -> - {DefAt0, LPreCAt0, XPreCAt0, LC0, XC0, X0, Attrs, Depr, OL0} = Data, + {DefAt0, LPreCAt0, XPreCAt0, LC0, XC0, X0, Attrs, Depr, OL0, + Doc, US0} = Data, %% Bad is a list of bad values of 'xref' attributes. {ALC0,AXC0,Bad0} = Attrs, FT = [tspec(func)], @@ -963,22 +1090,35 @@ prepare_module(_Mode = functions, XMod, Unres0, Data) -> XC = union(XC1, AXC), LC = union(LC1, ALC), - {DF1,DF_11,DF_21,DF_31,DBad} = depr_mod(Depr, X), + {DF1,DF_11,DF_21,DF_31,DFBad} = depr_mod(Depr, X), + {DC, DC_1, DC_2, DCBad} = doc_mod(Doc, X), + {US, US_1, US_2, USBad} = unsafe_mod(US0, X), + {EE, ECallAt} = inter_graph(X, L, LC, XC, CallAt), + {ok, {functions, XMod, [DefAt,L,X,LCallAt,XCallAt,CallAt,LC,XC,EE,ECallAt, - OL1,DF1,DF_11,DF_21,DF_31], NoCalls, Unres}, - DBad++Bad}; + OL1,DF1,DF_11,DF_21,DF_31,DC,DC_1,DC_2,US,US_1,US_2], + NoCalls, Unres}, + DFBad++DCBad++USBad++Bad}; prepare_module(_Mode = modules, XMod, _Unres, Data) -> - {X0, I0, Depr} = Data, + {X0, I0, Depr, Doc, Unsafe} = Data, + X1 = xref_utils:xset(X0, [tspec(func)]), I1 = xref_utils:xset(I0, [tspec(func)]), - {DF1,DF_11,DF_21,DF_31,DBad} = depr_mod(Depr, X1), - {ok, {modules, XMod, [X1,I1,DF1,DF_11,DF_21,DF_31]}, DBad}. + + {DF1,DF_11,DF_21,DF_31,DFBad} = depr_mod(Depr, X1), + {DC, DC_1, DC_2, DCBad} = doc_mod(Doc, X1), + {US, US_1, US_2, USBad} = unsafe_mod(Unsafe, X1), + + {ok, {modules, XMod, [X1,I1,DF1,DF_11,DF_21,DF_31, + DC, DC_1, DC_2, + US, US_1, US_2]}, + DFBad ++ DCBad ++ USBad}. finish_module({functions, XMod, List, NoCalls, Unres}, S) -> ok = check_module(XMod, S), [DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2,LC2,XC2,EE2,ECallAt2, - OL2,DF2,DF_12,DF_22,DF_32] = pack(List), + OL2,DF2,DF_12,DF_22,DF_32,DC,DC_1,DC_2,US,US_1,US_2] = pack(List), LU = range(LC2), @@ -988,7 +1128,7 @@ finish_module({functions, XMod, List, NoCalls, Unres}, S) -> MS = xref_utils:xset(M, atom), T = from_sets({MS,DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2, LC2,XC2,LU,EE2,ECallAt2,Unres,LPredefined,OL2, - DF2,DF_12,DF_22,DF_32}), + DF2,DF_12,DF_22,DF_32,DC,DC_1,DC_2,US,US_1,US_2}), NoUnres = XMod#xref_mod.no_unresolved, Info = no_info(X2, L2, LC2, XC2, EE2, Unres, NoCalls, NoUnres), @@ -998,10 +1138,13 @@ finish_module({functions, XMod, List, NoCalls, Unres}, S) -> {ok, [M], take_down(S1)}; finish_module({modules, XMod, List}, S) -> ok = check_module(XMod, S), - [X2,I2,DF2,DF_12,DF_22,DF_32] = pack(List), + [X2,I2,DF2,DF_12,DF_22,DF_32,DC,DC_1,DC_2,US,US_1,US_2] = pack(List), M = XMod#xref_mod.name, MS = xref_utils:xset(M, atom), - T = from_sets({MS, X2, I2, DF2, DF_12, DF_22, DF_32}), + T = from_sets({MS, X2, I2, + DF2, DF_12, DF_22, DF_32, + DC, DC_1, DC_2, + US, US_1, US_2}), Info = [], XMod1 = XMod#xref_mod{data = T, info = Info}, S1 = S#xref{modules = dict:store(M, XMod1, S#xref.modules)}, @@ -1040,7 +1183,48 @@ depr_mod({Depr,Bad0}, X) -> Bad1 = difference(All, XB), Bad2 = to_external(difference(Bad1, predefined_funs(Bad1))), Bad = map(fun(B) -> {depr_attr, B} end, usort(Bad2++Bad0)), - {DF,DF_1,DF_2,DF_3,Bad}. + + {DF, DF_1, DF_2, DF_3, Bad}. + +doc_mod({Documented0, Hidden0}, X) -> + FT = [tspec(func)], + + Documented = xref_utils:xset(Documented0, FT), + Hidden = xref_utils:xset(Hidden0, FT), + + All = union(from_sets([Documented, Hidden])), + Fun = {external, fun({M,F,A}) -> xref_utils:is_builtin(M, F, A) end}, + XB = union(X, specification(Fun, All)), + + DC_1 = intersection(Documented, XB), + DC_2 = intersection(Hidden, XB), + DC = union(DC_1, DC_2), + + Bad1 = difference(All, XB), + Bad2 = to_external(difference(Bad1, predefined_funs(Bad1))), + Bad = map(fun(B) -> {depr_attr, B} end, usort(Bad2)), + + {DC, DC_1, DC_2, Bad}. + +unsafe_mod({{Potentially0, Always0}, Bad0}, X) -> + FT = [tspec(func)], + + Potentially = xref_utils:xset(Potentially0, FT), + Always = xref_utils:xset(Always0, FT), + + All = union(from_sets([Potentially, Always])), + Fun = {external, fun({M,F,A}) -> xref_utils:is_builtin(M, F, A) end}, + XB = union(X, specification(Fun, All)), + + US_1 = intersection(Always, XB), + US_2 = intersection(Potentially, XB), + US = union(US_1, US_2), + + Bad1 = difference(All, XB), + Bad2 = to_external(difference(Bad1, predefined_funs(Bad1))), + Bad = map(fun(B) -> {depr_attr, B} end, usort(Bad2++Bad0)), + + {US, US_1, US_2, Bad}. %% Extra edges gathered from the attribute 'xref' (experimental) extra_edges(CAX, CAL, Bad0, F) -> @@ -1245,7 +1429,10 @@ do_set_up(S) when S#xref.mode =:= functions -> ModDictList = dict:to_list(S#xref.modules), [DefAt0, L, X0, LCallAt, XCallAt, CallAt, LC, XC, LU, EE0, ECallAt, UC, LPredefined, OL, - Mod_DF,Mod_DF_1,Mod_DF_2,Mod_DF_3] = make_families(ModDictList, 19), + Mod_DF, Mod_DF_1, Mod_DF_2, Mod_DF_3, + Mod_DC, Mod_DC_1, Mod_DC_2, + Mod_US, Mod_US_1, Mod_US_2] = + make_families(ModDictList, 25), {XC_1, XU, XPredefined} = do_set_up_1(XC), LC_1 = user_family(union_of_family(LC)), @@ -1276,8 +1463,10 @@ do_set_up(S) when S#xref.mode =:= functions -> AM = domain(F1), %% Undef is the union of U0 and Lib: - {Undef, U0, Lib, Lib_DF, Lib_DF_1, Lib_DF_2, Lib_DF_3} = - make_libs(XU, F1, AM, S#xref.library_path, S#xref.libraries), + {Undef, U0, Lib, Lib_DF, Lib_DF_1, Lib_DF_2, Lib_DF_3, + Lib_DC, Lib_DC_1, Lib_DC_2, + Lib_US, Lib_US_1, Lib_US_2} = + make_libs(XU, F1, AM, S#xref.library_path, S#xref.libraries), {B, U} = make_builtins(U0), X1_B = family_union(X1, B), F = family_union(F1, Lib), @@ -1289,6 +1478,14 @@ do_set_up(S) when S#xref.mode =:= functions -> UU = family_difference(family_difference(F1, LU), XU), DefAt = make_defat(Undef, DefAt0), + US = family_union(family_intersection(Mod_US, X1_B), Lib_US), + US_1 = family_union(family_intersection(Mod_US_1, X1_B), Lib_US_1), + US_2 = family_union(family_intersection(Mod_US_2, X1_B), Lib_US_2), + + DC = family_union(family_intersection(Mod_DC, X1_B), Lib_DC), + DC_1 = family_union(family_intersection(Mod_DC_1, X1_B), Lib_DC_1), + DC_2 = family_union(family_intersection(Mod_DC_2, X1_B), Lib_DC_2), + LM = domain(Lib), UM = difference(difference(domain(U), AM), LM), X = family_union(X1, Lib), @@ -1339,14 +1536,19 @@ do_set_up(S) when S#xref.mode =:= functions -> {'AM',AM},{'UM',UM},{'LM',LM}, {'ME',ME},{'AE',AE},{'RE',RE}, {'DF',DF},{'DF_1',DF_1},{'DF_2',DF_2},{'DF_3',DF_3}, + {'DC', DC}, {'DC_1', DC_1}, {'DC_2', DC_2}, + {'US', US}, {'US_1', US_1}, {'US_2', US_2}, {me2ae, ME2AE},{ae, AE2RE},{m2a, M2A},{a2r, A2R}, {def_at, DefAt}, {call_at, CallAt}, {e_call_at, ECallAt}, {l_call_at, LCallAt}, {x_call_at, XCallAt}], finish_set_up(S1, Vs); do_set_up(S) when S#xref.mode =:= modules -> ModDictList = dict:to_list(S#xref.modules), - [X0, I0, Mod_DF, Mod_DF_1, Mod_DF_2, Mod_DF_3] = - make_families(ModDictList, 7), + [X0, I0, + Mod_DF, Mod_DF_1, Mod_DF_2, Mod_DF_3, + Mod_DC, Mod_DC_1, Mod_DC_2, + Mod_US, Mod_US_1, Mod_US_2] = + make_families(ModDictList, 13), I = union_of_family(I0), AM = domain(X0), @@ -1369,15 +1571,28 @@ do_set_up(S) when S#xref.mode =:= modules -> RE = range(AE2RE), %% Undef is the union of U0 and Lib: - {_Undef, U0, Lib, Lib_DF, Lib_DF_1, Lib_DF_2, Lib_DF_3} = - make_libs(XU, X1, AM, S#xref.library_path, S#xref.libraries), + {_Undef, U0, Lib, + Lib_DF, Lib_DF_1, Lib_DF_2, Lib_DF_3, + Lib_DC, Lib_DC_1, Lib_DC_2, + Lib_US, Lib_US_1, Lib_US_2} = + make_libs(XU, X1, AM, S#xref.library_path, S#xref.libraries), + {B, U} = make_builtins(U0), X1_B = family_union(X1, B), + DF = family_union(family_intersection(Mod_DF, X1_B), Lib_DF), DF_1 = family_union(family_intersection(Mod_DF_1, X1_B), Lib_DF_1), DF_2 = family_union(family_intersection(Mod_DF_2, X1_B), Lib_DF_2), DF_3 = family_union(family_intersection(Mod_DF_3, X1_B), Lib_DF_3), + DC = family_union(family_intersection(Mod_DC, X1_B), Lib_DC), + DC_1 = family_union(family_intersection(Mod_DC_1, X1_B), Lib_DC_1), + DC_2 = family_union(family_intersection(Mod_DC_2, X1_B), Lib_DC_2), + + US = family_union(family_intersection(Mod_US, X1_B), Lib_US), + US_1 = family_union(family_intersection(Mod_US_1, X1_B), Lib_US_1), + US_2 = family_union(family_intersection(Mod_US_2, X1_B), Lib_US_2), + LM = domain(Lib), UM = difference(difference(domain(U), AM), LM), X = family_union(X1, Lib), @@ -1389,6 +1604,8 @@ do_set_up(S) when S#xref.mode =:= modules -> {'AM',AM},{'UM',UM},{'LM',LM}, {'ME',ME},{'AE',AE},{'RE',RE}, {'DF',DF},{'DF_1',DF_1},{'DF_2',DF_2},{'DF_3',DF_3}, + {'DC', DC}, {'DC_1', DC_1}, {'DC_2', DC_2}, + {'US', US}, {'US_1', US_1}, {'US_2', US_2}, {me2ae, ME2AE},{ae, AE2RE},{m2a, M2A},{a2r, A2R}, {def_at, Empty}, {call_at, Empty}, {e_call_at, Empty}, {l_call_at, Empty}, {x_call_at, Empty}], @@ -1423,6 +1640,12 @@ var_type('DF') -> {function, vertex}; var_type('DF_1') -> {function, vertex}; var_type('DF_2') -> {function, vertex}; var_type('DF_3') -> {function, vertex}; +var_type('DC') -> {function, vertex}; +var_type('DC_1') -> {function, vertex}; +var_type('DC_2') -> {function, vertex}; +var_type('US') -> {function, vertex}; +var_type('US_1') -> {function, vertex}; +var_type('US_2') -> {function, vertex}; var_type('A') -> {application, vertex}; var_type('AM') -> {module, vertex}; var_type('LM') -> {module, vertex}; @@ -1523,30 +1746,55 @@ make_libs(XU, F, AM, LibPath, LibDict) -> end, map(MFun, to_external(Lb)) end, - Fun = fun(FileName, Deprs) -> - case beam_lib:chunks(FileName, [exports, attributes]) of - {ok, {M, [{exports,X}, {attributes,A}]}} -> - Exports = mfa_exports(X, A, M), - %% No warnings for bad attributes... - {Deprecated,_Bad} = deprecated(A, Exports, M), - {{M,Exports}, [{M,Deprecated} | Deprs]}; - Error -> - throw(Error) - end - end, - {XL, DL} = mapfoldl(Fun, [], Fs), + + {XL, DepL, DocL, UnsL} = collect_lib(Fs, [], [], [], []), + LF = from_term(XL), + %% Undef is the first argument to make sure that the whole of LF %% becomes garbage: Lib = family_intersection(Undef, LF), + U = family_difference(Undef, Lib), {B,_} = make_builtins(Undef), + DLib = family_union(Lib, B), - [DF_1,DF_21,DF_31,DF1] = depr_lib(4, DL, DL, [], [], DLib), + + [DC_1, DC_2] = depr_lib(2, DocL, DocL, [], [], DLib), + DC = family_union(DC_1, DC_2), + + [US_1, US_2] = depr_lib(2, UnsL, UnsL, [], [], DLib), + US = family_union(US_1, US_2), + + [DF_1, DF_21, DF_31, DF1] = depr_lib(4, DepL, DepL, [], [], DLib), DF_2 = family_union(DF_21, DF_1), DF_3 = family_union(DF_31, DF_2), DF = family_union(DF1, DF_3), - U = family_difference(Undef, Lib), - {Undef, U, Lib, DF, DF_1, DF_2, DF_3}. + + {Undef, U, Lib, + DF, DF_1, DF_2, DF_3, + DC, DC_1, DC_2, + US, US_1, US_2}. + +collect_lib([Name | Names], Exports, Deprecated, Documented, Unsafe) -> + case beam_lib:chunks(Name, + [exports, attributes, documentation], + [allow_missing_chunks]) of + {ok, {M, [{exports,X}, {attributes,A}, {documentation, Doc}]}} -> + Es = mfa_exports(X, A, M), + %% No warnings for bad attributes... + {Ds, _} = deprecated(A, Es, M), + {Us, _} = unsafe(A, Es, M), + Docs = documented(Doc, A, M), + collect_lib(Names, + [{M, Es} | Exports], + [{M, Ds} | Deprecated], + [{M, Docs} | Documented], + [{M, Us} | Unsafe]); + Error -> + throw(Error) + end; +collect_lib([], Exports, Deprecated, Documented, Unsafe) -> + {Exports, Deprecated, Documented, Unsafe}. depr_lib(0, _, _, LL, [], _Lib) -> LL; diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl index 1239740ef9af..4ea8be731418 100644 --- a/lib/tools/src/xref_reader.erl +++ b/lib/tools/src/xref_reader.erl @@ -22,7 +22,7 @@ -module(xref_reader). -moduledoc false. --export([module/5]). +-export([module/7]). -import(lists, [keysearch/3, member/2, reverse/1]). @@ -35,6 +35,8 @@ el=[], ex=[], x=[], + documented=[], + unsafe=[], df, builtins_too=false, is_abstr, % abstract module? @@ -60,11 +62,12 @@ %% Unresolved}} | EXIT %% Attrs = {ALC, AXC, Bad} %% ALC, AXC and Bad are extracted from the attribute 'xref'. An experiment. -module(Module, Forms, CollectBuiltins, X, DF) -> +module(Module, Forms, CollectBuiltins, X, Deprecated, Documented, Unsafe) -> Attrs = [{Attr,V} || {attribute,_Anno,Attr,V} <- Forms], IsAbstract = xref_utils:is_abstract_module(Attrs), S = #xrefr{module = Module, builtins_too = CollectBuiltins, - is_abstr = IsAbstract, x = X, df = DF}, + is_abstr = IsAbstract, x = X, df = Deprecated, + documented = Documented, unsafe = Unsafe}, forms(Forms, S). forms([F | Fs], S) -> @@ -73,15 +76,18 @@ forms([F | Fs], S) -> forms([], S) -> #xrefr{module = M, def_at = DefAt, l_call_at = LCallAt, x_call_at = XCallAt, - el = LC, ex = XC, x = X, df = Depr, on_load = OnLoad, - lattrs = AL, xattrs = AX, battrs = B, unresolved = U} = S, + el = LC, ex = XC, x = X, df = Deprecated, on_load = OnLoad, + lattrs = AL, xattrs = AX, battrs = B, unresolved = U, + documented = Documented, unsafe = Unsafe} = S, OL = case OnLoad of undefined -> []; F -> [{M, F, 0}] end, Attrs = {lists:reverse(AL), lists:reverse(AX), lists:reverse(B)}, - {ok, M, {DefAt, LCallAt, XCallAt, LC, XC, X, Attrs, Depr, OL}, U}. + Data = {DefAt, LCallAt, XCallAt, LC, XC, X, Attrs, Deprecated, OL, + Documented, Unsafe}, + {ok, M, Data, U}. form({attribute, Anno, xref, Calls}, S) -> % experimental #xrefr{module = M, function = Fun, diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl index 469c7b7dbd10..eba1fc104469 100644 --- a/lib/tools/src/xref_utils.erl +++ b/lib/tools/src/xref_utils.erl @@ -22,6 +22,8 @@ -module(xref_utils). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %% Avoid warning for local function error/1 clashing with autoimported BIF. -compile({no_auto_import,[error/1]}). -export([xset/2]). diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl index 1ee0dd15330b..6c6d922ca468 100644 --- a/lib/tools/test/xref_SUITE.erl +++ b/lib/tools/test/xref_SUITE.erl @@ -47,7 +47,7 @@ -export([add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1, replace/1, update/1, deprecated/1, trycatch/1, fun_mfa/1, - fun_mfa_vars/1, qlc/1]). + fun_mfa_vars/1, qlc/1, unsafe/1, documented/1]). -export([analyze/1, basic/1, md/1, q/1, variables/1, unused_locals/1, behaviour/1]). @@ -82,7 +82,7 @@ groups() -> {files, [], [add, default, info, lib, read, read2, remove, replace, update, deprecated, trycatch, fun_mfa, - fun_mfa_vars, qlc]}, + fun_mfa_vars, qlc, unsafe, documented]}, {analyses, [], [analyze, basic, md, q, variables, unused_locals, behaviour]}, @@ -1803,8 +1803,8 @@ analyze(Conf) when is_list(Conf) -> Xbeam = fname(EB2, "x.beam"), Ybeam = fname(EB1_1, "y.beam"), - {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), - {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), + {ok, x} = compile:file(X, [return_errors, debug_info, {outdir,EB2}]), + {ok, y} = compile:file(Y, [return_errors, debug_info, {outdir,EB1_1}]), {ok, rel2, S1} = xref_base:add_release(S0, Dir, [{verbose,false}]), S = set_up(S1), @@ -2532,6 +2532,224 @@ add_modules([{Mod, Test} |Tests], Conf) -> ok = file:delete(Beam), add_modules(Tests, Conf). +%% Unsafe functions. +unsafe(Conf) when is_list(Conf) -> + Dir = filename:join(?privdir, "unsafe"), + _ = file:make_dir(Dir), + + {ok, _} = xref:start(s), + + {ok,UF} = xref:analyze(s, unsafe_function_calls), + [] = U = to_external(range(from_term(UF))), + {ok, U} = xref:analyse(s, unsafe_function_calls), + + ok = check_state(s), + + Test1 = <<"-module(unsafe_1). + + -export([t/0,f/1,bar/2,f/2,g/3,string/0]). + + -unsafe([{f,'_'}]). % US_1 + + %% This is OK to call within the application, but not without. + -doc hidden. + t() -> + g(1,2, 3), + ?MODULE:f(10). + + f(A) -> + ?MODULE:f(A,A). + + f(X, Y) -> + ?MODULE:g(X, Y, X). + + g(F, G, H) -> + ?MODULE:bar(F, {G,H}). + + string() -> + ?MODULE:string(). + + bar(_, _) -> + ?MODULE:t(). + ">>, + + compile_helper([{"unsafe_1", Test1}], + Dir, + fun() -> + {ok, lib1} = xref:add_application(s, + Dir, + [{name, lib1}]) + end), + + MAlpha = unsafe_1, + USa = usort([{{MAlpha,f,1},{MAlpha,f,2}},{{MAlpha,t,0},{MAlpha,f,1}}]), + + {ok,USa} = xref:analyse(s, unsafe_function_calls), + {ok,[{MAlpha,f,1},{MAlpha,f,2}]} = xref:q(s, "US_1"), + + ok = check_state(s), + + %% All of the module is unsafe. + Test2 = <<"-module(unsafe_2). + + -export([t/0,f/1,bar/2,f/2,g/3]). + + -unsafe([{f,'_',possibly}]). % US_2 + -unsafe([{g,'_'}]). % US_1 + -unsafe(module). % US_1 + + t() -> + g(1,2, 3), + ?MODULE:f(10). + + f(A) -> + ?MODULE:f(A,A). + + f(X, Y) -> + ?MODULE:g(X, Y, X). + + g(F, G, H) -> + ?MODULE:bar(F, {G,H}). + + bar(_, _) -> + unsafe_1:t(). %% Cross-application edge to DC_2! + ">>, + + compile_helper([{"unsafe_2", Test2}], + Dir, + fun() -> + {ok, lib2} = xref:add_application(s, + Dir, + [{name, lib2}]) + end), + + MBeta = unsafe_2, + USb = usort(USa ++ + [%% Cross-application call to private function, which is not + %% marked unsafe on its own. + {{MBeta,bar,2},{MAlpha,t,0}}, + %% Unsafe calls within unsafe_2 + {{MBeta,f,1},{MBeta,f,2}}, + {{MBeta,f,2},{MBeta,g,3}}, + {{MBeta,g,3},{MBeta,bar,2}}, + {{MBeta,t,0},{MBeta,f,1}}]), + + {ok,USb} = xref:analyse(s, unsafe_function_calls), + + {ok,[{MBeta,f,1}, + {MBeta,f,2}]} = xref:q(s, "US_2"), + + {ok,[{MAlpha,f,1}, + {MAlpha,f,2}, + {MBeta,bar,2}, + {MBeta,f,1}, + {MBeta,f,2}, + {MBeta,g,3}, + {MBeta,t,0}]} = xref:q(s, "US_1"), + + ok = check_state(s), + xref:stop(s), + + ok. + +%% Un/documented functions. +documented(Conf) when is_list(Conf) -> + Dir = filename:join(?privdir, "documented"), + _ = file:make_dir(Dir), + + {ok, _} = xref:start(s), + + {ok,UF} = xref:q(s, "DC"), + [] = U = to_external(range(from_term(UF))), + {ok, U} = xref:q(s, "DC"), + + ok = check_state(s), + + Test1 = <<"-module(documented_1). + + -export([t/0,f/1,bar/2,f/2,g/3,string/0]). + + -doc hidden. % DC_2 + t() -> + g(1,2, 3), + ?MODULE:f(10). + + -doc \"present\". % DC_1 + f(A) -> + ?MODULE:f(A,A). + + -doc \"present\". % DC_1 + f(X, Y) -> + ?MODULE:g(X, Y, X). + + -doc \"present\". % DC_1 + g(F, G, H) -> + ?MODULE:bar(F, {G,H}). + + -doc \"present\". % DC_1 + string() -> + ?MODULE:string(). + + -doc #{ equiv => string/0 }. % DC_1 + equiv() -> + ?MODULE:string(). + + bar(_, _) -> % No annotation! + ?MODULE:t(). + ">>, + + Test2 = <<"-module(documented_2). + + -export([t/0, bar/2]). + + t() -> % No annotation! + documented_1:t(). + + bar(A, B) -> % No annotation! + documented_1:bar(A, B). + ">>, + + compile_helper([{"documented_1", Test1}], + Dir, + fun() -> + {ok, lib1} = xref:add_application(s, + Dir, + [{name, lib1}]) + end), + + compile_helper([{"documented_2", Test2}], + Dir, + fun() -> + {ok, lib2} = xref:add_application(s, + Dir, + [{name, lib2}]) + end), + + MAlpha = documented_1, + MBeta = documented_2, + + {ok,[{MAlpha,f,1}, + {MAlpha,f,2}, + {MAlpha,g,3}, + {MAlpha,string,0}]} = xref:q(s, "DC_1"), + {ok,[{MAlpha,t,0}]} = xref:q(s, "DC_2"), + {ok,[{MAlpha,bar,2}, + {MBeta,bar,2}, + {MBeta,t,0}]} = xref:q(s, "(X - DC_2) - DC_1"), + + %% Note that this does not include the call to documented_1:t/0 since that + %% is a _private function_, not an _undocumented_ one. + {ok,[{{MBeta,bar,2},{MAlpha,bar,2}}]} + = xref:analyse(s, undocumented_function_calls), + + {ok,[{{MBeta,t,0},{MAlpha,t,0}}]} = + xref:analyse(s, private_function_calls), + + ok = check_state(s), + xref:stop(s), + + ok. + %%% %%% Utilities %%% @@ -2608,7 +2826,9 @@ add_module(S, XMod, DefAt, X, LCallAt, XCallAt, XC, LC) -> DBad = [], Depr = {Depr0,DBad}, OL = [], - Data = {DefAt, LCallAt, XCallAt, LC, XC, X, Attr, Depr, OL}, + Doc = {[], []}, + US = {{[], []}, []}, + Data = {DefAt, LCallAt, XCallAt, LC, XC, X, Attr, Depr, OL, Doc, US}, Unres = [], {ok, _Module, _Bad, State} = xref_base:do_add_module(S, XMod, Unres, Data), @@ -2866,3 +3086,22 @@ add_erts_code_path(KernelPath) -> _Other1 -> [KernelPath] end. + +compile_helper([{Name, Source} | Rest], Dir, Fun) -> + File = fname(Dir, Name ++ ".erl"), + Beam = fname(Dir, Name ++ ".beam"), + + ok = file:write_file(File, Source), + {ok, _} = compile:file(File, + [return_errors, + debug_info, + {outdir,Dir}]), + + try + compile_helper(Rest, Dir, Fun) + after + file:delete(File), + file:delete(Beam) + end; +compile_helper([], _Dir, Fun) -> + Fun(). diff --git a/lib/wx/src/wx.erl b/lib/wx/src/wx.erl index 0dfa97803e00..0860e83e7b6f 100644 --- a/lib/wx/src/wx.erl +++ b/lib/wx/src/wx.erl @@ -179,6 +179,8 @@ Global (classless) functions are located in the wx_misc module. See #wxMouseState\{\} defined in wx.hrl """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([parent_class/1, new/0, new/1, destroy/0, get_env/0, set_env/1, subscribe_events/0, debug/1, batch/1,foreach/2,map/2,foldl/3,foldr/3, diff --git a/lib/xmerl/src/xmerl_lib.erl b/lib/xmerl/src/xmerl_lib.erl index 3cc59614ecd1..6e004b2cee4d 100644 --- a/lib/xmerl/src/xmerl_lib.erl +++ b/lib/xmerl/src/xmerl_lib.erl @@ -26,6 +26,8 @@ -module(xmerl_lib). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([normalize_content/1, normalize_content/3, expand_content/1, expand_content/3, normalize_element/1, normalize_element/3, expand_element/1, expand_element/3, expand_attributes/1, diff --git a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc index 1211cea72bfb..6d06fdf26a18 100644 --- a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc +++ b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc @@ -23,6 +23,8 @@ %%---------------------------------------------------------------------- %-compile(export_all). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%---------------------------------------------------------------------- %% Include files %%---------------------------------------------------------------------- diff --git a/lib/xmerl/src/xmerl_sax_parser_latin1.erlsrc b/lib/xmerl/src/xmerl_sax_parser_latin1.erlsrc index 0acb0caab3d1..9cccb0eab359 100644 --- a/lib/xmerl/src/xmerl_sax_parser_latin1.erlsrc +++ b/lib/xmerl/src/xmerl_sax_parser_latin1.erlsrc @@ -28,6 +28,8 @@ -module(xmerl_sax_parser_latin1). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%---------------------------------------------------------------------- %% Macros %%---------------------------------------------------------------------- diff --git a/lib/xmerl/src/xmerl_sax_parser_list.erlsrc b/lib/xmerl/src/xmerl_sax_parser_list.erlsrc index 507ef3ace8fe..e32b05ee5296 100644 --- a/lib/xmerl/src/xmerl_sax_parser_list.erlsrc +++ b/lib/xmerl/src/xmerl_sax_parser_list.erlsrc @@ -28,6 +28,8 @@ -module(xmerl_sax_parser_list). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%---------------------------------------------------------------------- %% Macros %%---------------------------------------------------------------------- diff --git a/lib/xmerl/src/xmerl_sax_parser_utf16be.erlsrc b/lib/xmerl/src/xmerl_sax_parser_utf16be.erlsrc index 91c0459dd6cf..41f8b1426f7d 100644 --- a/lib/xmerl/src/xmerl_sax_parser_utf16be.erlsrc +++ b/lib/xmerl/src/xmerl_sax_parser_utf16be.erlsrc @@ -28,6 +28,8 @@ -module(xmerl_sax_parser_utf16be). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%---------------------------------------------------------------------- %% Macros %%---------------------------------------------------------------------- diff --git a/lib/xmerl/src/xmerl_sax_parser_utf16le.erlsrc b/lib/xmerl/src/xmerl_sax_parser_utf16le.erlsrc index 8a66576d4980..9f7800c84a0a 100644 --- a/lib/xmerl/src/xmerl_sax_parser_utf16le.erlsrc +++ b/lib/xmerl/src/xmerl_sax_parser_utf16le.erlsrc @@ -28,6 +28,8 @@ -module(xmerl_sax_parser_utf16le). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%---------------------------------------------------------------------- %% Macros %%---------------------------------------------------------------------- diff --git a/lib/xmerl/src/xmerl_sax_parser_utf8.erlsrc b/lib/xmerl/src/xmerl_sax_parser_utf8.erlsrc index a5d646c6250b..af891a39359d 100644 --- a/lib/xmerl/src/xmerl_sax_parser_utf8.erlsrc +++ b/lib/xmerl/src/xmerl_sax_parser_utf8.erlsrc @@ -28,6 +28,8 @@ -module(xmerl_sax_parser_utf8). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%---------------------------------------------------------------------- %% Macros %%---------------------------------------------------------------------- diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl index 57e78fbe2567..4bd0e4293239 100644 --- a/lib/xmerl/src/xmerl_scan.erl +++ b/lib/xmerl/src/xmerl_scan.erl @@ -36,6 +36,12 @@ See also the -vsn('0.20'). -date('03-09-16'). +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + +-unsafe([{'_', '_', + "this module cannot be used with untrusted input, use " + "xmerl_sax_parser instead"}]). + %% main API -export([string/1, string/2, file/1, file/2]). diff --git a/lib/xmerl/src/xmerl_uri.erl b/lib/xmerl/src/xmerl_uri.erl index c896c5abebfa..ebd3ec798c0d 100644 --- a/lib/xmerl/src/xmerl_uri.erl +++ b/lib/xmerl/src/xmerl_uri.erl @@ -24,6 +24,7 @@ -module(xmerl_uri). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). -export([parse/1,resolve/2 % scan_abspath/1 diff --git a/lib/xmerl/src/xmerl_validate.erl b/lib/xmerl/src/xmerl_validate.erl index 799c232e723e..9693f119ee4b 100644 --- a/lib/xmerl/src/xmerl_validate.erl +++ b/lib/xmerl/src/xmerl_validate.erl @@ -23,6 +23,8 @@ -module(xmerl_validate). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([validate/2]). diff --git a/lib/xmerl/src/xmerl_xpath.erl b/lib/xmerl/src/xmerl_xpath.erl index a978f76ef479..c137d70819f3 100644 --- a/lib/xmerl/src/xmerl_xpath.erl +++ b/lib/xmerl/src/xmerl_xpath.erl @@ -48,6 +48,7 @@ Some useful shell commands for debugging the XPath parser ``` """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). %% main API -export([string/2, diff --git a/lib/xmerl/src/xmerl_xpath_scan.erl b/lib/xmerl/src/xmerl_xpath_scan.erl index 52b7d30a24d9..121fbdc786c5 100644 --- a/lib/xmerl/src/xmerl_xpath_scan.erl +++ b/lib/xmerl/src/xmerl_xpath_scan.erl @@ -49,6 +49,7 @@ -module(xmerl_xpath_scan). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). %% main API -export([tokens/1]). diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl index 5ef45df4bef4..ae6ec4d9c33f 100644 --- a/lib/xmerl/src/xmerl_xsd.erl +++ b/lib/xmerl/src/xmerl_xsd.erl @@ -31,6 +31,8 @@ XML Schema please study [part 0](http://www.w3.org/TR/xmlschema-0/). An XML structure is validated by [`xmerl_xsd:validate/[2,3]`](`validate/2`). """. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + %%---------------------------------------------------------------------- %% Include files %%---------------------------------------------------------------------- diff --git a/lib/xmerl/src/xmerl_xsd_re.erl b/lib/xmerl/src/xmerl_xsd_re.erl index e4c56c94f1d4..2e48188db89a 100644 --- a/lib/xmerl/src/xmerl_xsd_re.erl +++ b/lib/xmerl/src/xmerl_xsd_re.erl @@ -23,6 +23,8 @@ -module(xmerl_xsd_re). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([map/1]). %% api -export([scan/1]). %% test diff --git a/lib/xmerl/src/xmerl_xsd_type.erl b/lib/xmerl/src/xmerl_xsd_type.erl index a396da20f055..28ca47fda9a0 100644 --- a/lib/xmerl/src/xmerl_xsd_type.erl +++ b/lib/xmerl/src/xmerl_xsd_type.erl @@ -23,6 +23,8 @@ -module(xmerl_xsd_type). -moduledoc false. +-compile([{nowarn_unsafe_function, {erlang, list_to_atom, 1}}]). + -export([check_simpleType/3,facet_fun/2,compare_floats/2, replace_ws/2,collapse_ws/1]). diff --git a/system/doc/general_info/DEPRECATIONS b/system/doc/general_info/DEPRECATIONS index 111123d21fb1..9f1ea80995e9 100644 --- a/system/doc/general_info/DEPRECATIONS +++ b/system/doc/general_info/DEPRECATIONS @@ -36,6 +36,31 @@ # is scheduled to be removed in OTP 25. # +# +# Added in OTP 29. +# +crypto:private_decrypt/4 unsafe=29 +crypto:private_encrypt/4 unsafe=29 +crypto:public_decrypt/4 unsafe=29 +crypto:public_encrypt/4 unsafe=29 +erlang:binary_to_atom/_ unsafe=29 +erlang:binary_to_term/_ unsafe=29 +erlang:list_to_atom/1 unsafe=29 +file:consult/_ unsafe=29 +file:path_consult/_ unsafe=29 +http_uri:_/_ unsafe=29 +os:cmd/_ unsafe=29 +public_key:decrypt_private/2 unsafe=29 +public_key:decrypt_public/2 unsafe=29 +public_key:encrypt_private/2 unsafe=29 +public_key:encrypt_public/2 unsafe=29 + +## Possibly unsafe +public_key:decrypt_private/3 unsafe=29 +public_key:decrypt_public/3 unsafe=29 +public_key:encrypt_private/3 unsafe=29 +public_key:encrypt_public/3 unsafe=29 + # # Added in OTP 28. # @@ -48,7 +73,7 @@ crypto:enable_fips_mode/1 since=28 # mnesia_registry:create_table/_ since=27 remove=29 code:lib_dir/2 since=27 -ssl:prf/5 since=27 +ssl:prf/5 since=27 unsafe=29 ssl:prf_random/0 since=27 remove=28 #