Commit 83481414 authored by Sean McGivern's avatar Sean McGivern Committed by James Edwards-Jones

Merge branch 'fix-re2-infinite-loop-nick' into 'security-9-3'

Fix an infinite loop in Gitlab:UntrustedRegexp

See merge request !2146
parent 2e46a584
---
title: Fix an infinite loop when handling user-supplied regular expressions
merge_request:
author:
...@@ -22,13 +22,28 @@ module Gitlab ...@@ -22,13 +22,28 @@ module Gitlab
end end
def scan(text) def scan(text)
scan_regexp.scan(text).map do |match| text = text.dup # modified in-place
if regexp.number_of_capturing_groups == 0 results = []
match.first
else loop do
match match = scan_regexp.match(text)
end break unless match
# Ruby scan returns empty strings, not nil
groups = match.to_a.map(&:to_s)
results <<
if regexp.number_of_capturing_groups.zero?
groups[0]
else
groups[1..-1]
end
text.slice!(0, match.end(0) || 1)
break unless text.present?
end end
results
end end
def replace(text, rewrite) def replace(text, rewrite)
...@@ -43,7 +58,7 @@ module Gitlab ...@@ -43,7 +58,7 @@ module Gitlab
# groups, so work around it # groups, so work around it
def scan_regexp def scan_regexp
@scan_regexp ||= @scan_regexp ||=
if regexp.number_of_capturing_groups == 0 if regexp.number_of_capturing_groups.zero?
RE2::Regexp.new('(' + regexp.source + ')') RE2::Regexp.new('(' + regexp.source + ')')
else else
regexp regexp
......
...@@ -46,10 +46,28 @@ describe Gitlab::UntrustedRegexp do ...@@ -46,10 +46,28 @@ describe Gitlab::UntrustedRegexp do
context 'malicious regexp' do context 'malicious regexp' do
let(:text) { malicious_text } let(:text) { malicious_text }
let(:regexp) { malicious_regexp } let(:regexp) { malicious_regexp }
include_examples 'malicious regexp' include_examples 'malicious regexp'
end end
context 'empty regexp' do
let(:regexp) { '' }
let(:text) { 'foo' }
it 'returns an array of empty matches' do
is_expected.to eq(['', '', ''])
end
end
context 'empty capture group regexp' do
let(:regexp) { '()' }
let(:text) { 'foo' }
it 'returns arrays of empty matches in an array' do
is_expected.to eq([[''], [''], ['']])
end
end
context 'no capture group' do context 'no capture group' do
let(:regexp) { '.+' } let(:regexp) { '.+' }
let(:text) { 'foo' } let(:text) { 'foo' }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment