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