From f0cfce64b6a061ffeafeda254734f0b1f2f452fd Mon Sep 17 00:00:00 2001
From: Steve Vinoski
Date: Sun, 1 Mar 2015 12:33:20 -0500
Subject: Ensure NIF term creation disallows illegal values
Add a check to enif_make_double to see if its double argument is
infinity or NaN, returning a badarg exception if it is. Change the
erl_nif documentation to specify that enif_make_double returns a
badarg exception if its double argument is either infinity or NaN. Add
tests to nif_SUITE for this change.
Add checks to the enif_make* functions for atoms to prevent the
creation of atoms whose name lengths are greater than the allowed
maximum atom length. The enif_make_atom and enif_make_atom_len
functions now return a badarg exception if the input string is too
long. The enif_make_existing_atom and enif_make_existing_atom_len
functions return false if the input string is too long. Change the
erl_nif documentation to reflect the changes to these functions. Add
tests to nif_SUITE for these changes.
Add a field to ErlNifEnv to track that a NIF has raised an exception
via enif_make_badarg. If a NIF calls enif_make_badarg but then ignores
its return value and instead tries to return a non-exception term as
its return value, the runtime still raises a badarg. This is needed to
prevent enif_make_badarg values resulting from calls to
enif_make_double, enif_make_atom, or enif_make_atom_len from being
erroneously stored within other terms and returned from a NIF. Calling
enif_make_badarg but not returning its return value has been
documented as being illegal ever since enif_make_badarg was added, but
the runtime has not enforced it until now. Add tests for regular and
dirty NIFs to ensure that calls to enif_make_badarg result in badarg
exceptions even if a NIF fails to return the result of
enif_make_badarg as its return value. Add documentation to
enif_make_badarg to specify that calling it raises a badarg even if a
NIF ignores its return value.
---
erts/doc/src/erl_nif.xml | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
(limited to 'erts/doc')
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 3de94be9ff..feba6daaa0 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -898,12 +898,14 @@ typedef enum {
ERL_NIF_TERMenif_make_atom(ErlNifEnv* env, const char* name)
Create an atom term
Create an atom term from the null-terminated C-string name
- with iso-latin-1 encoding.
+ with iso-latin-1 encoding. If the length of name exceeds the maximum length
+ allowed for an atom, enif_make_atom returns a badarg exception.
ERL_NIF_TERMenif_make_atom_len(ErlNifEnv* env, const char* name, size_t len)
Create an atom term
Create an atom term from the string name with length len.
- Null-characters are treated as any other characters.
+ Null-characters are treated as any other characters. If len is greater than the maximum length
+ allowed for an atom, enif_make_atom returns a badarg exception.
ERL_NIF_TERMenif_make_badarg(ErlNifEnv* env)
Make a badarg exception.
@@ -911,8 +913,10 @@ typedef enum {
an associated exception reason in env. If
enif_make_badarg is called, the term it returns must
be returned from the function that called it. No other return value
- is allowed. Also, the term returned from enif_make_badarg may
- be passed only to
+ is allowed. Once a NIF or any function it calls invokes enif_make_badarg,
+ the runtime ensures that a badarg exception is raised when the NIF
+ returns, even if the NIF attempts to return a non-exception term instead.
+ Also, the term returned from enif_make_badarg may be passed only to
enif_is_exception and
not to any other NIF API function.
@@ -931,7 +935,9 @@ typedef enum {
ERL_NIF_TERMenif_make_double(ErlNifEnv* env, double d)
Create a floating-point term
- Create a floating-point term from a double.
+ Create a floating-point term from a double. If the double argument is
+ not finite or is NaN, enif_make_double returns a badarg exception.
+
intenif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding encode)
Create an existing atom term
@@ -939,7 +945,8 @@ typedef enum {
the null-terminated C-string name with encoding
encode. If the atom
already exists store the term in *atom and return true, otherwise
- return false.
+ return false. If the length of name exceeds the maximum length
+ allowed for an atom, enif_make_existing_atom returns false.
intenif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding encoding)
Create an existing atom term
@@ -947,7 +954,9 @@ typedef enum {
string name with length len and encoding
encode. Null-characters
are treated as any other characters. If the atom already exists store the term
- in *atom and return true, otherwise return false.
+ in *atom and return true, otherwise return false. If len is greater
+ than the maximum length allowed for an atom, enif_make_existing_atom_len
+ returns false.
ERL_NIF_TERMenif_make_int(ErlNifEnv* env, int i)
Create an integer term
--
cgit v1.2.3
From 9f903f6031ff40e415c8807aca19f699d0b553f1 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Mon, 13 Apr 2015 18:30:18 +0200
Subject: erts: Clearify erl_nif documentation about badarg exception
Also state that maximum atom length is 255 characters.
---
erts/doc/src/erl_nif.xml | 44 +++++++++++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 17 deletions(-)
(limited to 'erts/doc')
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index feba6daaa0..afeec69f02 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -899,26 +899,34 @@ typedef enum {
Create an atom term
Create an atom term from the null-terminated C-string name
with iso-latin-1 encoding. If the length of name exceeds the maximum length
- allowed for an atom, enif_make_atom returns a badarg exception.
+ allowed for an atom (255 characters), enif_make_atom invokes
+ enif_make_badarg.
+
ERL_NIF_TERMenif_make_atom_len(ErlNifEnv* env, const char* name, size_t len)
Create an atom term
Create an atom term from the string name with length len.
Null-characters are treated as any other characters. If len is greater than the maximum length
- allowed for an atom, enif_make_atom returns a badarg exception.
+ allowed for an atom (255 characters), enif_make_atom invokes
+ enif_make_badarg.
+
ERL_NIF_TERMenif_make_badarg(ErlNifEnv* env)
Make a badarg exception.
- Make a badarg exception to be returned from a NIF, and set
- an associated exception reason in env. If
- enif_make_badarg is called, the term it returns must
- be returned from the function that called it. No other return value
- is allowed. Once a NIF or any function it calls invokes enif_make_badarg,
- the runtime ensures that a badarg exception is raised when the NIF
- returns, even if the NIF attempts to return a non-exception term instead.
- Also, the term returned from enif_make_badarg may be passed only to
- enif_is_exception and
- not to any other NIF API function.
+ Make a badarg exception to be returned from a NIF, and associate
+ it with the environment env. Once a NIF or any function
+ it calls invokes enif_make_badarg, the runtime ensures that a
+ badarg exception is raised when the NIF returns, even if the NIF
+ attempts to return a non-exception term instead.
+ The return value from enif_make_badarg may only be used as
+ return value from the NIF that invoked it (direct or indirectly)
+ or be passed to
+ enif_is_exception, but
+ not to any other NIF API function.
+ In earlier versions (older than erts-7.0, OTP 18) the return value
+ from enif_make_badarg had to be returned from the NIF. This
+ requirement is now lifted as the return value from the NIF is ignored
+ if enif_make_badarg has been invoked.
ERL_NIF_TERMenif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)
Make a binary term.
@@ -936,8 +944,9 @@ typedef enum {
ERL_NIF_TERMenif_make_double(ErlNifEnv* env, double d)
Create a floating-point term
Create a floating-point term from a double. If the double argument is
- not finite or is NaN, enif_make_double returns a badarg exception.
-
+ not finite or is NaN, enif_make_double invokes
+ enif_make_badarg.
+
intenif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding encode)
Create an existing atom term
@@ -946,7 +955,8 @@ typedef enum {
encode. If the atom
already exists store the term in *atom and return true, otherwise
return false. If the length of name exceeds the maximum length
- allowed for an atom, enif_make_existing_atom returns false.
+ allowed for an atom (255 characters), enif_make_existing_atom
+ returns false.
intenif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding encoding)
Create an existing atom term
@@ -955,8 +965,8 @@ typedef enum {
encode. Null-characters
are treated as any other characters. If the atom already exists store the term
in *atom and return true, otherwise return false. If len is greater
- than the maximum length allowed for an atom, enif_make_existing_atom_len
- returns false.
+ than the maximum length allowed for an atom (255 characters),
+ enif_make_existing_atom_len returns false.
ERL_NIF_TERMenif_make_int(ErlNifEnv* env, int i)
Create an integer term
--
cgit v1.2.3
From 80e15112a6e31e053ad0670096c23bda2fc341e4 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Tue, 14 Apr 2015 15:18:33 +0200
Subject: erts: Add enif_has_pending_exception
---
erts/doc/src/erl_nif.xml | 8 ++++++++
1 file changed, 8 insertions(+)
(limited to 'erts/doc')
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index afeec69f02..5c912e0fe3 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -806,6 +806,12 @@ typedef enum {
and return true, or return false if term is not an unsigned integer or is
outside the bounds of type unsigned long.
+ intenif_has_pending_exception(ErlNifEnv* env)
+ Check if an exception has been raised.
+ Return true if a pending exception is associated
+ with the environment env. The only possible exception is currently
+ badarg (see enif_make_badarg).
+
intenif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin)
Inspect the content of a binary
Initialize the structure pointed to by bin with
@@ -923,6 +929,8 @@ typedef enum {
or be passed to
enif_is_exception, but
not to any other NIF API function.
+ See also: enif_has_pending_exception.
+
In earlier versions (older than erts-7.0, OTP 18) the return value
from enif_make_badarg had to be returned from the NIF. This
requirement is now lifted as the return value from the NIF is ignored
--
cgit v1.2.3
From 308b03e8afa14e03973330942e7aacf0cc925bf2 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Tue, 14 Apr 2015 15:43:40 +0200
Subject: erts: Remove old docs about experimental NIF versions.
---
erts/doc/src/erl_nif.xml | 28 ----------------------------
1 file changed, 28 deletions(-)
(limited to 'erts/doc')
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 5c912e0fe3..4bad8b253c 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -66,34 +66,6 @@
- The NIF concept is officially supported from R14B. NIF source code
- written for earlier experimental versions might need adaption to run on R14B
- or later versions:
-
- - No incompatible changes between R14B and R14A.
- - Incompatible changes between R14A and R13B04:
-
- - Environment argument removed for enif_alloc,
- enif_realloc, enif_free, enif_alloc_binary,
- enif_realloc_binary, enif_release_binary,
- enif_alloc_resource, enif_release_resource,
- enif_is_identical and enif_compare.
- - Character encoding argument added to enif_get_atom
- and enif_make_existing_atom.
- - Module argument added to enif_open_resource_type
- while changing name spaces of resource types from global to module local.
-
-
- - Incompatible changes between R13B04 and R13B03:
-
- - The function prototypes of the NIFs have changed to expect argc and argv
- arguments. The arity of a NIF is by that no longer limited to 3.
- - enif_get_data renamed as enif_priv_data.
- - enif_make_string got a third argument for character encoding.
-
-
-
-
A minimal example of a NIF library can look like this:
--
cgit v1.2.3