summaryrefslogtreecommitdiff
path: root/workhorse/internal/upload/rewrite.go
diff options
context:
space:
mode:
Diffstat (limited to 'workhorse/internal/upload/rewrite.go')
-rw-r--r--workhorse/internal/upload/rewrite.go72
1 files changed, 68 insertions, 4 deletions
diff --git a/workhorse/internal/upload/rewrite.go b/workhorse/internal/upload/rewrite.go
index e51604c6ed9..ba6bd0e501a 100644
--- a/workhorse/internal/upload/rewrite.go
+++ b/workhorse/internal/upload/rewrite.go
@@ -8,12 +8,15 @@ import (
"io/ioutil"
"mime/multipart"
"net/http"
+ "os"
"strings"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"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/filestore"
"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 err error
+
+ imageType := exif.FileTypeFromSuffix(filename)
switch {
- case exif.IsExifFile(filename):
- inputReader, err = handleExifUpload(ctx, p, filename)
+ case imageType != exif.TypeUnknown:
+ inputReader, err = handleExifUpload(ctx, p, filename, imageType)
if err != nil {
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)
}
-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{
"filename": filename,
}).Print("running exiftool to remove any metadata")
- cleaner, err := exif.NewCleaner(ctx, r)
+ cleaner, err := exif.NewCleaner(ctx, tmpfile)
if err != nil {
return nil, err
}
@@ -177,6 +218,29 @@ func handleExifUpload(ctx context.Context, r io.Reader, filename string) (io.Rea
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) {
parserConfig := parser.Config{
TempPath: tempPath,