From 1ddab9c7b66237ea6dd429fb75e4c81247d88920 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?=
Date: Mon, 25 Jan 2016 13:12:50 +0100
Subject: Eliminate run-time system crash in code:load_abs/1
The run-time system would terminate if code:load_abs/1 was
called with a filename containing any non-latin1 characters.
The reason is that code_server would attempt to construct a
module name from the filename using list_to_atom/1 and that
atoms currently are limited to the latin1 character set.
But how should the error be reported?
I have decided to that the simplest and least confusing way
is to move the call to list_to_atom/1 to 'code' module and
let it crash the calling process. The resulting stack back
trace will make it clear what the reason for the crash was.
---
lib/kernel/src/code.erl | 4 +++-
lib/kernel/src/code_server.erl | 9 ++-------
lib/kernel/test/code_SUITE.erl | 1 +
3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 352c02562b..7d0102d4ef 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -142,7 +142,9 @@ ensure_loaded(Mod) when is_atom(Mod) ->
%% XXX File as an atom is allowed only for backwards compatibility.
-spec load_abs(Filename) -> load_ret() when
Filename :: file:filename().
-load_abs(File) when is_list(File); is_atom(File) -> call({load_abs,File,[]}).
+load_abs(File) when is_list(File); is_atom(File) ->
+ Mod = list_to_atom(filename:basename(File)),
+ call({load_abs,File,Mod}).
%% XXX Filename is also an atom(), e.g. 'cover_compiled'
-spec load_abs(Filename :: loaded_filename(), Module :: module()) -> load_ret().
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index e461c95d19..614219794c 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -313,7 +313,7 @@ handle_call(get_path, {_From,_Tag}, S) ->
{reply,S#state.path,S};
%% Messages to load, delete and purge modules/files.
-handle_call({load_abs,File,Mod}, Caller, S) ->
+handle_call({load_abs,File,Mod}, Caller, S) when is_atom(Mod) ->
case modp(File) of
false ->
{reply,{error,badarg},S};
@@ -1222,15 +1222,10 @@ modp(Atom) when is_atom(Atom) -> true;
modp(List) when is_list(List) -> int_list(List);
modp(_) -> false.
-load_abs(File, Mod0, Caller, St) ->
+load_abs(File, Mod, Caller, St) ->
Ext = objfile_extension(),
FileName0 = lists:concat([File, Ext]),
FileName = absname(FileName0),
- Mod = if Mod0 =:= [] ->
- list_to_atom(filename:basename(FileName0, Ext));
- true ->
- Mod0
- end,
case erl_prim_loader:get_file(FileName) of
{ok,Bin,_} ->
try_load_module(FileName, Mod, Bin, Caller, St);
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index ef5303defd..8f97b6c6f8 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -323,6 +323,7 @@ load_abs(Config) when is_list(Config) ->
{error, nofile} = code:load_abs(TestDir ++ "/duuuumy_mod"),
{error, badfile} = code:load_abs(TestDir ++ "/code_a_test"),
{'EXIT', _} = (catch code:load_abs({})),
+ {'EXIT', _} = (catch code:load_abs("Non-latin-имя-файла")),
{module, code_b_test} = code:load_abs(TestDir ++ "/code_b_test"),
code:stick_dir(TestDir),
{error, sticky_directory} = code:load_abs(TestDir ++ "/code_b_test"),
--
cgit v1.2.3
From 28f7a47ab4d533cc72090484eb3a7e5713fa58bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?=
Date: Mon, 25 Jan 2016 15:56:59 +0100
Subject: code: Correct the types for error returns
The specifications for functions that load code in the 'code'
module (e.g. code:load_file/1) have some problems:
* The specs claim that the functions can return {error,on_load}, but
they never do. However, they can return {error,on_load_failure} if
the -on_load function in a module fails.
* The specs claim that the functions can return {error,native_code},
but they never do.
While we are it, also extend the on_load_errors/1 test case to test
that the load functions return {error,on_load_failure} when an
-on_load function fails.
---
lib/kernel/src/code.erl | 5 ++---
lib/kernel/test/code_SUITE.erl | 11 +++++++++++
.../code_SUITE_data/on_load_errors/simple_on_load_error.erl | 5 +++++
3 files changed, 18 insertions(+), 3 deletions(-)
create mode 100644 lib/kernel/test/code_SUITE_data/on_load_errors/simple_on_load_error.erl
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 7d0102d4ef..7237550786 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -77,10 +77,9 @@
%%----------------------------------------------------------------------------
-type load_error_rsn() :: 'badfile'
- | 'native_code'
| 'nofile'
| 'not_purged'
- | 'on_load'
+ | 'on_load_failure'
| 'sticky_directory'.
-type load_ret() :: {'error', What :: load_error_rsn()}
| {'module', Module :: module()}.
@@ -135,7 +134,7 @@ load_file(Mod) when is_atom(Mod) ->
-spec ensure_loaded(Module) -> {module, Module} | {error, What} when
Module :: module(),
- What :: embedded | badfile | native_code | nofile | on_load.
+ What :: embedded | badfile | nofile | on_load_failure.
ensure_loaded(Mod) when is_atom(Mod) ->
call({ensure_loaded,Mod}).
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 8f97b6c6f8..2b77ec8972 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -1600,6 +1600,17 @@ on_load_errors(Config) when is_list(Config) ->
ok
end,
+ %% Make sure that the code loading functions return the correct
+ %% error code.
+ Simple = simple_on_load_error,
+ SimpleList = atom_to_list(Simple),
+ {error,on_load_failure} = code:load_file(Simple),
+ {error,on_load_failure} = code:ensure_loaded(Simple),
+ {ok,SimpleCode} = file:read_file("simple_on_load_error.beam"),
+ {error,on_load_failure} = code:load_binary(Simple, "", SimpleCode),
+ {error,on_load_failure} = code:load_abs(SimpleList),
+ {error,on_load_failure} = code:load_abs(SimpleList, Simple),
+
ok.
do_on_load_error(ReturnValue) ->
diff --git a/lib/kernel/test/code_SUITE_data/on_load_errors/simple_on_load_error.erl b/lib/kernel/test/code_SUITE_data/on_load_errors/simple_on_load_error.erl
new file mode 100644
index 0000000000..603c282257
--- /dev/null
+++ b/lib/kernel/test/code_SUITE_data/on_load_errors/simple_on_load_error.erl
@@ -0,0 +1,5 @@
+-module(simple_on_load_error).
+-on_load(on_load/0).
+
+on_load() ->
+ nope.
--
cgit v1.2.3
From fbfe12dad837300942fc4bf0a3f927b25eaf50a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?=
Date: Tue, 26 Jan 2016 08:11:00 +0100
Subject: Update documentation for code-loading functions
Some of the error reasons were not explained.
---
lib/kernel/doc/src/code.xml | 61 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 47 insertions(+), 14 deletions(-)
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index eb0f4b7a06..1bd52040a0 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -287,6 +287,46 @@
was given to set_path/1).
+
+
+ Error Reasons for Code-Loading Functions
+
+ Functions that load code (such as load_file/1) will
+ return {error,Reason} if the load operation fails.
+ Here follows a description of the common reasons.
+
+
+ badfile
+ -
+
The object code has an incorrect format or the module
+ name in the object code is not the expected module name.
+
+
+ nofile
+ -
+
No file with object code was found.
+
+
+ not_purged
+ -
+
The object code could not be loaded because an old version
+ of the code already existed.
+
+
+ on_load_failure
+ -
+
The module has an
+ -on_load function
+ that failed when it was called.
+
+
+ sticky_directory
+ -
+
The object code resides in a sticky directory.
+
+
+
+
@@ -411,12 +451,8 @@
be used to load object code with a module name that is
different from the file name.
Returns {module, Module} if successful, or
- {error, nofile} if no object code is found, or
- {error, sticky_directory} if the object code resides in
- a sticky directory. Also if the loading fails, an error tuple is
- returned. See
- erlang:load_module/2
- for possible values of What.
+ {error, Reason} if loading fails.
+ See Error Reasons for Code-Loading Functions for a description of the possible error reasons.
@@ -428,7 +464,7 @@
Does the same as load_file(Module), but
Filename is either an absolute file name, or a
- relative file name. The code path is not searched. It returns
+ relative file name. The code path is not searched. It returns
a value in the same way as
load_file/1. Note
that Filename should not contain the extension (for
@@ -444,7 +480,8 @@
load_file/1,
unless the module is already loaded.
In embedded mode, however, it does not load a module which is not
- already loaded, but returns {error, embedded} instead.
+ already loaded, but returns {error, embedded} instead.
+ See Error Reasons for Code-Loading Functions for a description of other possible error reasons.
@@ -461,12 +498,8 @@
comes. Accordingly, Filename is not opened and read by
the code server.
Returns {module, Module} if successful, or
- {error, sticky_directory} if the object code resides in
- a sticky directory, or {error, badarg} if any argument
- is invalid. Also if the loading fails, an error tuple is
- returned. See
- erlang:load_module/2
- for possible values of What.
+ {error, Reason} if loading fails.
+ See Error Reasons for Code-Loading Functions for a description of the possible error reasons.
--
cgit v1.2.3