121 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| require 'fast_spec_helper'
 | |
| require 'support/shared_examples/lib/gitlab/malicious_regexp_shared_examples'
 | |
| require 'support/helpers/stub_feature_flags'
 | |
| 
 | |
| RSpec.describe Gitlab::UntrustedRegexp::RubySyntax do
 | |
|   describe '.matches_syntax?' do
 | |
|     it 'returns true if regexp is valid' do
 | |
|       expect(described_class.matches_syntax?('/some .* thing/'))
 | |
|         .to be true
 | |
|     end
 | |
| 
 | |
|     it 'returns true if regexp is invalid, but resembles regexp' do
 | |
|       expect(described_class.matches_syntax?('/some ( thing/'))
 | |
|         .to be true
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '.valid?' do
 | |
|     it 'returns true if regexp is valid' do
 | |
|       expect(described_class.valid?('/some .* thing/'))
 | |
|         .to be true
 | |
|     end
 | |
| 
 | |
|     it 'returns false if regexp is invalid' do
 | |
|       expect(described_class.valid?('/some ( thing/'))
 | |
|         .to be false
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '.fabricate' do
 | |
|     context 'when regexp is valid' do
 | |
|       it 'fabricates regexp without flags' do
 | |
|         expect(described_class.fabricate('/some .* thing/')).not_to be_nil
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when regexp is empty' do
 | |
|       it 'fabricates regexp correctly' do
 | |
|         expect(described_class.fabricate('//')).not_to be_nil
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when regexp is a raw pattern' do
 | |
|       it 'returns error' do
 | |
|         expect(described_class.fabricate('some .* thing')).to be_nil
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '.fabricate!' do
 | |
|     context 'safe regexp is used' 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 Gitlab::UntrustedRegexp.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 Gitlab::UntrustedRegexp.new('(?im)something')
 | |
|         end
 | |
| 
 | |
|         it 'fabricates regexp without flags' do
 | |
|           regexp = described_class.fabricate!('/something/')
 | |
| 
 | |
|           expect(regexp).to eq Gitlab::UntrustedRegexp.new('something')
 | |
|         end
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when unsafe regexp is used' do
 | |
|       include StubFeatureFlags
 | |
| 
 | |
|       before do
 | |
|         stub_feature_flags(allow_unsafe_ruby_regexp: true)
 | |
| 
 | |
|         allow(Gitlab::UntrustedRegexp).to receive(:new).and_raise(RegexpError)
 | |
|       end
 | |
| 
 | |
|       context 'when no fallback is enabled' do
 | |
|         it 'raises an exception' do
 | |
|           expect { described_class.fabricate!('/something/') }
 | |
|             .to raise_error(RegexpError)
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       context 'when fallback is used' do
 | |
|         it 'fabricates regexp with a single flag' do
 | |
|           regexp = described_class.fabricate!('/something/i', fallback: true)
 | |
| 
 | |
|           expect(regexp).to eq Regexp.new('something', Regexp::IGNORECASE)
 | |
|         end
 | |
| 
 | |
|         it 'fabricates regexp with multiple flags' do
 | |
|           regexp = described_class.fabricate!('/something/im', fallback: true)
 | |
| 
 | |
|           expect(regexp).to eq Regexp.new('something', Regexp::IGNORECASE | Regexp::MULTILINE)
 | |
|         end
 | |
| 
 | |
|         it 'fabricates regexp without flags' do
 | |
|           regexp = described_class.fabricate!('/something/', fallback: true)
 | |
| 
 | |
|           expect(regexp).to eq Regexp.new('something')
 | |
|         end
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when regexp is a raw pattern' do
 | |
|       it 'raises an error' do
 | |
|         expect { described_class.fabricate!('some .* thing') }
 | |
|           .to raise_error(RegexpError)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 |