Skip to content
Snippets Groups Projects
Commit 82f4564f authored by Sean McGivern's avatar Sean McGivern
Browse files

Fix project search results for digits surrounded by colons

A file containing /:\d+:/ in its contents would break the search results if
those contents were part of the results, because we were splitting on colons,
which can't work with untrusted input.

Changing to use the null byte as a separator is much safer.
parent 1df5c74f
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -932,7 +932,7 @@ class Repository
return [] if empty? || query.blank?
 
offset = 2
args = %W(grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref})
args = %W(grep -i -I -n -z --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref})
 
run_git(args).first.scrub.split(/^--$/)
end
Loading
Loading
---
title: Fix file search results when they match file contents with a number between
two colons
merge_request: 16462
author:
type: fixed
Loading
Loading
@@ -44,25 +44,20 @@ module Gitlab
ref = nil
filename = nil
basename = nil
data = ""
startline = 0
 
result.each_line.each_with_index do |line, index|
matches = line.match(/^(?<ref>[^:]*):(?<filename>.*):(?<startline>\d+):/)
if matches
result.strip.each_line.each_with_index do |line, index|
prefix ||= line.match(/^(?<ref>[^:]*):(?<filename>.*)\x00(?<startline>\d+)\x00/)&.tap do |matches|
ref = matches[:ref]
filename = matches[:filename]
startline = matches[:startline]
startline = startline.to_i - index
extname = Regexp.escape(File.extname(filename))
basename = filename.sub(/#{extname}$/, '')
break
end
end
data = ""
 
result.each_line do |line|
data << line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '')
data << line.sub(prefix.to_s, '')
end
 
FoundBlob.new(
Loading
Loading
Loading
Loading
@@ -70,15 +70,6 @@ describe Gitlab::ProjectSearchResults do
 
subject { described_class.parse_search_result(search_result) }
 
it 'can correctly parse filenames including ":"' do
special_char_result = "\nmaster:testdata/project::function1.yaml-1----\nmaster:testdata/project::function1.yaml:2:test: data1\n"
blob = described_class.parse_search_result(special_char_result)
expect(blob.ref).to eq('master')
expect(blob.filename).to eq('testdata/project::function1.yaml')
end
it "returns a valid FoundBlob" do
is_expected.to be_an Gitlab::SearchResults::FoundBlob
expect(subject.id).to be_nil
Loading
Loading
@@ -90,8 +81,32 @@ describe Gitlab::ProjectSearchResults do
expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n")
end
 
context 'when the matching filename contains a colon' do
let(:search_result) { "\nmaster:testdata/project::function1.yaml\x001\x00---\n" }
it 'returns a valid FoundBlob' do
expect(subject.filename).to eq('testdata/project::function1.yaml')
expect(subject.basename).to eq('testdata/project::function1')
expect(subject.ref).to eq('master')
expect(subject.startline).to eq(1)
expect(subject.data).to eq('---')
end
end
context 'when the matching content contains a number surrounded by colons' do
let(:search_result) { "\nmaster:testdata/foo.txt\x001\x00blah:9:blah" }
it 'returns a valid FoundBlob' do
expect(subject.filename).to eq('testdata/foo.txt')
expect(subject.basename).to eq('testdata/foo')
expect(subject.ref).to eq('master')
expect(subject.startline).to eq(1)
expect(subject.data).to eq('blah:9:blah')
end
end
context "when filename has extension" do
let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" }
let(:search_result) { "master:CONTRIBUTE.md\x005\x00- [Contribute to GitLab](#contribute-to-gitlab)\n" }
 
it { expect(subject.path).to eq('CONTRIBUTE.md') }
it { expect(subject.filename).to eq('CONTRIBUTE.md') }
Loading
Loading
@@ -99,7 +114,7 @@ describe Gitlab::ProjectSearchResults do
end
 
context "when file under directory" do
let(:search_result) { "master:a/b/c.md:5:a b c\n" }
let(:search_result) { "master:a/b/c.md\x005\x00a b c\n" }
 
it { expect(subject.path).to eq('a/b/c.md') }
it { expect(subject.filename).to eq('a/b/c.md') }
Loading
Loading
@@ -144,7 +159,7 @@ describe Gitlab::ProjectSearchResults do
end
 
it 'finds by content' do
expect(results).to include("master:Title.md:1:Content\n")
expect(results).to include("master:Title.md\x001\x00Content\n")
end
end
 
Loading
Loading
Loading
Loading
@@ -657,7 +657,7 @@ describe Repository do
subject { results.first }
 
it { is_expected.to be_an String }
it { expect(subject.lines[2]).to eq("master:CHANGELOG:190: - Feature: Replace teams with group membership\n") }
it { expect(subject.lines[2]).to eq("master:CHANGELOG\x00190\x00 - Feature: Replace teams with group membership\n") }
end
end
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment