Bug 159522 - gwenview craches on images with incorrect exif info
Summary: gwenview craches on images with incorrect exif info
Status: RESOLVED FIXED
Alias: None
Product: gwenview
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Debian testing Linux
: NOR normal
Target Milestone: ---
Assignee: Gwenview Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-03-18 15:01 UTC by paul s. romanchenko
Modified: 2012-10-19 13:26 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
patch to avoid crashing on not well formed information (623 bytes, patch)
2008-03-19 15:11 UTC, Angelo Naselli
Details
a better patch to avoid crashing on not well formed information (771 bytes, patch)
2008-03-19 17:15 UTC, Angelo Naselli
Details

Note You need to log in before you can comment on or make changes to this bug.
Description paul s. romanchenko 2008-03-18 15:01:30 UTC
Version:            (using KDE 3.5.9)
Installed from:    Debian testing/unstable Packages
OS:                Linux

$ exif IMGP9854-01.jpeg
EXIF tags in 'IMGP9854-01.jpeg' ('Intel' byte order):
--------------------+----------------------------------------------------------
Tag                 |Value
--------------------+----------------------------------------------------------
Manufacturer        |PENTAX Corporation
Model               |PENTAX *ist DS
x-Resolution        |300/0
y-Resolution        |300/0
Corrupt data (ExifEntry):
The tag 'ResolutionUnit' contains data of an invalid format ('Long', expected 'Short').
Resolution Unit     |%                                                           
$ gwenview IMGP9854-01.jpeg
...crashed

#5  0x00002b6b19bdc1ab in Exiv2::ValueType<std::pair<unsigned int, unsigned int> >::toLong () from /usr/lib/libexiv2.so.2
#6  0x00002b6b14afc338 in ImageUtils::JPEGContent::dotsPerMeter ()
   from /usr/lib/libgwenviewcore.so.1
#7  0x00002b6b14afc61b in ImageUtils::JPEGContent::dotsPerMeterX ()
   from /usr/lib/libgwenviewcore.so.1
#8  0x00002b6b14ae0a9b in Gwenview::ImageLoader::changed ()
   from /usr/lib/libgwenviewcore.so.1
#9  0x00002b6b14a9f65a in Gwenview::JPEGFormat::decode ()
   from /usr/lib/libgwenviewcore.so.1
#10 0x00002b6b14ae2fae in Gwenview::ImageLoader::decodeChunk ()
   from /usr/lib/libgwenviewcore.so.1
#11 0x00002b6b14ae3349 in Gwenview::ImageLoader::qt_invoke ()
   from /usr/lib/libgwenviewcore.so.1

Image: http://xtalk.msk.su/photo/Valday07/IMGP9854-01.jpeg
Comment 1 Angelo Naselli 2008-03-18 15:29:37 UTC
> Image: http://xtalk.msk.su/photo/Valday07/IMGP9854-01.jpeg

confirm it crashes, i will take a look at it thanks.

Angelo
Comment 2 caulier.gilles 2008-03-19 10:33:19 UTC
Andreas,

This is relevant on Exiv2 library used by Gwenview. I CC you in this file to have your viewpoint. Thanks in advance...

Gilles Caulier
Comment 3 Angelo Naselli 2008-03-19 11:52:26 UTC
mercoledì 19 marzo 2008 alle 10:33, Gilles Caulier ha scritto:
[bugs.kde.org quoted mail]
The failure is for:
Program received signal SIGFPE, Arithmetic exception.
Andreas, do you rise such an exception? if, the failing code is :

int JPEGContent::dotsPerMeterX() const {
        return dotsPerMeter("XResolution");
}
    
    
int JPEGContent::dotsPerMeterY() const {
        return dotsPerMeter("YResolution");
}
    
    
int JPEGContent::dotsPerMeter(const QString& keyName) const {
        Exiv2::ExifKey keyResUnit("Exif.Image.ResolutionUnit");
        Exiv2::ExifData::iterator it = d->mExifData.findKey(keyResUnit);
        if (it == d->mExifData.end()) {
                return 0;
        }
        int res = it->toLong();
        QString keyVal = "Exif.Image." + keyName;
        Exiv2::ExifKey keyResolution(keyVal.ascii());
        it = d->mExifData.findKey(keyResolution);
        if (it == d->mExifData.end()) {
                return 0;
        }
        // The unit for measuring XResolution and YResolution. The same unit is used for both XResolution and YResolution.
        //     If the image resolution in unknown, 2 (inches) is designated.
        //         Default = 2
        //         2 = inches
        //         3 = centimeters
        //         Other = reserved
        const float INCHESPERMETER = (100. / 2.54); 
        switch (res) {
        case 3:  // dots per cm 
                return (it->toLong() * 100); 
        default:  // dots per inch 
                return (it->toLong() * INCHESPERMETER); 
        }
    
        return 0;
}

Maybe i forgot to catch exceptions..., the failing line is  return (it->toLong() * INCHESPERMETER); 

Angelo
Comment 4 Angelo Naselli 2008-03-19 12:23:40 UTC
martedì 18 marzo 2008 alle 15:01, paul s.romanchenko ha scritto:
> x-Resolution        |300/0
> y-Resolution        |300/0



