diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 19:05:49 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 19:05:49 +0300 |
commit | 43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch) | |
tree | dceebdc68925362117480a5d672bcff122fb625b /lib/gitlab/untrusted_regexp.rb | |
parent | 20c84b99005abd1c82101dfeff264ac50d2df211 (diff) |
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'lib/gitlab/untrusted_regexp.rb')
-rw-r--r-- | lib/gitlab/untrusted_regexp.rb | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/lib/gitlab/untrusted_regexp.rb b/lib/gitlab/untrusted_regexp.rb index 7c7bda3a8f9..fe3377dae68 100644 --- a/lib/gitlab/untrusted_regexp.rb +++ b/lib/gitlab/untrusted_regexp.rb @@ -10,6 +10,9 @@ module Gitlab # Not all regular expression features are available in untrusted regexes, and # there is a strict limit on total execution time. See the RE2 documentation # at https://github.com/google/re2/wiki/Syntax for more details. + # + # This class doesn't change any instance variables, which allows it to be frozen + # and setup in constants. class UntrustedRegexp require_dependency 're2' @@ -21,6 +24,7 @@ module Gitlab end @regexp = RE2::Regexp.new(pattern, log_errors: false) + @scan_regexp = initialize_scan_regexp raise RegexpError, regexp.error unless regexp.ok? end @@ -29,6 +33,27 @@ module Gitlab RE2.GlobalReplace(text, regexp, rewrite) end + # There is no built-in replace with block support (like `gsub`). We can accomplish + # the same thing by parsing and rebuilding the string with the substitutions. + def replace_gsub(text) + new_text = +'' + remainder = text + + matched = match(remainder) + + until matched.nil? || matched.to_a.compact.empty? + partitioned = remainder.partition(matched.to_s) + new_text << partitioned.first + remainder = partitioned.last + + new_text << yield(matched) + + matched = match(remainder) + end + + new_text << remainder + end + def scan(text) matches = scan_regexp.scan(text).to_a matches.map!(&:first) if regexp.number_of_capturing_groups == 0 @@ -87,17 +112,16 @@ module Gitlab private - attr_reader :regexp + attr_reader :regexp, :scan_regexp # RE2 scan operates differently to Ruby scan when there are no capture # groups, so work around it - def scan_regexp - @scan_regexp ||= - if regexp.number_of_capturing_groups == 0 - RE2::Regexp.new('(' + regexp.source + ')') - else - regexp - end + def initialize_scan_regexp + if regexp.number_of_capturing_groups == 0 + RE2::Regexp.new('(' + regexp.source + ')') + else + regexp + end end end end |