[erlang-bugs] enif_make_double returns invalid term for 'nan'

Mikael Pettersson mikpelinux@REDACTED
Sun Mar 1 18:34:13 CET 2015


Heinz Nikolaus Gies writes:
 > Hi Mikael,
 > thank for the clarification. That makes sense, I find 2) actually more troublesome since I went to consult the documents to be sure it’s not a defined behavior. What was a bit more concerning was that that it returned a value that breaks transparently breaks other erlang functions.
 > 
 > Perhaps simply returning a bad_arg would make a lot more sense?

Erlang-level exceptions don't exist at this level of the VM.  They have to
be synthesized explicitly, and doing that requires documented protocols
for signalling errors, and code to follow them.

E.g., the interface to BIFs is such that to signal badarg, the BIF:
1. stores a special flag in the current process struct, and
2. returns THE_NON_VALUE.

The caller, beam_emu.c or native code wrappers in hipe_${arch}_bifs, checks
for THE_NON_VALUE returns and branches to the exception-raising code.

The problem here is that we're in even lower-level code, and there is no
documentation that enif_make_*() can fail, how to detect such failures,
or what to do in response.  Once this is in place, the next problem is
to ensure that NIFs are properly updated and not just recompiled.

 > ---
 > Cheers,
 > Heinz Nikolaus Gies
 > heinz@REDACTED
 > 
 > 
 > 
 > > On Mar 1, 2015, at 13:02, Mikael Pettersson <mikpelinux@REDACTED> wrote:
 > > 
 > > Heinz Nikolaus Gies writes:
 > >> When enif_make_double gets a nan value passed as the double argument it returns a invalid term, this term can neither be printed (via the fmt*) functions nor can it be deserialized by binary_to_term when serializing it the following binary is generated:
 > >> 
 > >> 6> io:format("~p~n", [term_to_binary(V)]).
 > >> <<131,99,110,97,110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
 > >> 
 > >> V is the double returned by enif_make_double
 > > 
 > > There are two issues here:
 > > 1. the VM disallows INFs and NANs, but NIF authors may not be aware of that
 > > 2. enif_make_double() SHOULD reject non-finite doubles but it doesn't, and
 > >   its documentation doesn't mention any failure modes; returning THE_NON_VALUE
 > >   may not be detected as a failure by the NIF and so this non-value may leak
 > >   into aggregates (lists or tuples) where it will totally break things
 > > 
 > > When looking at this I noticed that enif_make_atom() also has problems: it
 > > may fail and return THE_NON_VALUE if the resulting atom would be too long,
 > > but the documentation doesn't mention this possibility so the NIF might
 > > continue and store this non-value in aggregates before returning.
 > > 
 > > The OTP folks need to straighten up error handling in the enif_make_*()
 > > functions.
 > 
 > xapplication/pgp-signature [Click mouse-2 to save to a file]

-- 



More information about the erlang-bugs mailing list