New upstream version 13.9.6+ds1

This commit is contained in:
Pirate Praveen 2021-04-15 22:33:27 +05:30
parent d6ce6a5a68
commit 459ea34293
19 changed files with 281 additions and 79 deletions

View file

@ -2,6 +2,14 @@
documentation](doc/development/changelog.md) for instructions on adding your own documentation](doc/development/changelog.md) for instructions on adding your own
entry. entry.
## 13.9.6 (2021-04-13)
### Security (2 changes)
- Clean only legitimate JPG and TIFF files.
- Update ruby-saml and rexml gems.
## 13.9.5 (2021-03-31) ## 13.9.5 (2021-03-31)
### Security (6 changes) ### Security (6 changes)

View file

@ -1 +1 @@
13.9.5 13.9.6

View file

@ -1 +1 @@
8.63.2 8.63.3

View file

@ -29,6 +29,8 @@ gem 'devise', '~> 4.7.2'
gem 'bcrypt', '3.1.12' gem 'bcrypt', '3.1.12'
gem 'doorkeeper', '~> 5.5.0.rc2' gem 'doorkeeper', '~> 5.5.0.rc2'
gem 'doorkeeper-openid_connect', '~> 1.7.5' gem 'doorkeeper-openid_connect', '~> 1.7.5'
gem 'rexml', '~> 3.2.5'
gem 'ruby-saml', '~> 1.12.1'
gem 'omniauth', '~> 1.8' gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0' gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9' gem 'omniauth-azure-oauth2', '~> 0.0.9'

View file

@ -998,7 +998,7 @@ GEM
retriable (3.1.2) retriable (3.1.2)
reverse_markdown (1.4.0) reverse_markdown (1.4.0)
nokogiri nokogiri
rexml (3.2.4) rexml (3.2.5)
rinku (2.0.0) rinku (2.0.0)
rotp (2.1.2) rotp (2.1.2)
rouge (3.26.0) rouge (3.26.0)
@ -1072,8 +1072,9 @@ GEM
ruby-magic-static (0.3.4) ruby-magic-static (0.3.4)
ruby-prof (1.3.1) ruby-prof (1.3.1)
ruby-progressbar (1.11.0) ruby-progressbar (1.11.0)
ruby-saml (1.7.2) ruby-saml (1.12.1)
nokogiri (>= 1.5.10) nokogiri (>= 1.10.5)
rexml
ruby-statistics (2.1.2) ruby-statistics (2.1.2)
ruby2_keywords (0.0.2) ruby2_keywords (0.0.2)
ruby_parser (3.15.0) ruby_parser (3.15.0)
@ -1498,6 +1499,7 @@ DEPENDENCIES
request_store (~> 1.5) request_store (~> 1.5)
responders (~> 3.0) responders (~> 3.0)
retriable (~> 3.1.2) retriable (~> 3.1.2)
rexml (~> 3.2.5)
rouge (~> 3.26.0) rouge (~> 3.26.0)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-parameterized rspec-parameterized
@ -1509,6 +1511,7 @@ DEPENDENCIES
ruby-magic-static (~> 0.3.4) ruby-magic-static (~> 0.3.4)
ruby-prof (~> 1.3.0) ruby-prof (~> 1.3.0)
ruby-progressbar (~> 1.10) ruby-progressbar (~> 1.10)
ruby-saml (~> 1.12.1)
ruby_parser (~> 3.15) ruby_parser (~> 3.15)
rubyzip (~> 2.0.0) rubyzip (~> 2.0.0)
rugged (~> 1.0.1) rugged (~> 1.0.1)

View file

@ -1 +1 @@
13.9.5 13.9.6

View file

