Add extended /regexp/ scheme support to untrusted regexp
This commit is contained in:
parent
f52de2f73c
commit
0ce63efe96
2 changed files with 71 additions and 1 deletions
|
@ -9,6 +9,8 @@ module Gitlab
|
|||
# there is a strict limit on total execution time. See the RE2 documentation
|
||||
# at https://github.com/google/re2/wiki/Syntax for more details.
|
||||
class UntrustedRegexp
|
||||
require_dependency 're2'
|
||||
|
||||
delegate :===, :source, to: :regexp
|
||||
|
||||
def initialize(pattern, multiline: false)
|
||||
|
@ -52,6 +54,27 @@ module Gitlab
|
|||
Regexp.new(pattern)
|
||||
end
|
||||
|
||||
def self.valid?(pattern)
|
||||
self.fabricate(pattern)
|
||||
rescue RegexpError
|
||||
false
|
||||
end
|
||||
|
||||
def self.fabricate(pattern)
|
||||
matches = pattern.match(%r{^/(?<regexp>.+)/(?<flags>[ismU]*)$})
|
||||
|
||||
if matches
|
||||
expression = matches[:regexp]
|
||||
flags = matches[:flags]
|
||||
|
||||
expression.prepend("(?#{flags})") if flags.present?
|
||||
|
||||
self.new(expression, multiline: false)
|
||||
else
|
||||
self.new(pattern, multiline: false)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :regexp
|
||||
|
|
|
@ -1,6 +1,53 @@
|
|||
require 'spec_helper'
|
||||
require 'fast_spec_helper'
|
||||
require 'support/shared_examples/malicious_regexp_shared_examples'
|
||||
|
||||
describe Gitlab::UntrustedRegexp do
|
||||
describe '.valid?' do
|
||||
it 'returns true if regexp is valid' do
|
||||
end
|
||||
|
||||
it 'returns true if regexp is invalid' do
|
||||
end
|
||||
end
|
||||
|
||||
describe '.fabricate' do
|
||||
context 'when regexp is using /regexp/ scheme with flags' do
|
||||
it 'fabricates regexp with a single flag' do
|
||||
regexp = described_class.fabricate('/something/i')
|
||||
|
||||
expect(regexp).to eq described_class.new('(?i)something')
|
||||
expect(regexp.scan('SOMETHING')).to be_one
|
||||
end
|
||||
|
||||
it 'fabricates regexp with multiple flags' do
|
||||
regexp = described_class.fabricate('/something/im')
|
||||
|
||||
expect(regexp).to eq described_class.new('(?im)something')
|
||||
end
|
||||
|
||||
it 'fabricates regexp without flags' do
|
||||
regexp = described_class.fabricate('/something/')
|
||||
|
||||
expect(regexp).to eq described_class.new('something')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when regexp is not plain pattern' do
|
||||
it 'fabricates regexp without flags' do
|
||||
regexp = described_class.fabricate('something')
|
||||
|
||||
expect(regexp).to eq described_class.new('something')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when regexp is invalid' do
|
||||
it 'raises an error' do
|
||||
expect { described_class.fabricate('/some ( thing/') }
|
||||
.to raise_error(RegexpError)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#initialize' do
|
||||
subject { described_class.new(pattern) }
|
||||
|
||||
|
|
Loading…
Reference in a new issue