oozcitak / exiflibrary

A .Net Standard library for editing Exif metadata
MIT License
131 stars 48 forks source link

Field offset validation #105

Open andyjohnson0 opened 2 years ago

andyjohnson0 commented 2 years ago

I have an original image that throws an exception in ImageFile.FromFileAsync() due to a number of invalid field offsets.

The image has GPS and Interop IFD tags in the EXIF IFD. The offsets for these tags are superficially valid in that they point within the header, but they actually point to a region that is uniformly initialised with 255. Consequently when JPEGFile.ReadExifAPP1() reads the IFD from this region it retrieves a field count of 65536 and after 100 or so iterations around the field read loop (reading invalid 255 tag values) it generates a field offset that exceeds the size of the header byte array and Array.Copy() throws an ArgumentException.

The image comes from a Panasonic DMC TZ-60 and was taken in 2018. I'm happy to share it. I don't know what caused the corruption but it is present in my original, unmodified master copy, so I'm pretty sure that that's how the camera encoded it.

I've tested a small change to JPEGFile.ReadExifAPP1() that validates the calculated field offset and, if it is out of range, generates a warning and abandons further reading off the current IFD. Alternatively, it could just continue to the next tag but this generates hundreds of subsequent identical warnings for the image in question.

If this is useful then I'm happy to share the code here or send it as a pull request - whichever is appropriate. I'm unsure what the norm is for this project/repo.

andyjohnson0 commented 2 years ago

As I'm not sure how actively this library is being maintained at present, I'll just drop the fix here as a comment.

In JPEGFile.ReadExifAPP1(), after the line:

int fieldoffset = ifdoffset + 2 + 12 * i;

add the following:

if (fieldoffset < 0 || fieldoffset >= header.Length - 12)
{
    Errors.Add(new ImageError(Severity.Warning,
                              $"Invalid field offset: {currentifd} IFD field {i} of {fieldcount} has invalid offset {fieldoffset} for header of length {header.Length}."));
    break;
}