@ -45,6 +45,7 @@ module Gitlab
ALLOWED_TAGS = WHITELISTED_TAGS + IGNORED_TAGS ALLOWED_TAGS = WHITELISTED_TAGS + IGNORED_TAGS
EXCLUDE_PARAMS = WHITELISTED_TAGS.map { |tag| "-#{tag}" } EXCLUDE_PARAMS = WHITELISTED_TAGS.map { |tag| "-#{tag}" }
ALLOWED_MIME_TYPES = %w(image/jpeg image/tiff).freeze
attr_reader :logger attr_reader :logger
@ -96,12 +97,12 @@ module Gitlab
end end
end end
private
def extra_tags(path) def extra_tags(path)
exif_tags(path).keys - ALLOWED_TAGS exif_tags(path).keys - ALLOWED_TAGS
end end
private
def remove_and_store(tmpdir, src_path, uploader) def remove_and_store(tmpdir, src_path, uploader)
exec_remove_exif!(src_path) exec_remove_exif!(src_path)
logger.info "#{upload_ref(uploader.upload)}: exif removed, storing" logger.info "#{upload_ref(uploader.upload)}: exif removed, storing"
@ -133,15 +134,26 @@ module Gitlab
# upload is stored into the file with the original name - this filename # upload is stored into the file with the original name - this filename
# is used by carrierwave when storing the file back to the storage # is used by carrierwave when storing the file back to the storage
filename = File.join(dir, uploader.filename) filename = File.join(dir, uploader.filename)
contents = uploader.read
check_for_allowed_types(contents)
File.open(filename, 'w') do |file| File.open(filename, 'w') do |file|
file.binmode file.binmode
file.write uploader.read file.write contents
end end
filename filename
end end
def check_for_allowed_types(contents)
mime_type = Gitlab::Utils::MimeType.from_string(contents)
unless ALLOWED_MIME_TYPES.include?(mime_type)
raise "File type #{mime_type} not supported. Only supports #{ALLOWED_MIME_TYPES.join(", ")}."
end
end
def upload_ref(upload) def upload_ref(upload)
"#{upload.id}:#{upload.path}" "#{upload.id}:#{upload.path}"
end end

View file

