Skip to content

Commit 60100d1

Browse files
committed
fix: guard infix reassociation against malformed operands
Recent fn-head parsing changes introduced infix reassociation branches that assume comma/when operands always carry list arguments. In the absinthe matrix CI run, a malformed intermediate AST used , which passed the guard and crashed in . This change hardens the parser by requiring list operands before reassociation in , and by making fn-head nested-parens validation a no-op for non-list argument payloads. This preserves existing behavior for valid AST shapes while preventing parser crashes on recoverable malformed intermediates encountered during large real-world repo parsing.
1 parent 5490366 commit 60100d1

1 file changed

Lines changed: 5 additions & 3 deletions

File tree

lib/spitfire.ex

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,7 @@ defmodule Spitfire do
13761376

13771377
# Reject nested grouped tuple/keyword arguments inside fn heads, for example
13781378
# `fn (a, (b, c)) -> ... end` and `fn ((a, b), c) -> ... end`.
1379-
defp maybe_error_invalid_fn_head_args(parser, args) do
1379+
defp maybe_error_invalid_fn_head_args(parser, args) when is_list(args) do
13801380
Enum.reduce(args, parser, fn arg, parser ->
13811381
case arg do
13821382
{:comma, [{:parens, parens_meta} | _], _} ->
@@ -1394,6 +1394,8 @@ defmodule Spitfire do
13941394
end)
13951395
end
13961396

1397+
defp maybe_error_invalid_fn_head_args(parser, _args), do: parser
1398+
13971399
# Reject top-level fn-head wrappers that carry more than one parens entry,
13981400
# such as `((a, b))` and `((a: 1))`.
13991401
defp maybe_error_nested_top_parens(parser, meta) do
@@ -1568,11 +1570,11 @@ defmodule Spitfire do
15681570

15691571
_ ->
15701572
case lhs do
1571-
{:comma, comma_meta, args} when args != [] ->
1573+
{:comma, comma_meta, args} when is_list(args) and args != [] ->
15721574
{leading, [last]} = Enum.split(args, -1)
15731575
{:comma, comma_meta, leading ++ [{token, newlines ++ meta, [last, rhs]}]}
15741576

1575-
{:when, when_meta, when_args} when length(when_args) > 2 ->
1577+
{:when, when_meta, when_args} when is_list(when_args) and length(when_args) > 2 ->
15761578
{leading, [second_last, guard]} = Enum.split(when_args, -2)
15771579
when_node = {:when, when_meta, [second_last, guard]}
15781580
{:comma, [], leading ++ [{token, newlines ++ meta, [when_node, rhs]}]}

0 commit comments

Comments
 (0)