Commit bca6156a authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/security/gitlab@13-12-stable-ee

parent f37a805b
<template> <template>
<div class="nothing-here-block"> <div class="nothing-here-block">
{{ __('This diff was suppressed by a .gitattributes entry.') }} {{ __("File suppressed by a .gitattributes entry or the file's encoding is unsupported.") }}
</div> </div>
</template> </template>
...@@ -20,7 +20,7 @@ class ProtectedBranch::PushAccessLevel < ApplicationRecord ...@@ -20,7 +20,7 @@ class ProtectedBranch::PushAccessLevel < ApplicationRecord
def check_access(user) def check_access(user)
if user && deploy_key.present? if user && deploy_key.present?
return true if user.can?(:read_project, project) && enabled_deploy_key_for_user?(deploy_key, user) return user.can?(:read_project, project) && enabled_deploy_key_for_user?(deploy_key, user)
end end
super super
......
.nothing-here-block .nothing-here-block
= _("This diff was suppressed by a .gitattributes entry.") = _("File suppressed by a .gitattributes entry or the file's encoding is unsupported.")
...@@ -250,7 +250,7 @@ module Gitlab ...@@ -250,7 +250,7 @@ module Gitlab
end end
def diffable? def diffable?
repository.attributes(file_path).fetch('diff') { true } diffable_by_attribute? && !text_with_binary_notice?
end end
def binary_in_repo? def binary_in_repo?
...@@ -366,6 +366,15 @@ module Gitlab ...@@ -366,6 +366,15 @@ module Gitlab
private private
def diffable_by_attribute?
repository.attributes(file_path).fetch('diff') { true }
end
# NOTE: Files with unsupported encodings (e.g. UTF-16) are treated as binary by git, but they are recognized as text files during encoding detection. These files have `Binary files a/filename and b/filename differ' as their raw diff content which cannot be used. We need to handle this special case and avoid displaying incorrect diff.
def text_with_binary_notice?
text? && has_binary_notice?
end
def fetch_blob(sha, path) def fetch_blob(sha, path)
return unless sha return unless sha
......
...@@ -6,7 +6,7 @@ module Gitlab ...@@ -6,7 +6,7 @@ module Gitlab
include Enumerable include Enumerable
def parse(lines, diff_file: nil) def parse(lines, diff_file: nil)
return [] if lines.blank? return [] if lines.blank? || Git::Diff.has_binary_notice?(lines.first)
@lines = lines @lines = lines
line_obj_index = 0 line_obj_index = 0
......
...@@ -33,6 +33,8 @@ module Gitlab ...@@ -33,6 +33,8 @@ module Gitlab
SERIALIZE_KEYS = %i(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file too_large).freeze SERIALIZE_KEYS = %i(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file too_large).freeze
BINARY_NOTICE_PATTERN = %r(Binary files a\/(.*) and b\/(.*) differ).freeze
class << self class << self
def between(repo, head, base, options = {}, *paths) def between(repo, head, base, options = {}, *paths)
straight = options.delete(:straight) || false straight = options.delete(:straight) || false
...@@ -131,8 +133,13 @@ module Gitlab ...@@ -131,8 +133,13 @@ module Gitlab
def patch_hard_limit_bytes def patch_hard_limit_bytes
Gitlab::CurrentSettings.diff_max_patch_bytes Gitlab::CurrentSettings.diff_max_patch_bytes
end end
end
def has_binary_notice?(text)
return false unless text.present?
text.start_with?(BINARY_NOTICE_PATTERN)
end
end
def initialize(raw_diff, expanded: true) def initialize(raw_diff, expanded: true)
@expanded = expanded @expanded = expanded
...@@ -215,7 +222,7 @@ module Gitlab ...@@ -215,7 +222,7 @@ module Gitlab
end end
def has_binary_notice? def has_binary_notice?
@diff.start_with?('Binary') self.class.has_binary_notice?(@diff)
end end
private private
......
...@@ -14015,6 +14015,9 @@ msgstr "" ...@@ -14015,6 +14015,9 @@ msgstr ""
msgid "File renamed with no changes." msgid "File renamed with no changes."
msgstr "" msgstr ""
msgid "File suppressed by a .gitattributes entry or the file's encoding is unsupported."
msgstr ""
msgid "File synchronization concurrency limit" msgid "File synchronization concurrency limit"
msgstr "" msgstr ""
...@@ -33097,9 +33100,6 @@ msgstr "" ...@@ -33097,9 +33100,6 @@ msgstr ""
msgid "This diff is collapsed." msgid "This diff is collapsed."
msgstr "" msgstr ""
msgid "This diff was suppressed by a .gitattributes entry."
msgstr ""
msgid "This directory" msgid "This directory"
msgstr "" msgstr ""
......
...@@ -253,7 +253,7 @@ RSpec.describe 'Expand and collapse diffs', :js do ...@@ -253,7 +253,7 @@ RSpec.describe 'Expand and collapse diffs', :js do
click_link('Expand all') click_link('Expand all')
# Wait for elements to appear to ensure full page reload # Wait for elements to appear to ensure full page reload
expect(page).to have_content('This diff was suppressed by a .gitattributes entry') expect(page).to have_content("File suppressed by a .gitattributes entry or the file's encoding is unsupported.")
expect(page).to have_content('This source diff could not be displayed because it is too large.') expect(page).to have_content('This source diff could not be displayed because it is too large.')
expect(page).to have_content('too_large_image.jpg') expect(page).to have_content('too_large_image.jpg')
find('.note-textarea') find('.note-textarea')
......
...@@ -174,4 +174,14 @@ RSpec.describe 'Diff file viewer', :js, :with_clean_rails_cache do ...@@ -174,4 +174,14 @@ RSpec.describe 'Diff file viewer', :js, :with_clean_rails_cache do
end end
end end
end end
context 'when the the encoding of the file is unsupported' do
before do
visit_commit('f05a98786e4274708e1fa118c7ad3a29d1d1b9a3')
end
it 'shows it is not diffable' do
expect(page).to have_content("File suppressed by a .gitattributes entry or the file's encoding is unsupported.")
end
end
end end
...@@ -23,7 +23,7 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiff do ...@@ -23,7 +23,7 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiff do
it 'does not highlight files marked as undiffable in .gitattributes' do it 'does not highlight files marked as undiffable in .gitattributes' do
allow_next_instance_of(Gitlab::Diff::File) do |instance| allow_next_instance_of(Gitlab::Diff::File) do |instance|
allow(instance).to receive(:diffable?).and_return(false) allow(instance).to receive(:diffable_by_attribute?).and_return(false)
end end
expect_next_instance_of(Gitlab::Diff::File) do |instance| expect_next_instance_of(Gitlab::Diff::File) do |instance|
......
...@@ -186,26 +186,46 @@ RSpec.describe Gitlab::Diff::File do ...@@ -186,26 +186,46 @@ RSpec.describe Gitlab::Diff::File do
end end
describe '#diffable?' do describe '#diffable?' do
let(:commit) { project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863') } context 'when attributes exist' do
let(:diffs) { commit.diffs } let(:commit) { project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863') }
let(:diffs) { commit.diffs }
before do before do
info_dir_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do info_dir_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
File.join(project.repository.path_to_repo, 'info') File.join(project.repository.path_to_repo, 'info')
end
FileUtils.mkdir(info_dir_path) unless File.exist?(info_dir_path)
File.write(File.join(info_dir_path, 'attributes'), "*.md -diff\n")
end end
FileUtils.mkdir(info_dir_path) unless File.exist?(info_dir_path) it "returns true for files that do not have attributes" do
File.write(File.join(info_dir_path, 'attributes'), "*.md -diff\n") diff_file = diffs.diff_file_with_new_path('LICENSE')
expect(diff_file.diffable?).to be_truthy
end
it "returns false for files that have been marked as not being diffable in attributes" do
diff_file = diffs.diff_file_with_new_path('README.md')
expect(diff_file.diffable?).to be_falsey
end
end end
it "returns true for files that do not have attributes" do context 'when the text has binary notice' do
diff_file = diffs.diff_file_with_new_path('LICENSE') let(:commit) { project.commit('f05a98786e4274708e1fa118c7ad3a29d1d1b9a3') }
expect(diff_file.diffable?).to be_truthy let(:diff_file) { commit.diffs.diff_file_with_new_path('VERSION') }
it "returns false" do
expect(diff_file.diffable?).to be_falsey
end
end end
it "returns false for files that have been marked as not being diffable in attributes" do context 'when the content is binary' do
diff_file = diffs.diff_file_with_new_path('README.md') let(:commit) { project.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
expect(diff_file.diffable?).to be_falsey let(:diff_file) { commit.diffs.diff_file_with_new_path('files/images/6049019_460s.jpg') }
it "returns true" do
expect(diff_file.diffable?).to be_truthy
end
end end
end end
...@@ -729,6 +749,18 @@ RSpec.describe Gitlab::Diff::File do ...@@ -729,6 +749,18 @@ RSpec.describe Gitlab::Diff::File do
end end
end end
context 'when the the encoding of the file is unsupported' do
let(:commit) { project.commit('f05a98786e4274708e1fa118c7ad3a29d1d1b9a3') }
let(:diff_file) { commit.diffs.diff_file_with_new_path('VERSION') }
it 'returns a Not Diffable viewer' do
expect(diff_file.simple_viewer).to be_a(DiffViewer::NotDiffable)
end
it { expect(diff_file.highlighted_diff_lines).to eq([]) }
it { expect(diff_file.parallel_diff_lines).to eq([]) }
end
describe '#diff_hunk' do describe '#diff_hunk' do
context 'when first line is a match' do context 'when first line is a match' do
let(:raw_diff) do let(:raw_diff) do
......
...@@ -146,6 +146,16 @@ eos ...@@ -146,6 +146,16 @@ eos
it { expect(parser.parse(nil)).to eq([]) } it { expect(parser.parse(nil)).to eq([]) }
end end
context 'when it is a binary notice' do
let(:diff) do
<<~END
Binary files a/test and b/test differ
END
end
it { expect(parser.parse(diff.each_line)).to eq([]) }
end
describe 'tolerates special diff markers in a content' do describe 'tolerates special diff markers in a content' do
it "counts lines correctly" do it "counts lines correctly" do
diff = <<~END diff = <<~END
......
...@@ -44,7 +44,7 @@ RSpec.describe ProtectedBranch::PushAccessLevel do ...@@ -44,7 +44,7 @@ RSpec.describe ProtectedBranch::PushAccessLevel do
let(:can_push) { true } let(:can_push) { true }
before_all do before_all do
project.add_guest(user) project.add_maintainer(user)
end end
context 'when this push_access_level is tied to a deploy key' do context 'when this push_access_level is tied to a deploy key' do
......
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