Skip to content

Commit

Permalink
Fix PCRE2 do not allocate JIT stack if unavailable (#13100)
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Mar 2, 2023
1 parent 865d050 commit 0f0eb1d
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 4 deletions.
4 changes: 3 additions & 1 deletion spec/std/regex_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@ describe "Regex" do
{% else %}
# Can't use regex literal because the *LIMIT_DEPTH verb is not supported in libpcre (only libpcre2)
# and thus the compiler doesn't recognize it.
str.matches?(Regex.new("(*LIMIT_DEPTH=8192)^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"))
regex = Regex.new("(*LIMIT_DEPTH=8192)^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")
pending! "PCRE2 JIT mode not available." unless regex.@jit
str.matches?(regex)
{% end %}
# We don't care whether this actually matches or not, it's just to make
# sure the engine does not stack overflow with a large string.
Expand Down
9 changes: 6 additions & 3 deletions src/regex/pcre2.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,29 @@ require "crystal/thread_local_value"
# :nodoc:
module Regex::PCRE2
@re : LibPCRE2::Code*
@jit : Bool

# :nodoc:
def initialize(*, _source @source : String, _options @options)
@re = PCRE2.compile(source, pcre2_options(options) | LibPCRE2::UTF | LibPCRE2::NO_UTF_CHECK | LibPCRE2::DUPNAMES | LibPCRE2::UCP) do |error_message|
raise ArgumentError.new(error_message)
end

jit_compile
@jit = jit_compile
end

private def jit_compile : Nil
private def jit_compile : Bool
ret = LibPCRE2.jit_compile(@re, LibPCRE2::JIT_COMPLETE)
if ret < 0
case error = LibPCRE2::Error.new(ret)
when .jit_badoption?
# okay
return false
else
raise ArgumentError.new("Regex JIT compile error: #{error}")
end
end
true
end

protected def self.compile(source, options)
Expand Down Expand Up @@ -153,7 +156,7 @@ module Regex::PCRE2
private def match_data(str, byte_index, options)
match_data = LibPCRE2.match_data_create_from_pattern(@re, Regex::PCRE2.general_context)
match_context = LibPCRE2.match_context_create(nil)
LibPCRE2.jit_stack_assign(match_context, nil, Regex::PCRE2.jit_stack.as(Void*))
LibPCRE2.jit_stack_assign(match_context, nil, Regex::PCRE2.jit_stack.as(Void*)) if @jit
match_count = LibPCRE2.match(@re, str, str.bytesize, byte_index, pcre2_options(options) | LibPCRE2::NO_UTF_CHECK, match_data, match_context)

if match_count < 0
Expand Down

0 comments on commit 0f0eb1d

Please sign in to comment.