From ddbd61715214b72959206f3308c448b132683f94 Mon Sep 17 00:00:00 2001 From: pnezis Date: Sat, 7 Mar 2026 10:44:21 +0200 Subject: [PATCH] Raise `ArgumentError` on invalid binding in `Code.eval_string/3` Previously, passing a non-list binding to `Code.eval_string/3` would crash deep in Erlang code with a confusing `FunctionClauseError` in `:elixir_erl_var.load_binding/6`. --- lib/elixir/lib/code.ex | 10 ++++++++-- lib/elixir/test/elixir/code_test.exs | 10 ++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/elixir/lib/code.ex b/lib/elixir/lib/code.ex index 6f5765976d0..d3f12c9df70 100644 --- a/lib/elixir/lib/code.ex +++ b/lib/elixir/lib/code.ex @@ -621,11 +621,17 @@ defmodule Code do def eval_string(string, binding \\ [], opts \\ []) def eval_string(string, binding, %Macro.Env{} = env) do - validated_eval_string(string, binding, env) + validated_eval_string(string, validate_binding(binding), env) end def eval_string(string, binding, opts) when is_list(opts) do - validated_eval_string(string, binding, opts) + validated_eval_string(string, validate_binding(binding), opts) + end + + defp validate_binding(binding) when is_list(binding), do: binding + + defp validate_binding(binding) do + raise ArgumentError, "binding must be a list, got: #{inspect(binding)}" end defp validated_eval_string(string, binding, opts_or_env) do diff --git a/lib/elixir/test/elixir/code_test.exs b/lib/elixir/test/elixir/code_test.exs index 0d1144fef3b..53bd4f4652c 100644 --- a/lib/elixir/test/elixir/code_test.exs +++ b/lib/elixir/test/elixir/code_test.exs @@ -176,6 +176,16 @@ defmodule CodeTest do {"1", [{:c, 2}, {:b, "1"}, {:a, 1}]} end + test "raises on invalid binding type" do + assert_raise ArgumentError, "binding must be a list, got: :not_a_list", fn -> + Code.eval_string("1 + 1", :not_a_list) + end + + assert_raise ArgumentError, "binding must be a list, got: %{}", fn -> + Code.eval_string("1 + 1", %{}, __ENV__) + end + end + test "keeps caller in stacktrace" do try do Code.eval_string("<>", [a: :a, b: :b], file: "myfile")