@ -4,6 +4,11 @@ require 'spec_helper'
RSpec.describe Gitlab::Sanitizers::Exif do RSpec.describe Gitlab::Sanitizers::Exif do
let(:sanitizer) { described_class.new } let(:sanitizer) { described_class.new }
let(:mime_type) { 'image/jpeg' }
before do
allow(Gitlab::Utils::MimeType).to receive(:from_string).and_return(mime_type)
end
describe '#batch_clean' do describe '#batch_clean' do
context 'with image uploads' do context 'with image uploads' do
@ -43,7 +48,7 @@ RSpec.describe Gitlab::Sanitizers::Exif do
end end
end end
it 'filters only jpg/tiff images' do it 'filters only jpg/tiff images by filename' do
create(:upload, path: 'filename.jpg') create(:upload, path: 'filename.jpg')
create(:upload, path: 'filename.jpeg') create(:upload, path: 'filename.jpeg')
create(:upload, path: 'filename.JPG') create(:upload, path: 'filename.JPG')
@ -53,12 +58,16 @@ RSpec.describe Gitlab::Sanitizers::Exif do
create(:upload, path: 'filename.txt') create(:upload, path: 'filename.txt')
expect(sanitizer).to receive(:clean).exactly(5).times expect(sanitizer).to receive(:clean).exactly(5).times
sanitizer.batch_clean sanitizer.batch_clean
end end
end end
describe '#clean' do describe '#clean' do
let(:uploader) { create(:upload, :with_file, :issuable_upload).retrieve_uploader } let(:uploader) { create(:upload, :with_file, :issuable_upload).retrieve_uploader }
let(:dry_run) { false }
subject { sanitizer.clean(uploader, dry_run: dry_run) }
context "no dry run" do context "no dry run" do
it "removes exif from the image" do it "removes exif from the image" do
@ -76,7 +85,7 @@ RSpec.describe Gitlab::Sanitizers::Exif do
[expected_args, 0] [expected_args, 0]
end end
sanitizer.clean(uploader, dry_run: false) subject
expect(uploader.upload.id).not_to eq(original_upload.id) expect(uploader.upload.id).not_to eq(original_upload.id)
expect(uploader.upload.path).to eq(original_upload.path) expect(uploader.upload.path).to eq(original_upload.path)
@ -89,23 +98,35 @@ RSpec.describe Gitlab::Sanitizers::Exif do
expect(sanitizer).not_to receive(:exec_remove_exif!) expect(sanitizer).not_to receive(:exec_remove_exif!)
expect(uploader).not_to receive(:store!) expect(uploader).not_to receive(:store!)
sanitizer.clean(uploader, dry_run: false) subject
end end
it "raises an error if the exiftool fails with an error" do it "raises an error if the exiftool fails with an error" do
expect(Gitlab::Popen).to receive(:popen).and_return(["error", 1]) expect(Gitlab::Popen).to receive(:popen).and_return(["error", 1])
expect { sanitizer.clean(uploader, dry_run: false) }.to raise_exception(RuntimeError, "failed to get exif tags: error") expect { subject }.to raise_exception(RuntimeError, "failed to get exif tags: error")
end
context 'for files that do not have the correct MIME type' do
let(:mime_type) { 'text/plain' }
it 'cleans only jpg/tiff images with the correct mime types' do
expect(sanitizer).not_to receive(:extra_tags)
expect { subject }.to raise_error(RuntimeError, /File type text\/plain not supported/)
end
end end
end end
context "dry run" do context "dry run" do
let(:dry_run) { true }
it "doesn't change the image" do it "doesn't change the image" do
expect(sanitizer).to receive(:extra_tags).and_return({ 'foo' => 'bar' }) expect(sanitizer).to receive(:extra_tags).and_return({ 'foo' => 'bar' })
expect(sanitizer).not_to receive(:exec_remove_exif!) expect(sanitizer).not_to receive(:exec_remove_exif!)
expect(uploader).not_to receive(:store!) expect(uploader).not_to receive(:store!)
sanitizer.clean(uploader, dry_run: true) subject
end end
end end
end end
@ -119,7 +140,7 @@ RSpec.describe Gitlab::Sanitizers::Exif do
expect(Gitlab::Popen).to receive(:popen).and_return([tags, 0]) expect(Gitlab::Popen).to receive(:popen).and_return([tags, 0])
expect(sanitizer.extra_tags('filename')).not_to be_empty expect(sanitizer.send(:extra_tags, 'filename')).not_to be_empty
end end
it "returns an empty list for file with only whitelisted and ignored tags" do it "returns an empty list for file with only whitelisted and ignored tags" do
@ -130,7 +151,7 @@ RSpec.describe Gitlab::Sanitizers::Exif do
expect(Gitlab::Popen).to receive(:popen).and_return([tags, 0]) expect(Gitlab::Popen).to receive(:popen).and_return([tags, 0])
expect(sanitizer.extra_tags('some file')).to be_empty expect(sanitizer.send(:extra_tags, 'some file')).to be_empty
end end
end end
end end

View file

@ -1,5 +1,11 @@
# Changelog for gitlab-workhorse # Changelog for gitlab-workhorse
## v8.63.3
### Security
- Check image content type before running exiftool in workhorse
https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/
## v8.63.2 ## v8.63.2
### Security ### Security

View file

@ -1 +1 @@
8.63.2 8.63.3

View file

