summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-30 11:40:06 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-30 11:40:06 +0000
commit6b3f0a47a2410b5a2a9fc1e78ff2d006b05a3e05 (patch)
treebd4e2f1b1eabdca0f546685e9df8b5a0b649940c /lib
parent76b84b42f64b8009cc181d5da0c656a8a521986d (diff)
downloadgitlab-ce-6b3f0a47a2410b5a2a9fc1e78ff2d006b05a3e05.tar.gz
Add latest changes from gitlab-org/security/gitlab@14-0-stable-ee
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/diff/file.rb11
-rw-r--r--lib/gitlab/diff/parser.rb2
-rw-r--r--lib/gitlab/git/diff.rb11
-rw-r--r--lib/gitlab/http.rb18
4 files changed, 36 insertions, 6 deletions
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index dcd4bbdabf5..35581952f4a 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -250,7 +250,7 @@ module Gitlab
end
def diffable?
- repository.attributes(file_path).fetch('diff') { true }
+ diffable_by_attribute? && !text_with_binary_notice?
end
def binary_in_repo?
@@ -366,6 +366,15 @@ module Gitlab
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)
return unless sha
diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
index 4a47e4b80b6..adb711ca89f 100644
--- a/lib/gitlab/diff/parser.rb
+++ b/lib/gitlab/diff/parser.rb
@@ -6,7 +6,7 @@ module Gitlab
include Enumerable
def parse(lines, diff_file: nil)
- return [] if lines.blank?
+ return [] if lines.blank? || Git::Diff.has_binary_notice?(lines.first)
@lines = lines
line_obj_index = 0
diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb
index 53df0b7b389..8325eadce2f 100644
--- a/lib/gitlab/git/diff.rb
+++ b/lib/gitlab/git/diff.rb
@@ -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
+ BINARY_NOTICE_PATTERN = %r(Binary files a\/(.*) and b\/(.*) differ).freeze
+
class << self
def between(repo, head, base, options = {}, *paths)
straight = options.delete(:straight) || false
@@ -131,8 +133,13 @@ module Gitlab
def patch_hard_limit_bytes
Gitlab::CurrentSettings.diff_max_patch_bytes
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)
@expanded = expanded
@@ -215,7 +222,7 @@ module Gitlab
end
def has_binary_notice?
- @diff.start_with?('Binary')
+ self.class.has_binary_notice?(@diff)
end
private
diff --git a/lib/gitlab/http.rb b/lib/gitlab/http.rb
index be87dcc0ff9..7e45cd216f5 100644
--- a/lib/gitlab/http.rb
+++ b/lib/gitlab/http.rb
@@ -8,9 +8,10 @@ module Gitlab
class HTTP
BlockedUrlError = Class.new(StandardError)
RedirectionTooDeep = Class.new(StandardError)
+ ReadTotalTimeout = Class.new(Net::ReadTimeout)
HTTP_TIMEOUT_ERRORS = [
- Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout
+ Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout, Gitlab::HTTP::ReadTotalTimeout
].freeze
HTTP_ERRORS = HTTP_TIMEOUT_ERRORS + [
SocketError, OpenSSL::SSL::SSLError, OpenSSL::OpenSSLError,
@@ -23,6 +24,7 @@ module Gitlab
read_timeout: 20,
write_timeout: 30
}.freeze
+ DEFAULT_READ_TOTAL_TIMEOUT = 20.seconds
include HTTParty # rubocop:disable Gitlab/HTTParty
@@ -41,7 +43,19 @@ module Gitlab
options
end
- httparty_perform_request(http_method, path, options_with_timeouts, &block)
+ unless options.has_key?(:use_read_total_timeout)
+ return httparty_perform_request(http_method, path, options_with_timeouts, &block)
+ end
+
+ start_time = Gitlab::Metrics::System.monotonic_time
+ read_total_timeout = options.fetch(:timeout, DEFAULT_READ_TOTAL_TIMEOUT)
+
+ httparty_perform_request(http_method, path, options_with_timeouts) do |fragment|
+ elapsed = Gitlab::Metrics::System.monotonic_time - start_time
+ raise ReadTotalTimeout, "Request timed out after #{elapsed} seconds" if elapsed > read_total_timeout
+
+ block.call fragment if block
+ end
rescue HTTParty::RedirectionTooDeep
raise RedirectionTooDeep
rescue *HTTP_ERRORS => e