uploads: fix "ArgumentError: string contains null byte" error
Fix an error when trying to upload a file larger than the file size limit. In this case we tried to dump the whole HTTP response into the error message, which included the binary file itself, which caused this exception because it contained null bytes.
This commit is contained in:
@@ -148,12 +148,12 @@ module Danbooru
|
|||||||
response = get(url)
|
response = get(url)
|
||||||
|
|
||||||
raise DownloadError, "Downloading #{response.uri} failed with code #{response.status}" if response.status != 200
|
raise DownloadError, "Downloading #{response.uri} failed with code #{response.status}" if response.status != 200
|
||||||
raise FileTooLargeError, response if @max_size && response.content_length.to_i > @max_size
|
raise FileTooLargeError, "File size too large (size: #{response.content_length.to_i.to_formatted_s(:human_size)}; max size: #{@max_size.to_formatted_s(:human_size)})" if @max_size && response.content_length.to_i > @max_size
|
||||||
|
|
||||||
size = 0
|
size = 0
|
||||||
response.body.each do |chunk|
|
response.body.each do |chunk|
|
||||||
size += chunk.size
|
size += chunk.size
|
||||||
raise FileTooLargeError if @max_size && size > @max_size
|
raise FileTooLargeError, "File size too large (max size: #{@max_size.to_formatted_s(:human_size)})" if @max_size && size > @max_size
|
||||||
file.write(chunk)
|
file.write(chunk)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class MediaAsset < ApplicationRecord
|
|||||||
|
|
||||||
validates :md5, uniqueness: { conditions: -> { where(status: [:processing, :active]) } }
|
validates :md5, uniqueness: { conditions: -> { where(status: [:processing, :active]) } }
|
||||||
validates :file_ext, inclusion: { in: %w[jpg png gif mp4 webm swf zip], message: "Not an image or video" }
|
validates :file_ext, inclusion: { in: %w[jpg png gif mp4 webm swf zip], message: "Not an image or video" }
|
||||||
validates :file_size, numericality: { less_than_or_equal_to: Danbooru.config.max_file_size }
|
validates :file_size, numericality: { less_than_or_equal_to: Danbooru.config.max_file_size, message: ->(asset, _) { "too large (size: #{asset.file_size.to_formatted_s(:human_size)}; max size: #{Danbooru.config.max_file_size.to_formatted_s(:human_size)})" } }
|
||||||
validates :duration, numericality: { less_than_or_equal_to: MAX_VIDEO_DURATION, message: "must be less than #{MAX_VIDEO_DURATION} seconds", allow_nil: true }, on: :create # XXX should allow admins to bypass
|
validates :duration, numericality: { less_than_or_equal_to: MAX_VIDEO_DURATION, message: "must be less than #{MAX_VIDEO_DURATION} seconds", allow_nil: true }, on: :create # XXX should allow admins to bypass
|
||||||
validate :validate_resolution, on: :create
|
validate :validate_resolution, on: :create
|
||||||
|
|
||||||
|
|||||||
@@ -177,18 +177,32 @@ class UploadsControllerTest < ActionDispatch::IntegrationTest
|
|||||||
assert_match("Not an image or video", Upload.last.error)
|
assert_match("Not an image or video", Upload.last.error)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "fail if the file size is too large" do
|
context "for a file larger than the file size limit" do
|
||||||
skip "flaky test"
|
setup do
|
||||||
Danbooru.config.stubs(:max_file_size).returns(1.kilobyte)
|
skip "flaky test"
|
||||||
|
Danbooru.config.stubs(:max_file_size).returns(1.kilobyte)
|
||||||
|
end
|
||||||
|
|
||||||
file = Rack::Test::UploadedFile.new("test/files/test.jpg")
|
should "fail for a direct file upload" do
|
||||||
post_auth uploads_path(format: :json), @user, params: { upload: { file: file }}
|
create_upload!("test/files/test.jpg", user: @user)
|
||||||
perform_enqueued_jobs
|
|
||||||
|
|
||||||
assert_response 201
|
assert_response 201
|
||||||
assert_match("File size must be less than or equal to", Upload.last.error)
|
assert_match("File size too large", Upload.last.error)
|
||||||
|
end
|
||||||
|
|
||||||
Danbooru.config.unstub(:max_file_size)
|
should "fail for a source upload with a Content-Length header" do
|
||||||
|
create_upload!("https://nghttp2.org/httpbin/bytes/2000", user: @user)
|
||||||
|
|
||||||
|
assert_response 201
|
||||||
|
assert_match("File size too large", Upload.last.error)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "fail for a source upload without a Content-Length header" do
|
||||||
|
create_upload!("https://nghttp2.org/httpbin/stream-bytes/2000", user: @user)
|
||||||
|
|
||||||
|
assert_response 201
|
||||||
|
assert_match("File size too large", Upload.last.error)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "for a corrupted image" do
|
context "for a corrupted image" do
|
||||||
|
|||||||
Reference in New Issue
Block a user