@ -29,6 +29,7 @@ require (
gitlab.com/gitlab-org/gitaly v1.74.0 gitlab.com/gitlab-org/gitaly v1.74.0
gitlab.com/gitlab-org/labkit v1.0.0 gitlab.com/gitlab-org/labkit v1.0.0
gocloud.dev v0.21.1-0.20201223184910-5094f54ed8bb gocloud.dev v0.21.1-0.20201223184910-5094f54ed8bb
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
golang.org/x/lint v0.0.0-20200302205851-738671d3881b golang.org/x/lint v0.0.0-20200302205851-738671d3881b
golang.org/x/net v0.0.0-20201224014010-6772e930b67b golang.org/x/net v0.0.0-20201224014010-6772e930b67b
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 // indirect golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 // indirect

View file

@ -22,6 +22,14 @@ type cleaner struct {
eof bool eof bool
} }
type FileType int
const (
TypeUnknown FileType = iota
TypeJPEG
TypeTIFF
)
func NewCleaner(ctx context.Context, stdin io.Reader) (io.ReadCloser, error) { func NewCleaner(ctx context.Context, stdin io.Reader) (io.ReadCloser, error) {
c := &cleaner{ctx: ctx} c := &cleaner{ctx: ctx}
@ -100,8 +108,16 @@ func (c *cleaner) startProcessing(stdin io.Reader) error {
return nil return nil
} }
func IsExifFile(filename string) bool { func FileTypeFromSuffix(filename string) FileType {
filenameMatch := regexp.MustCompile(`(?i)\.(jpg|jpeg|tiff)$`) jpegMatch := regexp.MustCompile(`(?i)^[^\n]*\.(jpg|jpeg)$`)
if jpegMatch.MatchString(filename) {
return TypeJPEG
}
return filenameMatch.MatchString(filename) tiffMatch := regexp.MustCompile(`(?i)^[^\n]*\.tiff$`)
if tiffMatch.MatchString(filename) {
return TypeTIFF
}
return TypeUnknown
} }

View file

@ -11,39 +11,57 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestIsExifFile(t *testing.T) { func TestFileTypeFromSuffix(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
expected bool expected FileType
}{ }{
{ {
name: "/full/path.jpg", name: "/full/path.jpg",
expected: true, expected: TypeJPEG,
}, },
{ {
name: "path.jpeg", name: "path.jpeg",
expected: true, expected: TypeJPEG,
}, },
{ {
name: "path.tiff", name: "path.tiff",
expected: true, expected: TypeTIFF,
}, },
{ {
name: "path.JPG", name: "path.JPG",
expected: true, expected: TypeJPEG,
}, },
{ {
name: "path.tar", name: "path.tar",
expected: false, expected: TypeUnknown,
}, },
{ {
name: "path", name: "path",
expected: false, expected: TypeUnknown,
},
{
name: "something.jpg.py",
expected: TypeUnknown,
},
{
name: "something.py.jpg",
expected: TypeJPEG,
},
{
name: `something.jpg
.py`,
expected: TypeUnknown,
},
{
name: `something.something
.jpg`,
expected: TypeUnknown,
}, },
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
require.Equal(t, test.expected, IsExifFile(test.name)) require.Equal(t, test.expected, FileTypeFromSuffix(test.name))
}) })
} }
} }

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1 @@
invalid data

View file

