Skip to content

Commit 741c616

Browse files
fkleonbep
authored andcommitted
Allow invalid encoding in EXIF UserComment field
However, emit a warning in this case.
1 parent b26d2ec commit 741c616

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[{
2+
"SourceFile": "../testdata/images/invalid-encoding-usercomment.jpg",
3+
"ExifTool": {
4+
"ExifToolVersion": 12.76,
5+
"Warning": "Invalid EXIF text encoding for UserComment"
6+
},
7+
"File": {
8+
"FileName": "invalid-encoding-usercomment.jpg",
9+
"Directory": "../testdata/images",
10+
"FileSize": 381,
11+
"FilePermissions": 100644,
12+
"FileType": "JPEG",
13+
"FileTypeExtension": "JPG",
14+
"MIMEType": "image/jpeg",
15+
"ExifByteOrder": "MM",
16+
"ImageWidth": 1,
17+
"ImageHeight": 1,
18+
"EncodingProcess": 0,
19+
"BitsPerSample": 8,
20+
"ColorComponents": 1
21+
},
22+
"JFIF": {
23+
"JFIFVersion": "1 1",
24+
"ResolutionUnit": 0,
25+
"XResolution": 1,
26+
"YResolution": 1
27+
},
28+
"EXIF": {
29+
"UserComment": "UserComment"
30+
}
31+
}]

helpers.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,12 @@ func (c vc) convertUserComment(ctx valueConverterContext, v any) any {
296296
// UserComment tag is identified based on an ID code in a fixed 8-byte area at the start of the tag data area.
297297
b, ok := typeAssert[[]byte](ctx, v)
298298
if !ok {
299+
// Handle plain string user comment (which is against spec; but commonly done)
300+
// Exiftool prints a warning but returns the string as-is.
301+
// See https://github.com/exiftool/exiftool/blob/13.27/lib/Image/ExifTool/Exif.pm#L5483
302+
if text, ok := typeAssert[string](ctx, v); ok {
303+
return text
304+
}
299305
return ""
300306
}
301307
if len(b) < 8 {

imagemeta_test.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,37 @@ func TestDecodeCorrupt(t *testing.T) {
173173
}
174174
}
175175

176+
func TestDecodeUserCommentWithInvalidEncoding(t *testing.T) {
177+
c := qt.New(t)
178+
179+
img, err := os.Open(filepath.Join("testdata", "images", "invalid-encoding-usercomment.jpg"))
180+
c.Assert(err, qt.IsNil)
181+
defer img.Close()
182+
183+
var userComment any
184+
handleTag := func(ti imagemeta.TagInfo) error {
185+
if ti.Tag == "UserComment" {
186+
userComment = ti.Value
187+
}
188+
return nil
189+
}
190+
191+
var warning error
192+
warnf := func(format string, args ...any) {
193+
warning = fmt.Errorf(format, args...)
194+
}
195+
196+
err = imagemeta.Decode(imagemeta.Options{R: img, ImageFormat: imagemeta.JPEG, HandleTag: handleTag, Sources: imagemeta.EXIF, Warnf: warnf})
197+
c.Assert(err, qt.IsNil)
198+
199+
// Expect user comment to be decoded
200+
c.Assert(userComment, qt.IsNotNil)
201+
c.Assert(userComment, eq, "UserComment")
202+
203+
// But with a warning about incorrect type
204+
c.Assert(warning, qt.ErrorMatches, "UserComment: expected \\[\\]uint8, got string")
205+
}
206+
176207
func TestDecodeCustomXMPHandler(t *testing.T) {
177208
c := qt.New(t)
178209

@@ -888,7 +919,8 @@ func withTestDataFile(t testing.TB, fn func(path string, info os.FileInfo, err e
888919
}
889920

890921
var goldenSkip = map[string]bool{
891-
"goexif/geodegrees_as_string.jpg": true, // The file has many EXIF errors. I think we do a better job than exiftools, but there are some differences.
922+
"goexif/geodegrees_as_string.jpg": true, // The file has many EXIF errors. I think we do a better job than exiftools, but there are some differences.
923+
"invalid-encoding-usercomment.jpg": true, // The file has an EXIF error that produces a warning in imagemeta. It's tested separately.
892924
}
893925

894926
var isSpaceDelimitedFloatRe = regexp.MustCompile(`^(\d+\.\d+) (\d+\.\d+)`)
381 Bytes
Loading

0 commit comments

Comments
 (0)