diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-30 11:40:06 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-30 11:40:06 +0000 |
commit | 6b3f0a47a2410b5a2a9fc1e78ff2d006b05a3e05 (patch) | |
tree | bd4e2f1b1eabdca0f546685e9df8b5a0b649940c /lib | |
parent | 76b84b42f64b8009cc181d5da0c656a8a521986d (diff) | |
download | gitlab-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.rb | 11 | ||||
-rw-r--r-- | lib/gitlab/diff/parser.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/git/diff.rb | 11 | ||||
-rw-r--r-- | lib/gitlab/http.rb | 18 |
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 |