@ -8,12 +8,15 @@ import (
"io/ioutil" "io/ioutil"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"os"
"strings" "strings"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promauto"
"gitlab.com/gitlab-org/labkit/log" "gitlab.com/gitlab-org/labkit/log"
"golang.org/x/image/tiff"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/api" "gitlab.com/gitlab-org/gitlab-workhorse/internal/api"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/filestore" "gitlab.com/gitlab-org/gitlab-workhorse/internal/filestore"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/lsif_transformer/parser" "gitlab.com/gitlab-org/gitlab-workhorse/internal/lsif_transformer/parser"
@ -122,9 +125,11 @@ func (rew *rewriter) handleFilePart(ctx context.Context, name string, p *multipa
var inputReader io.ReadCloser var inputReader io.ReadCloser
var err error var err error
imageType := exif.FileTypeFromSuffix(filename)
switch { switch {
case exif.IsExifFile(filename): case imageType != exif.TypeUnknown:
inputReader, err = handleExifUpload(ctx, p, filename) inputReader, err = handleExifUpload(ctx, p, filename, imageType)
if err != nil { if err != nil {
return err return err
} }
@ -164,12 +169,48 @@ func (rew *rewriter) handleFilePart(ctx context.Context, name string, p *multipa
return rew.filter.ProcessFile(ctx, name, fh, rew.writer) return rew.filter.ProcessFile(ctx, name, fh, rew.writer)
} }
func handleExifUpload(ctx context.Context, r io.Reader, filename string) (io.ReadCloser, error) { func handleExifUpload(ctx context.Context, r io.Reader, filename string, imageType exif.FileType) (io.ReadCloser, error) {
tmpfile, err := ioutil.TempFile("", "exifremove")
if err != nil {
return nil, err
}
go func() {
<-ctx.Done()
tmpfile.Close()
}()
if err := os.Remove(tmpfile.Name()); err != nil {
return nil, err
}
_, err = io.Copy(tmpfile, r)
if err != nil {
return nil, err
}
tmpfile.Seek(0, io.SeekStart)
isValidType := false
switch imageType {
case exif.TypeJPEG:
isValidType = isJPEG(tmpfile)
case exif.TypeTIFF:
isValidType = isTIFF(tmpfile)
}
tmpfile.Seek(0, io.SeekStart)
if !isValidType {
log.WithContextFields(ctx, log.Fields{
"filename": filename,
"imageType": imageType,
}).Print("invalid content type, not running exiftool")
return tmpfile, nil
}
log.WithContextFields(ctx, log.Fields{ log.WithContextFields(ctx, log.Fields{
"filename": filename, "filename": filename,
}).Print("running exiftool to remove any metadata") }).Print("running exiftool to remove any metadata")
cleaner, err := exif.NewCleaner(ctx, r) cleaner, err := exif.NewCleaner(ctx, tmpfile)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -177,6 +218,29 @@ func handleExifUpload(ctx context.Context, r io.Reader, filename string) (io.Rea
return cleaner, nil return cleaner, nil
} }
func isTIFF(r io.Reader) bool {
_, err := tiff.Decode(r)
if err == nil {
return true
}
if _, unsupported := err.(tiff.UnsupportedError); unsupported {
return true
}
return false
}
func isJPEG(r io.Reader) bool {
// Only the first 512 bytes are used to sniff the content type.
buf, err := ioutil.ReadAll(io.LimitReader(r, 512))
if err != nil {
return false
}
return http.DetectContentType(buf) == "image/jpeg"
}
func handleLsifUpload(ctx context.Context, reader io.Reader, tempPath, filename string, preauth *api.Response) (io.ReadCloser, error) { func handleLsifUpload(ctx context.Context, reader io.Reader, tempPath, filename string, preauth *api.Response) (io.ReadCloser, error) {
parserConfig := parser.Config{ parserConfig := parser.Config{
TempPath: tempPath, TempPath: tempPath,

View file

@ -0,0 +1,43 @@
package upload
import (
"os"
"testing"
"github.com/stretchr/testify/require"
)
func TestImageTypeRecongition(t *testing.T) {
tests := []struct {
filename string
isJPEG bool
isTIFF bool
}{
{
filename: "exif/testdata/sample_exif.jpg",
isJPEG: true,
isTIFF: false,
}, {
filename: "exif/testdata/sample_exif.tiff",
isJPEG: false,
isTIFF: true,
}, {
filename: "exif/testdata/sample_exif_corrupted.jpg",
isJPEG: true,
isTIFF: false,
}, {
filename: "exif/testdata/sample_exif_invalid.jpg",
isJPEG: false,
isTIFF: false,
},
}
for _, test := range tests {
t.Run(test.filename, func(t *testing.T) {
input, err := os.Open(test.filename)
require.NoError(t, err)
require.Equal(t, test.isJPEG, isJPEG(input))
require.Equal(t, test.isTIFF, isTIFF(input))
})
}
}

View file

@ -358,26 +358,10 @@ func TestInvalidFileNames(t *testing.T) {
} }
func TestUploadHandlerRemovingExif(t *testing.T) { func TestUploadHandlerRemovingExif(t *testing.T) {
tempPath, err := ioutil.TempDir("", "uploads")
require.NoError(t, err)
defer os.RemoveAll(tempPath)
var buffer bytes.Buffer
content, err := ioutil.ReadFile("exif/testdata/sample_exif.jpg") content, err := ioutil.ReadFile("exif/testdata/sample_exif.jpg")
require.NoError(t, err) require.NoError(t, err)
writer := multipart.NewWriter(&buffer) runUploadTest(t, content, "sample_exif.jpg", 200, func(w http.ResponseWriter, r *http.Request) {
file, err := writer.CreateFormFile("file", "test.jpg")
require.NoError(t, err)
_, err = file.Write(content)
require.NoError(t, err)
err = writer.Close()
require.NoError(t, err)
ts := testhelper.TestServerWithHandler(regexp.MustCompile(`/url/path\z`), func(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(100000) err := r.ParseMultipartForm(100000)
require.NoError(t, err) require.NoError(t, err)
@ -389,30 +373,54 @@ func TestUploadHandlerRemovingExif(t *testing.T) {
w.WriteHeader(200) w.WriteHeader(200)
fmt.Fprint(w, "RESPONSE") fmt.Fprint(w, "RESPONSE")
}) })
defer ts.Close()
httpRequest, err := http.NewRequest("POST", ts.URL+"/url/path", &buffer)
require.NoError(t, err)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
httpRequest = httpRequest.WithContext(ctx)
httpRequest.ContentLength = int64(buffer.Len())
httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
response := httptest.NewRecorder()
handler := newProxy(ts.URL)
apiResponse := &api.Response{TempPath: tempPath}
preparer := &DefaultPreparer{}
opts, _, err := preparer.Prepare(apiResponse)
require.NoError(t, err)
HandleFileUploads(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, 200, response.Code)
} }
func TestUploadHandlerRemovingInvalidExif(t *testing.T) { func TestUploadHandlerRemovingExifTiff(t *testing.T) {
content, err := ioutil.ReadFile("exif/testdata/sample_exif.tiff")
require.NoError(t, err)
runUploadTest(t, content, "sample_exif.tiff", 200, func(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(100000)
require.NoError(t, err)
size, err := strconv.Atoi(r.FormValue("file.size"))
require.NoError(t, err)
require.True(t, size < len(content), "Expected the file to be smaller after removal of exif")
require.True(t, size > 0, "Expected to receive not empty file")
w.WriteHeader(200)
fmt.Fprint(w, "RESPONSE")
})
}
func TestUploadHandlerRemovingExifInvalidContentType(t *testing.T) {
content, err := ioutil.ReadFile("exif/testdata/sample_exif_invalid.jpg")
require.NoError(t, err)
runUploadTest(t, content, "sample_exif_invalid.jpg", 200, func(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(100000)
require.NoError(t, err)
output, err := ioutil.ReadFile(r.FormValue("file.path"))
require.NoError(t, err)
require.Equal(t, content, output, "Expected the file to be same as before")
w.WriteHeader(200)
fmt.Fprint(w, "RESPONSE")
})
}
func TestUploadHandlerRemovingExifCorruptedFile(t *testing.T) {
content, err := ioutil.ReadFile("exif/testdata/sample_exif_corrupted.jpg")
require.NoError(t, err)
runUploadTest(t, content, "sample_exif_corrupted.jpg", 422, func(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(100000)
require.Error(t, err)
})
}
func runUploadTest(t *testing.T, image []byte, filename string, httpCode int, tsHandler func(http.ResponseWriter, *http.Request)) {
tempPath, err := ioutil.TempDir("", "uploads") tempPath, err := ioutil.TempDir("", "uploads")
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tempPath) defer os.RemoveAll(tempPath)
@ -420,17 +428,16 @@ func TestUploadHandlerRemovingInvalidExif(t *testing.T) {
var buffer bytes.Buffer var buffer bytes.Buffer
writer := multipart.NewWriter(&buffer) writer := multipart.NewWriter(&buffer)
file, err := writer.CreateFormFile("file", "test.jpg") file, err := writer.CreateFormFile("file", filename)
require.NoError(t, err)
_, err = file.Write(image)
require.NoError(t, err) require.NoError(t, err)
fmt.Fprint(file, "this is not valid image data")
err = writer.Close() err = writer.Close()
require.NoError(t, err) require.NoError(t, err)
ts := testhelper.TestServerWithHandler(regexp.MustCompile(`/url/path\z`), func(w http.ResponseWriter, r *http.Request) { ts := testhelper.TestServerWithHandler(regexp.MustCompile(`/url/path\z`), tsHandler)
err := r.ParseMultipartForm(100000)
require.Error(t, err)
})
defer ts.Close() defer ts.Close()
httpRequest, err := http.NewRequest("POST", ts.URL+"/url/path", &buffer) httpRequest, err := http.NewRequest("POST", ts.URL+"/url/path", &buffer)
@ -451,7 +458,7 @@ func TestUploadHandlerRemovingInvalidExif(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
HandleFileUploads(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts) HandleFileUploads(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, 422, response.Code) require.Equal(t, httpCode, response.Code)
} }
func newProxy(url string) *proxy.Proxy { func newProxy(url string) *proxy.Proxy {