Skip to main content

W0023 - Risk of Atoms Exhaustion

Error

   -module(main).

-export([do/0]).

do() ->
[binary_to_atom(<<I/integer>>) || I <- lists:seq(1, 100)].
%% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: Risk of atoms exhaustion.

Explanation

Erlang atoms are not garbage-collected. Once an atom is created, it is never removed. The emulator terminates if the configurable limit for the number of atoms is reached.

Therefore, converting arbitrary input strings or binaries to atoms can be dangerous in a system that runs continuously. All functions which can create atoms have a safe variant which should be favoured when possible:

Conversion FunctionSafer Version
list_to_atom/1list_to_existing_atom/1
binary_to_atom/1,2binary_to_existing_atom/1,2
binaty_to_term/1,2binary_to_term/2 with the safe option

When using the safe or existing versions of the above conversion functions, all atoms must have been created earlier or the function will cause an exception:

1> binary_to_existing_atom(<<"this_atom_does_not_exist">>).
** exception error: bad argument
in function binary_to_existing_atom/1
called as binary_to_existing_atom(<<"this_atom_does_not_exist">>)
*** argument 1: not an already existing atom

To explicitly create necessary atoms beforehand, you can export a function that returns a list of all atoms which are expected:

-export([atoms/0]).
atoms() ->
[my_atom, your_atom, our_atom].

If there is no way to know atom names in advance and there is 100% confidence in bounded string variations passed to the conversion function you can preceed the conversion function call with a special comment to silent the linter:

% elp:ignore atoms_exhaustion - An optional explanation here

For more information see the Atom Exhausion section of the Erlang Ecosystem Foundation Security Work Group.