Skip to content

Commit bfbd765

Browse files
committed
Assert scope is not match/guard when using escaped regexes (#14780)
1 parent 1327c0c commit bfbd765

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

lib/elixir/lib/regex.ex

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,9 @@ defmodule Regex do
10081008

10091009
pattern_ast =
10101010
cond do
1011+
is_nil(regex.re_pattern) ->
1012+
nil
1013+
10111014
# TODO: Remove this when we require Erlang/OTP 28+
10121015
# Before OTP 28.0, patterns did not contain any refs and could be safely be escaped
10131016
:erlang.system_info(:otp_release) < [?2, ?8] ->
@@ -1018,8 +1021,10 @@ defmodule Regex do
10181021
{:ok, exported} = :re.compile(regex.source, [:export] ++ regex.opts)
10191022

10201023
quote do
1021-
:re.import(unquote(Macro.escape(exported)))
1024+
Regex.__import_pattern__(unquote(Macro.escape(exported)))
10221025
end
1026+
# we now that the Regex module is defined at this stage, so this macro can be safely called
1027+
|> Macro.update_meta(&([required: true] ++ &1))
10231028

10241029
# TODO: Remove this when we require Erlang/OTP 28.1+
10251030
# OTP 28.0 works in degraded mode performance-wise, we need to recompile from the source
@@ -1041,4 +1046,15 @@ defmodule Regex do
10411046
}
10421047
end
10431048
end
1049+
1050+
@doc false
1051+
defmacro __import_pattern__(pattern) do
1052+
if __CALLER__.context in [:match, :guard] do
1053+
raise ArgumentError, "escaped Regex structs are not allowed in match or guards"
1054+
end
1055+
1056+
quote do
1057+
:re.import(unquote(pattern))
1058+
end
1059+
end
10441060
end

lib/elixir/test/elixir/macro_test.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ defmodule MacroTest do
168168
[
169169
__struct__: Regex,
170170
re_pattern:
171-
{{:., [], [:re, :import]}, [], [{:{}, [], [:re_exported_pattern | _]}]},
171+
{{:., [], [{:__aliases__, _, [:Regex]}, :__import_pattern__]},
172+
[required: true], [{:{}, [], [:re_exported_pattern | _]}]},
172173
source: "foo",
173174
opts: []
174175
]

lib/elixir/test/elixir/regex_test.exs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,25 @@ defmodule RegexTest do
2828
end
2929
end
3030

31+
@tag :re_import
32+
test "module attribute in match context" do
33+
assert_raise(
34+
ArgumentError,
35+
~r/escaped Regex structs are not allowed in match or guards/,
36+
fn ->
37+
Code.eval_quoted(
38+
quote do
39+
defmodule ModAttrGuard do
40+
@regex ~r/example/
41+
def example?(@regex), do: true
42+
def example?(_), do: false
43+
end
44+
end
45+
)
46+
end
47+
)
48+
end
49+
3150
test "multiline" do
3251
refute Regex.match?(~r/^b$/, "a\nb\nc")
3352
assert Regex.match?(~r/^b$/m, "a\nb\nc")

0 commit comments

Comments
 (0)