summaryrefslogtreecommitdiff
path: root/erts
diff options
context:
space:
mode:
authorJohn Högberg <john@erlang.org>2020-03-26 15:57:55 +0100
committerJohn Högberg <john@erlang.org>2020-03-26 17:11:54 +0100
commit0f0f62de4ebaec00006be70c6d7e700801e77b76 (patch)
treea44ac80cad17c22f74d888e92f76904486988624 /erts
parent851a440f5ea208e3a066402b87c734f001a490ec (diff)
downloaderlang-0f0f62de4ebaec00006be70c6d7e700801e77b76.tar.gz
erts: Fix external fun application of erlang:apply/3
Fun = fun erlang:apply/3, ... snip ... Fun(erlang, self, []). Code like the above would always crash because the CIF was just a stub that threw `badarg`, and the actual implementation in the `erlang` module was overwritten after an apply/3-specific loader hack was removed when refactoring CIF tracing. Since the CIF was only used for its MFA in an error handling macro, it's better to declare the MFA in said macro and skip the CIF altogether.
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/bif.c21
-rw-r--r--erts/emulator/beam/bif.tab1
-rw-r--r--erts/emulator/beam/instrs.tab3
-rw-r--r--erts/emulator/beam/ops.tab6
-rw-r--r--erts/emulator/test/bif_SUITE.erl18
5 files changed, 19 insertions, 30 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index ef2a1bce81..5beab81b98 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2358,27 +2358,6 @@ done:
}
/**********************************************************************/
-/*
- * apply/3 is implemented as an instruction and as erlang code in the
- * erlang module.
- *
- * There is only one reason that apply/3 is included in the BIF table:
- * The error handling code in the beam emulator passes the pointer to
- * this function to the error handling code if the apply instruction
- * fails. The error handling use the function pointer to lookup
- * erlang:apply/3 in the BIF table.
- *
- * This function will never be called. (It could be if init did something
- * like this: apply(erlang, apply, [M, F, A]). Not recommended.)
- */
-
-BIF_RETTYPE apply_3(BIF_ALIST_3)
-{
- BIF_ERROR(BIF_P, BADARG);
-}
-
-
-/**********************************************************************/
/* integer to float */
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 5d60a0f140..5fb8441a15 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -46,7 +46,6 @@ ubif erlang:abs/1
bif erlang:adler32/1
bif erlang:adler32/2
bif erlang:adler32_combine/3
-bif erlang:apply/3
bif erlang:atom_to_list/1
bif erlang:binary_to_list/1
bif erlang:binary_to_list/3
diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab
index d36f871ab5..697c777825 100644
--- a/erts/emulator/beam/instrs.tab
+++ b/erts/emulator/beam/instrs.tab
@@ -237,7 +237,8 @@ APPLY(I, Deallocate, Next) {
}
HANDLE_APPLY_ERROR() {
- I = handle_error(c_p, I, reg, &bif_trap_export[BIF_apply_3].info.mfa);
+ static ErtsCodeMFA apply3_mfa = {am_erlang, am_apply, 3};
+ I = handle_error(c_p, I, reg, &apply3_mfa);
goto post_error_handling;
}
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 70602c6798..686299b366 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -827,9 +827,9 @@ call_ext_only u==2 u$func:erlang:apply/2 => i_apply_fun_only
# The apply/3 BIF is an instruction.
#
-call_ext u==3 u$bif:erlang:apply/3 => i_apply
-call_ext_last u==3 u$bif:erlang:apply/3 D => i_apply_last D
-call_ext_only u==3 u$bif:erlang:apply/3 => i_apply_only
+call_ext u==3 u$func:erlang:apply/3 => i_apply
+call_ext_last u==3 u$func:erlang:apply/3 D => i_apply_last D
+call_ext_only u==3 u$func:erlang:apply/3 => i_apply_only
#
# The yield/0 BIF is an instruction
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl
index af27d4d4a9..a5f2e70d71 100644
--- a/erts/emulator/test/bif_SUITE.erl
+++ b/erts/emulator/test/bif_SUITE.erl
@@ -39,7 +39,8 @@
process_info_blast/1,
os_env_case_sensitivity/1,
test_length/1,
- fixed_apply_badarg/1]).
+ fixed_apply_badarg/1,
+ external_fun_apply3/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -55,7 +56,7 @@ all() ->
error_stacktrace, error_stacktrace_during_call_trace,
group_leader_prio, group_leader_prio_dirty,
is_process_alive, process_info_blast, os_env_case_sensitivity,
- test_length,fixed_apply_badarg].
+ test_length,fixed_apply_badarg,external_fun_apply3].
%% Uses erlang:display to test that erts_printf does not do deep recursion
display(Config) when is_list(Config) ->
@@ -353,8 +354,6 @@ auto_imports([], Errors) ->
extract_functions(M, Abstr) ->
[{{M,F,A},Body} || {function,_,F,A,Body} <- Abstr].
-check_stub({erlang,apply,3}, _) ->
- ok;
check_stub({_,F,A}, B) ->
try
[{clause,_,Args,[],Body}] = B,
@@ -1317,6 +1316,17 @@ fixed_apply_badarg(Config) when is_list(Config) ->
ok.
+external_fun_apply3(_Config) ->
+ %% erlang:apply/3 would always badarg when called through an external fun.
+
+ Apply = id(fun erlang:apply/3),
+ Self = Apply(erlang, self, []),
+ true = is_pid(Self),
+
+ {'EXIT',{undef,_}} = (catch Apply(does, 'not', [exist])),
+
+ ok.
+
%% helpers
id(I) -> I.