diff options
author | Sverker Eriksson <[email protected]> | 2016-02-08 15:47:49 +0100 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2016-02-08 16:11:56 +0100 |
commit | 7a319cd96f7f4869300b32442ebe892ae557f41c (patch) | |
tree | 74eac8b419d1f9de35b5deb46bdf2f4e3884df25 | |
parent | 14680fcc3fb9d0357fe33a94525d08896afed1c5 (diff) | |
download | otp-7a319cd96f7f4869300b32442ebe892ae557f41c.tar.gz otp-7a319cd96f7f4869300b32442ebe892ae557f41c.tar.bz2 otp-7a319cd96f7f4869300b32442ebe892ae557f41c.zip |
erts: Fix error cases in enif_get_list_length
false if improper list
false if length > UINT_MAX
-rw-r--r-- | erts/doc/src/erl_nif.xml | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 9 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 4 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 6 |
4 files changed, 15 insertions, 6 deletions
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 420c9fea38..be0e406b9c 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -753,7 +753,7 @@ typedef enum { <func><name><ret>int</ret><nametext>enif_get_list_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)</nametext></name> <fsummary>Get the length of list <c>term</c></fsummary> <desc><p>Set <c>*len</c> to the length of list <c>term</c> and return true, - or return false if <c>term</c> is not a list.</p></desc> + or return false if <c>term</c> is not a proper list.</p></desc> </func> <func><name><ret>int</ret><nametext>enif_get_long(ErlNifEnv* env, ERL_NIF_TERM term, long int* ip)</nametext></name> <fsummary>Read an long integer term</fsummary> diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index b057ec7770..12aaf4ce53 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -911,8 +911,13 @@ int enif_get_list_cell(ErlNifEnv* env, Eterm term, Eterm* head, Eterm* tail) int enif_get_list_length(ErlNifEnv* env, Eterm term, unsigned* len) { - if (is_not_list(term) && is_not_nil(term)) return 0; - *len = erts_list_length(term); + Sint i; + Uint u; + + if ((i = erts_list_length(term)) < 0) return 0; + u = (Uint)i; + if ((unsigned)u != u) return 0; + *len = u; return 1; } diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index b02a090103..bfec474966 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -1398,7 +1398,7 @@ is_checks(Config) when is_list(Config) -> get_length(doc) -> ["Test all enif_get_length functions"]; get_length(Config) when is_list(Config) -> ?line ensure_lib_loaded(Config, 1), - ?line ok = length_test(hejsan, "hejsan", [], [], not_a_list). + ?line ok = length_test(hejsan, "hejsan", [], [], not_a_list, [1,2|3]). ensure_lib_loaded(Config) -> ensure_lib_loaded(Config, 1). @@ -1951,7 +1951,7 @@ last_resource_dtor_call() -> ?nif_stub. make_new_resource(_,_) -> ?nif_stub. check_is(_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. check_is_exception() -> ?nif_stub. -length_test(_,_,_,_,_) -> ?nif_stub. +length_test(_,_,_,_,_,_) -> ?nif_stub. make_atoms() -> ?nif_stub. make_strings() -> ?nif_stub. make_new_resource_binary(_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 8ebce4fef4..1acb270d1f 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -914,6 +914,7 @@ static ERL_NIF_TERM check_is_exception(ErlNifEnv* env, int argc, const ERL_NIF_T * argv[2] empty list * argv[3] not an atom * argv[4] not a list + * argv[5] improper list */ static ERL_NIF_TERM length_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { @@ -934,6 +935,9 @@ static ERL_NIF_TERM length_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg if (enif_get_list_length(env, argv[4], &len)) return enif_make_badarg(env); + if (enif_get_list_length(env, argv[5], &len)) + return enif_make_badarg(env); + return enif_make_atom(env, "ok"); } @@ -2002,7 +2006,7 @@ static ErlNifFunc nif_funcs[] = {"make_new_resource", 2, make_new_resource}, {"check_is", 11, check_is}, {"check_is_exception", 0, check_is_exception}, - {"length_test", 5, length_test}, + {"length_test", 6, length_test}, {"make_atoms", 0, make_atoms}, {"make_strings", 0, make_strings}, {"make_new_resource", 2, make_new_resource}, |