Bug #1345

Assertion Failure (SIGABRT) in Exiv2:RafImage::readMetadata() in Libexiv2

Added by Sanjay Rawat 4 months ago. Updated 4 months ago.

Status:AssignedStart date:21 Apr 2018
Priority:NormalDue date:
Assignee:Robin Mills% Done:

50%

Category:image formatEstimated time:2.00 hours
Target version:0.27

Description

Hi,
I found a failure assertion event in libevix2(0.26 001a00, 64 bit). To reproduce,
$ exiv2 input_file

The input that triggered the failure is attached.
GDB output: ====
@(gdb) r
Starting program: /usr/local/bin/exiv2 outd/crashInputs/exiv2-2018-04-14T11-14-49.310776.exi
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc

Program received signal SIGABRT, Aborted.
0x00007ffff6e29c37 in _GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff6e29c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007ffff6e2d028 in __GI_abort () at abort.c:89
#2 0x00007ffff7432535 in __gnu_cxx::
_verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff74306d6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffff7430703 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff7430922 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007ffff7430e0d in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007ffff7430ea9 in operator new[](unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x00007ffff782a4fc in Exiv2::RafImage::readMetadata() () from /usr/local/lib/libexiv2.so.26
#9 0x000000000041bdfd in Action::Print::printSummary() ()
#10 0x000000000041e1a8 in Action::Print::run(std::string const&) ()
#11 0x0000000000406bba in main ()
@
I am not sure if this is a new issue as I have seen several issues involving readMetadata(), but none of them were for RafImage::readMetadata(). So i thought of reporting.

Thanks
-sanjay

exiv2-2018-04-14T11-14-49.310776.exi (8.14 KB) Sanjay Rawat, 21 Apr 2018 09:28

History

#1 Updated by Robin Mills 4 months ago

  • Category set to image format
  • Status changed from New to Assigned
  • Assignee set to Robin Mills
  • Target version set to 0.27
  • % Done changed from 0 to 10
  • Estimated time set to 4.00

Thanks for reporting this. I've reproduced this and will investigate.

#2 Updated by Robin Mills 4 months ago

  • % Done changed from 10 to 50
  • Estimated time changed from 4.00 to 2.00

Thanks for reporting this. The fix is in src/rafimage.cpp. Exiv2 supports about 20 different file formats (TIFF, JPEG, PNG, RAF etc) and every format has a metadata parser derived from Image::readMetadata(). Your fuzzed file has broken the raf parser, so I've added additional range checks:

537 rmills@rmillsmbp:~/gnu/github/exiv2/exiv2 $ git diff src/rafimage.cpp
diff --git a/src/rafimage.cpp b/src/rafimage.cpp
index f709d544..8315a824 100644
--- a/src/rafimage.cpp
+++ b/src/rafimage.cpp
@@ -290,6 +290,11 @@ namespace Exiv2 {

         clearMetadata();

+        // Ensure there is enough data to read the header
+        long size = io_->size();
+        if ( size <= (84+8) ) {
+            throw Error(Exiv2::kerCorruptedMetadata);
+        }
         io_->seek(84,BasicIo::beg);
         byte jpg_img_offset [4];
         io_->read(jpg_img_offset, 4);
@@ -298,6 +303,13 @@ namespace Exiv2 {
         long jpg_img_off = Exiv2::getULong((const byte *) jpg_img_offset, bigEndian);
         long jpg_img_len = Exiv2::getULong((const byte *) jpg_img_length, bigEndian);

+        // Ensure jpg lies within the file
+        if( (jpg_img_off <  0 &&  jpg_img_off >= size)
+        ||  (jpg_img_len < 12 && (jpg_img_off + jpg_img_len) >= size )
+        ){
+            throw Error(Exiv2::kerCorruptedMetadata);
+        }
+
         DataBuf buf(jpg_img_len - 12);
         io_->seek(jpg_img_off + 12,BasicIo::beg);
         io_->read(buf.pData_, buf.size_ - 12);
538 rmills@rmillsmbp:~/gnu/github/exiv2/exiv2 $ 
I will raise an issue on GitHub about this and it will be fixed and tracked there. I'll close this issue when the GitHub version is resolved.

Also available in: Atom PDF

Redmine Appliance - Powered by TurnKey Linux