Elixir and Erlang/OTP versions
Erlang/OTP 28 [erts-16.2] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]
Elixir 1.20.0-rc.4 (c1256f1) (compiled with Erlang/OTP 28)
Operating system
any
Current behavior
When translating var names to erlang if the variable is :"" it gets the same erlang name as _
|
build_name('_', Count) -> list_to_atom("_@" ++ integer_to_list(Count)); |
|
build_name(Name, Count) -> list_to_atom("_" ++ atom_to_list(Name) ++ "@" ++ integer_to_list(Count)). |
Which can lead to collision and macro hygiene bypass
This bug can be triggered in
defmodule Repro do
defmacro collide(expr) do
empty = Macro.var(:"", nil)
quote do
(fn x ->
unquote(empty) = String.Chars.to_string(x)
{unquote(empty), x}
end).(unquote(expr))
end
end
end
defmodule UseRepro do
require Repro
def run(x), do: Repro.collide(x)
end
UseRepro.run(:abc)
** (MatchError) no match of right hand side value:
"abc"
iex:5: UseRepro.run/1
iex:4: (file)
the same code works correctly if Macro.var(:"nonempty", nil) is used instead of Macro.var(:"", nil)
Expected behavior
Either forbid empty atom at AST expansion/translation time or normalize it
Elixir and Erlang/OTP versions
Erlang/OTP 28 [erts-16.2] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]
Elixir 1.20.0-rc.4 (c1256f1) (compiled with Erlang/OTP 28)
Operating system
any
Current behavior
When translating var names to erlang if the variable is
:""it gets the same erlang name as_elixir/lib/elixir/src/elixir_erl_var.erl
Lines 48 to 49 in 5d794ab
Which can lead to collision and macro hygiene bypass
This bug can be triggered in
the same code works correctly if
Macro.var(:"nonempty", nil)is used instead ofMacro.var(:"", nil)Expected behavior
Either forbid empty atom at AST expansion/translation time or normalize it