From 3de9282fba15dff726e233de4f4b957eddcfc1e2 Mon Sep 17 00:00:00 2001 From: Dhole Date: Tue, 18 May 2021 23:48:48 +0200 Subject: [PATCH] Sanitize float values in EXIF fields Read exposure as rational in EXIF internal parser --- api/scanner/exif/exif_parser_external.go | 34 +++++++++++++++++++++++ api/scanner/exif/exif_parser_internal.go | 7 +++-- api/scanner/exif/exif_test.go | 7 +++++ api/scanner/exif/test_data/bad-exif.jpg | Bin 0 -> 10563 bytes 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 api/scanner/exif/test_data/bad-exif.jpg diff --git a/api/scanner/exif/exif_parser_external.go b/api/scanner/exif/exif_parser_external.go index eb6d4d33..29940fea 100644 --- a/api/scanner/exif/exif_parser_external.go +++ b/api/scanner/exif/exif_parser_external.go @@ -2,6 +2,7 @@ package exif import ( "log" + "math" "time" "github.com/barasher/go-exiftool" @@ -28,6 +29,38 @@ func newExiftoolParser() (*externalExifParser, error) { }, nil } +// isFloatReal returns true when the float value represents a real number +// (different than +Inf, -Inf or NaN) +func isFloatReal(v float64) bool { + if math.IsInf(v, 1) { + return false + } else if math.IsInf(v, -1) { + return false + } else if math.IsNaN(v) { + return false + } + return true +} + +// sanitizeEXIF removes any EXIF float64 field that is not a real number (+Inf, +// -Inf or Nan) +func sanitizeEXIF(exif *models.MediaEXIF) { + if exif.Exposure != nil && !isFloatReal(*exif.Exposure) { + exif.Exposure = nil + } + if exif.Aperture != nil && !isFloatReal(*exif.Aperture) { + exif.Aperture = nil + } + if exif.FocalLength != nil && !isFloatReal(*exif.FocalLength) { + exif.FocalLength = nil + } + if (exif.GPSLatitude != nil && !isFloatReal(*exif.GPSLatitude)) || + (exif.GPSLongitude != nil && !isFloatReal(*exif.GPSLongitude)) { + exif.GPSLatitude = nil + exif.GPSLongitude = nil + } +} + func (p *externalExifParser) ParseExif(media_path string) (returnExif *models.MediaEXIF, returnErr error) { // ExifTool - No print conversion mode if p.et == nil { @@ -148,5 +181,6 @@ func (p *externalExifParser) ParseExif(media_path string) (returnExif *models.Me } returnExif = &newExif + sanitizeEXIF(returnExif) return } diff --git a/api/scanner/exif/exif_parser_internal.go b/api/scanner/exif/exif_parser_internal.go index 5897e6e5..1cb8a42f 100644 --- a/api/scanner/exif/exif_parser_internal.go +++ b/api/scanner/exif/exif_parser_internal.go @@ -62,11 +62,12 @@ func (p *internalExifParser) ParseExif(media_path string) (returnExif *models.Me newExif.DateShot = &date_utc } - exposure, err := exifTags.Get(exif.ExposureTime) + exposureTag, err := exifTags.Get(exif.ExposureTime) if err == nil { - exposureFloat, err := exposure.Float(0) + exposureRat, err := exposureTag.Rat(0) if err == nil { - newExif.Exposure = &exposureFloat + exposure, _ := exposureRat.Float64() + newExif.Exposure = &exposure } } diff --git a/api/scanner/exif/exif_test.go b/api/scanner/exif/exif_test.go index 538d7206..e586c2c6 100644 --- a/api/scanner/exif/exif_test.go +++ b/api/scanner/exif/exif_test.go @@ -51,6 +51,7 @@ func TestExifParsers(t *testing.T) { assert.EqualValues(t, *exif.Camera, "Canon EOS 600D") assert.EqualValues(t, *exif.Maker, "Canon") assert.WithinDuration(t, *exif.DateShot, time.Unix(1336318784, 0).UTC(), time.Minute) + assert.InDelta(t, *exif.Exposure, 1.0/4000.0, 0.0001) assert.EqualValues(t, *exif.Aperture, 6.3) assert.EqualValues(t, *exif.Iso, 800) assert.EqualValues(t, *exif.FocalLength, 300) @@ -66,6 +67,12 @@ func TestExifParsers(t *testing.T) { assert.Nil(t, exif) }, }, + { + path: "./test_data/bad-exif.jpg", + assert: func(t *testing.T, exif *models.MediaEXIF) { + assert.Nil(t, exif.Exposure) + }, + }, } for _, p := range parsers { diff --git a/api/scanner/exif/test_data/bad-exif.jpg b/api/scanner/exif/test_data/bad-exif.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62e5f900f5846292c3ad60cccc5309d24e43d426 GIT binary patch literal 10563 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 literal 0 HcmV?d00001