Skip to content

Commit 030e0c7

Browse files
committed
Do not explicitly recompile regexes, fallback to binary matching
Regexes used to be precompiled to binary values during code compilation. These binary values may be incompatible with different operating systems and OTP releases. That's why an explicit `Regex.recompile/1` or `Regex.recompile!/1` was required. Regexes now fallback to binary matching if the precompiled binary is not compatible with the runtime version.
1 parent 5cdb1ea commit 030e0c7

File tree

6 files changed

+9
-14
lines changed

6 files changed

+9
-14
lines changed

lib/elixir/lib/io/ansi/docs.ex

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -525,15 +525,11 @@ defmodule IO.ANSI.Docs do
525525

526526
defp escape_underlines_in_link(text) do
527527
# Regular expression adapted from https://tools.ietf.org/html/rfc3986#appendix-B
528-
~r{[a-z][a-z0-9\+\-\.]*://\S*}i
529-
|> Regex.recompile!()
530-
|> Regex.replace(text, &String.replace(&1, "_", "\\_"))
528+
Regex.replace(~r{[a-z][a-z0-9\+\-\.]*://\S*}i, text, &String.replace(&1, "_", "\\_"))
531529
end
532530

533531
defp remove_square_brackets_in_link(text) do
534-
~r{\[([^\]]*?)\]\((.*?)\)}
535-
|> Regex.recompile!()
536-
|> Regex.replace(text, "\\1 (\\2)")
532+
Regex.replace(~r{\[([^\]]*?)\]\((.*?)\)}, text, "\\1 (\\2)")
537533
end
538534

539535
# We have four entries: **, *, _ and `.

lib/elixir/lib/uri.ex

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,8 +452,7 @@ defmodule URI do
452452

453453
def parse(string) when is_binary(string) do
454454
# From https://tools.ietf.org/html/rfc3986#appendix-B
455-
regex =
456-
Regex.recompile!(~r{^(([a-z][a-z0-9\+\-\.]*):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?}i)
455+
regex = ~r{^(([a-z][a-z0-9\+\-\.]*):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?}i
457456

458457
parts = Regex.run(regex, string)
459458

@@ -486,7 +485,7 @@ defmodule URI do
486485

487486
# Split an authority into its userinfo, host and port parts.
488487
defp split_authority(string) do
489-
regex = Regex.recompile!(~r/(^(.*)@)?(\[[a-zA-Z0-9:.]*\]|[^:]*)(:(\d*))?/)
488+
regex = ~r/(^(.*)@)?(\[[a-zA-Z0-9:.]*\]|[^:]*)(:(\d*))?/
490489
components = Regex.run(regex, string || "")
491490

492491
destructure [_, _, userinfo, host, _, port], components

lib/ex_unit/lib/ex_unit/doc_test.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ defmodule ExUnit.DocTest do
414414
message = "Doctest did not compile, got: #{ex_message}"
415415

416416
message =
417-
if e.__struct__ == TokenMissingError and expr =~ Regex.recompile!(@opaque_type_regex) do
417+
if e.__struct__ == TokenMissingError and expr =~ @opaque_type_regex do
418418
message <>
419419
"""
420420
. If you are planning to assert on the result of an iex> expression \

lib/logger/lib/logger/formatter.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ defmodule Logger.Formatter do
8989
def compile({mod, fun}) when is_atom(mod) and is_atom(fun), do: {mod, fun}
9090

9191
def compile(str) when is_binary(str) do
92-
regex = Regex.recompile!(~r/(?<head>)\$[a-z]+(?<tail>)/)
92+
regex = ~r/(?<head>)\$[a-z]+(?<tail>)/
9393

9494
for part <- Regex.split(regex, str, on: [:head, :tail], trim: true) do
9595
case part do

lib/mix/lib/mix/release.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ defmodule Mix.Release do
6868
def from_config!(name, config, overrides) do
6969
{name, apps, opts} = find_release(name, config)
7070

71-
unless Atom.to_string(name) =~ Regex.recompile!(~r/^[a-z][a-z0-9_]*$/) do
71+
unless Atom.to_string(name) =~ ~r/^[a-z][a-z0-9_]*$/ do
7272
Mix.raise(
7373
"Invalid release name. A release name must start with a lowercase ASCII letter, " <>
7474
"followed by lowercase ASCII letters, numbers, or underscores, got: #{inspect(name)}"

lib/mix/lib/mix/tasks/new.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ defmodule Mix.Tasks.New do
167167
end
168168

169169
defp check_application_name!(name, inferred?) do
170-
unless name =~ Regex.recompile!(~r/^[a-z][a-z0-9_]*$/) do
170+
unless name =~ ~r/^[a-z][a-z0-9_]*$/ do
171171
Mix.raise(
172172
"Application name must start with a lowercase ASCII letter, followed by " <>
173173
"lowercase ASCII letters, numbers, or underscores, got: #{inspect(name)}" <>
@@ -182,7 +182,7 @@ defmodule Mix.Tasks.New do
182182
end
183183

184184
defp check_mod_name_validity!(name) do
185-
unless name =~ Regex.recompile!(~r/^[A-Z]\w*(\.[A-Z]\w*)*$/) do
185+
unless name =~ ~r/^[A-Z]\w*(\.[A-Z]\w*)*$/ do
186186
Mix.raise(
187187
"Module name must be a valid Elixir alias (for example: Foo.Bar), got: #{inspect(name)}"
188188
)

0 commit comments

Comments
 (0)