Skip to content

Commit 8930346

Browse files
hyperpolymathclaude
andcommitted
fix: replace String.to_atom with String.to_existing_atom
Prevents BEAM atom table exhaustion from unbounded String.to_atom calls. Detected by panic-attack assail batch scan (2026-03-30). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 49dec59 commit 8930346

5 files changed

Lines changed: 6 additions & 6 deletions

File tree

lib/phronesis/cli.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ defmodule Phronesis.CLI do
897897
end
898898

899899
defp run_benchmark(name, opts) do
900-
benchmark = String.to_atom(name)
900+
benchmark = String.to_existing_atom(name)
901901
iterations = Keyword.get(opts, :iterations, 10_000)
902902

903903
result = Phronesis.Benchmark.run(benchmark, iterations: iterations)

lib/phronesis/compiler.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ defmodule Phronesis.Compiler do
619619

620620
value =
621621
case base do
622-
%{} = map -> Map.get(map, String.to_atom(field)) || Map.get(map, field)
622+
%{} = map -> Map.get(map, String.to_existing_atom(field)) || Map.get(map, field)
623623
_ -> nil
624624
end
625625

@@ -632,7 +632,7 @@ defmodule Phronesis.Compiler do
632632
value =
633633
case base do
634634
nil -> nil
635-
%{} = map -> Map.get(map, String.to_atom(field)) || Map.get(map, field)
635+
%{} = map -> Map.get(map, String.to_existing_atom(field)) || Map.get(map, field)
636636
_ -> nil
637637
end
638638

lib/phronesis/consensus/raft/rpc.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ defmodule Phronesis.Consensus.Raft.RPC do
108108
defp parse_distributed_node(node_id) do
109109
case String.split(node_id, "@") do
110110
[name, host] ->
111-
node = String.to_atom("#{name}@#{host}")
111+
node = String.to_existing_atom("#{name}@#{host}")
112112

113113
if node in [node() | Node.list()] do
114114
{:ok, node, {:via, Registry, {Phronesis.Consensus.Registry, name}}}

lib/phronesis/consensus/supervisor.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ defmodule Phronesis.Consensus.Supervisor do
1919
def init(_opts) do
2020
# Check if consensus mode is enabled via environment
2121
consensus_enabled = System.get_env("PHRONESIS_CONSENSUS_ENABLED", "false") == "true"
22-
node_id = String.to_atom(System.get_env("PHRONESIS_NODE_ID", "node1"))
22+
node_id = String.to_existing_atom(System.get_env("PHRONESIS_NODE_ID", "node1"))
2323

2424
children =
2525
if consensus_enabled do

lib/phronesis/interpreter.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ defmodule Phronesis.Interpreter do
375375

376376
defp resolve_module(["Std", module_name | _rest] = path) do
377377
# Map Std.BGP → Phronesis.Stdlib.BGP, Std.RPKI → Phronesis.Stdlib.RPKI, etc.
378-
elixir_module = Module.concat([Phronesis, Stdlib, String.to_atom(module_name)])
378+
elixir_module = Module.concat([Phronesis, Stdlib, String.to_existing_atom(module_name)])
379379

380380
case Code.ensure_loaded(elixir_module) do
381381
{:module, _mod} ->

0 commit comments

Comments
 (0)