exiv2 -Ptn /home/anaselli/tmp/gv_crash/IMGP9854-01.jpeg
Make                         PENTAX Corporation
Model                        PENTAX *ist DS
XResolution                  (300/0)
YResolution                  (300/0)
ResolutionUnit               inch
ExifTag                      90
ExposureTime                 1/750 s
FNumber                      F9.5
ExposureProgram              Auto
ISOSpeedRatings              400
DateTimeOriginal             2007:04:15 16:14:25
DateTimeDigitized            2007:04:15 16:14:25
ExposureBiasValue            0
MeteringMode                 Multi-segment
Flash                        No, compulsory
FocalLength                  150.0 mm
SensingMethod                One-chip color area
CustomRendered               Normal process
ExposureMode                 Auto
WhiteBalance                 Auto
FocalLengthIn35mmFilm        225.0 mm
SceneCaptureType             Standard
Contrast                     Normal
Saturation                   Normal
Sharpness                    Normal
SubjectDistanceRange         Distant view


hmmmm: 
XResolution                  (300/0)
YResolution                  (300/0)
300/0  is a nan....
From a pictures of mine:
XResolution                  180
YResolution                  180

It should be an exiv2 upstream bug i believe.

Angelo
Comment 5 Andreas Huggel 2008-03-19 13:31:23 UTC
Well, if I understand this correctly, the program calls toLong() on a Rational with denominator 0. The conversion of a Rational to a long is a simple division (and truncation). If the denominator is 0, the result of the division is an arithmetic exception, this is the usual behaviour in such a situation. Do you see a better way for Exiv2 to handle this?
I think this needs to be fixed in the application, but rather than catching the exception, I would check the value before attempting a conversion.

-ahu.
Comment 6 Angelo Naselli 2008-03-19 14:47:44 UTC
> Well, if I understand this correctly, the program calls toLong() on a Rational with denominator 0. 
> The conversion of a Rational to a long is a simple division (and truncation). If the denominator is 0,
> the result of the division is an arithmetic exception, this is the usual behaviour in such a situation. 
> Do you see a better way for Exiv2 to handle this?   

Well no. But my mail was written before understanding what the problem was ;)
> I think this needs to be fixed in the application, but rather than catching the exception, I would check the value before attempting a conversion.

I'm not sure of that, how can i know if that is a string that cannot be converted
before doing that? I mean i would like to trust toLong method instead...
something like QString::toLong does (or say to :) ) for instance.
Comment 7 Angelo Naselli 2008-03-19 15:11:48 UTC
Created attachment 23966 [details]
patch to avoid crashing on not well formed information

Aurelien, i made this patch to fix the problem since we cannot trust to toLong
call. A better way could be to interpret the string and get the number instead
of using QString::toLong that should return 0. Please tell me if you have a
better idea or i can commit it, thanks.
Angelo
Comment 8 Andreas Huggel 2008-03-19 15:47:03 UTC
> QString::toLong that should return 0

Are you saying QString::toLong for "300/0" returns 0? But that's mathematically not correct! And it would make the application believe everything is fine when it isn't. Does it return the correct value for "300/2" then?

Anyway, the tags that you're dealing with here are X/YResolution and should be Rational values, you could try something like this (Value::toRational() doesn't throw for any type of Value):

    Exiv2::Rational r = it->toRational();
    if (r.second == 0) {
        // do whatever is appropriate: signal an error to the caller,
        // silently ignore the problem, or even set r.second = 1
        // (which would probably fix the invalid example at hand...)
    }
    return (it->toLong() * INCHESPERMETER);

-ahu.
Comment 9 Angelo Naselli 2008-03-19 16:34:39 UTC
mercoledì 19 marzo 2008 alle 15:47, Andreas Huggel ha scritto:
[bugs.kde.org quoted mail]
Well as you said after it could return the right value or -1 a not valid one for instance.
A good test is better than a crash (i've tried to catch the exception but it seemed i couldn't :( )
 
> Are you saying QString::toLong for "300/0" returns 0? 
> But that's mathematically not correct! 

Well neither is 300/0 :p

> Anyway, the tags that you're dealing with here are X/YResolution and 
> should be Rational values,

hmm good to know it, i've never thought about that, i've always thought it was an int :( 
so do you mean it is something like float? I don't understand that though x/y resolution
what is the difference between 300/0 and 300/1 then? and shouldn't 300/2 written as 150?
> you could try something like this (Value::toRational() doesn't throw for any type of Value):  
> 
>     Exiv2::Rational r = it->toRational();
>     if (r.second == 0) {
>         // do whatever is appropriate: signal an error to the caller,
>         // silently ignore the problem, or even set r.second = 1
>         // (which would probably fix the invalid example at hand...)
>     }
>     return (it->toLong() * INCHESPERMETER);

Thanks for the hint i can make a better patch now.

Angelo
Comment 10 Angelo Naselli 2008-03-19 17:15:33 UTC
Created attachment 23968 [details]
a better patch to avoid crashing on not well formed information

used a rational value instead.
Comment 11 Aurelien Gateau 2008-03-29 01:33:45 UTC
Patch looks good (except I prefer to use 'double' instead of 'float'). Please commit.
Comment 12 Angelo Naselli 2008-03-29 23:21:11 UTC
SVN commit 791583 by anaselli:

Fixed wrong exiv2 interface usage
BUG: 159522

 M  +8 -3      jpegcontent.cpp  


WebSVN link: http://websvn.kde.org/?view=rev&revision=791583