Skip to content

Commit a99eaf4

Browse files
committed
Catch exceptions when reading EXIF metadata
If the EXIF data is corrupted, this will cleanly return rather than crashing with abort(). Most of these instances likely can't ever be triggered without timing attacks that replace the image file during operation of the program, but better safe than sorry.
1 parent 5b0224d commit a99eaf4

File tree

7 files changed

+54
-6
lines changed

7 files changed

+54
-6
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ jobs:
126126
cxx: g++
127127
target: all
128128
install_target: install install-po install-desktop-file
129-
failing_tests: 16
129+
failing_tests: 17
130130
- name: sanitize
131131
cc: clang
132132
gtk: 3

exif-gps.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,20 @@ char* ReadExifData(const char* File, int* IncludesGPS, double* Lat, double* Long
120120
DEBUGLOG("Failed to open file %s.\n", File);
121121
return NULL;
122122
}
123-
Image->readMetadata();
124123
if (Image.get() == NULL)
125124
{
126125
DEBUGLOG("Failed to read file %s %s.\n",
127126
File, Exiv2::strError().c_str());
128127
return NULL;
129128
}
130129

130+
try {
131+
Image->readMetadata();
132+
} catch (Exiv2::Error& e) {
133+
DEBUGLOG("Failed to read EXIF metadata in %s.\n", File);
134+
return NULL;
135+
}
136+
131137
Exiv2::ExifData &ExifRead = Image->exifData();
132138

133139
// Read the tag out.
@@ -288,14 +294,20 @@ char* ReadGPSTimestamp(const char* File, char* DateStamp, char* TimeStamp, int*
288294
DEBUGLOG("Failed to open file %s.\n", File);
289295
return NULL;
290296
}
291-
Image->readMetadata();
292297
if (Image.get() == NULL)
293298
{
294299
DEBUGLOG("Failed to read file %s %s.\n",
295300
File, Exiv2::strError().c_str());
296301
return NULL;
297302
}
298303

304+
try {
305+
Image->readMetadata();
306+
} catch (Exiv2::Error& e) {
307+
DEBUGLOG("Failed to read EXIF metadata in %s.\n", File);
308+
return NULL;
309+
}
310+
299311
Exiv2::ExifData &ExifRead = Image->exifData();
300312

301313
// Read the tag out.
@@ -458,7 +470,6 @@ int WriteGPSData(const char* File, const struct GPSPoint* Point,
458470
DEBUGLOG("Failed to open file %s.\n", File);
459471
return 0;
460472
}
461-
Image->readMetadata();
462473
if (Image.get() == NULL)
463474
{
464475
// It failed if we got here.
@@ -467,6 +478,13 @@ int WriteGPSData(const char* File, const struct GPSPoint* Point,
467478
return 0;
468479
}
469480

481+
try {
482+
Image->readMetadata();
483+
} catch (Exiv2::Error& e) {
484+
DEBUGLOG("Failed to read EXIF metadata in %s.\n", File);
485+
return 0;
486+
}
487+
470488
Exiv2::ExifData &ExifToWrite = Image->exifData();
471489

472490
// Make sure we're starting from a clean GPS IFD.
@@ -661,7 +679,6 @@ int WriteFixedDatestamp(const char* File, struct timespec Time)
661679
DEBUGLOG("Failed to open file %s.\n", File);
662680
return 0;
663681
}
664-
Image->readMetadata();
665682
if (Image.get() == NULL)
666683
{
667684
// It failed if we got here.
@@ -670,6 +687,13 @@ int WriteFixedDatestamp(const char* File, struct timespec Time)
670687
return 0;
671688
}
672689

690+
try {
691+
Image->readMetadata();
692+
} catch (Exiv2::Error& e) {
693+
DEBUGLOG("Failed to read EXIF metadata in %s.\n", File);
694+
return 0;
695+
}
696+
673697
Exiv2::ExifData &ExifToWrite = Image->exifData();
674698

675699
const struct tm TimeStamp = *gmtime(&Time.tv_sec);
@@ -723,7 +747,6 @@ int RemoveGPSExif(const char* File, int NoChangeMtime, int NoWriteExif)
723747
DEBUGLOG("Failed to open file %s.\n", File);
724748
return 0;
725749
}
726-
Image->readMetadata();
727750
if (Image.get() == NULL)
728751
{
729752
// It failed if we got here.
@@ -732,6 +755,13 @@ int RemoveGPSExif(const char* File, int NoChangeMtime, int NoWriteExif)
732755
return 0;
733756
}
734757

758+
try {
759+
Image->readMetadata();
760+
} catch (Exiv2::Error& e) {
761+
DEBUGLOG("Failed to read EXIF metadata in %s.\n", File);
762+
return 0;
763+
}
764+
735765
Exiv2::ExifData &ExifInfo = Image->exifData();
736766

737767
if (ExifInfo.count() == 0)

tests/data/test198.param

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
TITLE='Show GPS data on file with corrupt EXIF'
2+
COMMAND='$PROGRAM -s "$STAGINGDIR/badexif.jpg" > "$OUTFILE" 2>&1'
3+
RESULTCODE=1
4+
SEDCOMMAND='s@^.*/@@' # strip path

tests/data/test198.result

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
badexif.jpg: No EXIF data.

tests/data/test199.param

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
TITLE='Correlate a file with corrupted EXIF with --replace'
2+
PRECOMMAND='cat "$STAGINGDIR/badexif.jpg" >"$LOGDIR/test.jpg"'
3+
COMMAND='$PROGRAM -l "1 2" -R "$LOGDIR/test.jpg" > "$OUTFILE" 2>&1'
4+
RESULTCODE=2

tests/data/test199.result

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Legend: . = Ok, / = Interpolated, < = Rounded, - = No match, ^ = Too far
2+
w = Write Fail, ? = No EXIF date, ! = GPS already present
3+
4+
Correlate: ?
5+
6+
Completed correlation process.
7+
Matched: 0 (0 Exact, 0 Interpolated, 0 Rounded).
8+
Failed: 1 (0 Not matched, 0 Write failure, 0 Too Far,
9+
1 No Date, 0 GPS Already Present.)

tests/staging/badexif.jpg

1.04 KB
Loading

0 commit comments

Comments
 (0)