Bug #65873 [Opn->Csd]: Integer overflow in exif_read_data()

From: Date: Mon, 16 Dec 2013 19:45:33 +0000
Subject: Bug #65873 [Opn->Csd]: Integer overflow in exif_read_data()
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-183363@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=65873&edit=1

 ID:                 65873
 Updated by:         stas@php.net
 Reported by:        tstarling@php.net
 Summary:            Integer overflow in exif_read_data()
-Status:             Open
+Status:             Closed
 Type:               Bug
 Package:            EXIF related
 Operating System:   Linux
 PHP Version:        5.5Git-2013-10-10 (Git)
-Assigned To:        
+Assigned To:        stas
 Block user comment: N
 Private report:     N

 New Comment:

The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.




Previous Comments:
------------------------------------------------------------------------
[2013-10-10 22:49:16] tstarling@php.net

Note that this bug originates from the same line of code as bug #60150. The fix for bug #60150 fixed
that particular test case, but didn't implement the required logic correctly.

------------------------------------------------------------------------
[2013-10-10 06:39:13] tstarling@php.net

Description:
------------
exif_read_data() can crash or read data from arbitrary memory locations when presented with a large
file with a tag value located before the relevant IFD. 

Throughout exif.c, the pointer offset_base is deliberately assigned a value before the start of its
associated buffer. It is a kind of virtual start-of-file pointer -- when you add a file offset to
offset_base, you get a pointer to the memory that holds the file data at that offset.

The bug occurs when the IFD offset is larger than the heap address for the file buffer. This only
happens when both the heap address is small (e.g. if it is allocated from brk()) and the IFD offset
is large. In this case, offset_base wraps around past the start of the address space and becomes a
large positive pointer. This is mostly harmless, except for when a tag value is so far before the
start of the IFD that its virtual pointer also wraps around to a large positive value. Then in
exif_process_IFD_TAG():

if (byte_count > IFDlength || offset_val > IFDlength-byte_count || value_ptr < dir_entry) {

The "value_ptr < dir_entry" condition should be true, because the value is before the
IFD in the file, but because value_ptr has wrapped around and dir_entry hasn't, it is false. So
this code incorrectly assumes that value_ptr is inside the already-loaded buffer.

Our test file is here: https://noc.wikimedia.org/~reedy/segfault.tar.gz
. It was generated innocently, it is not "crafted". 

This bug was originally reported here: https://bugzilla.wikimedia.org/show_bug.cgi?id=55541

Test script:
---------------
exif_read_data("/path/to/test.tiff");

The use of brk() for allocation instead of mmap() is required for reproduction, and is more reliable
across various systems and builds if the environment variable ZEND_MM_SEG_SIZE=65536 is specified:

ZEND_MM_SEG_SIZE=65536 php -r 'exif_read_data("/path/to/test.tiff");'




------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=65873&edit=1


Thread (3 messages)

« previous php.bugs (#183363) next »