php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #72407 NULL Pointer Dereference at _gdScaleVert
Submitted: 2016-06-15 00:41 UTC Modified: 2016-06-21 06:47 UTC
From: marceloje at gmail dot com Assigned: stas
Status: Closed Package: GD related
PHP Version: 5.5.36 OS: *
Private report: No CVE-ID:
Password:
Status:
Package:
Bug Type:
Summary:
From: marceloje at gmail dot com
New email:
PHP Version: OS:

 

 [2016-06-15 00:41 UTC] marceloje at gmail dot com
Description:
------------
_gdScaleVert not check _gdContributionsCalc return, this could cause NULL Pointer Dereference at _gdScaleCol.

Source code (https://github.com/php/php-src/blame/master/ext/gd/libgd/gd_interpolation.c#L1049):

static inline void _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_width, const unsigned int src_height, const gdImagePtr pDst, const unsigned int dst_width, const unsigned int dst_height)
{
    unsigned int u;
    LineContribType * contrib;
......
    contrib = _gdContributionsCalc(dst_height, src_height, (double)(dst_height) / (double)(src_height), pSrc->interpolation);
    /* scale each column */
    for (u = 0; u < dst_width - 1; u++) {
        _gdScaleCol(pSrc, src_width, pDst, dst_width, dst_height, u, contrib);
    }
    _gdContributionsFree(contrib);
}

_gdScaleHoriz checks the return value of _gdContributionsCalc:

static inline void _gdScaleHoriz(gdImagePtr pSrc, unsigned int src_width, unsigned int src_height, gdImagePtr pDst,  unsigned int dst_width, unsigned int dst_height)
{
    unsigned int u;
    LineContribType * contrib;
...
    contrib = _gdContributionsCalc(dst_width, src_width, (double)dst_width / (double)src_width, pSrc->interpolation);
    if (contrib == NULL) {    // Check return
        return;
    }
    /* Scale each row */
    for (u = 0; u < dst_height - 1; u++) {
        _gdScaleRow(pSrc, src_width, pDst, dst_width, u, contrib);
    }
    _gdContributionsFree (contrib);
}


Test script:
---------------
<?php
ini_set('memory_limit', -1);

$img = imagecreatetruecolor(100, 100);
imagescale($img, 100, 1000000, 6);
?>


Expected result:
----------------
No crash

Actual result:
--------------
ASAN output:

USE_ZEND_ALLOC=0 /ram/php-70/sapi/cli/php -n poc.php

ASAN:SIGSEGV
=================================================================
==31979==ERROR: AddressSanitizer: SEGV on unknown address 0x00000000 (pc 0x086914d8 bp 0x0a5b6000 sp 0xff9d8f00 T0)
    #0 0x86914d7 in _gdContributionsFree /home/user/php/php-70-asan/ext/gd/libgd/gd_interpolation.c:905
    #1 0x86914d7 in _gdContributionsCalc /home/user/php/php-70-asan/ext/gd/libgd/gd_interpolation.c:952
    #2 0x86914d7 in _gdScaleVert /home/user/php/php-70-asan/ext/gd/libgd/gd_interpolation.c:1049
    #3 0x86914d7 in gdImageScaleTwoPass /home/user/php/php-70-asan/ext/gd/libgd/gd_interpolation.c:1080
    #4 0x86a1505 in gdImageScale /home/user/php/php-70-asan/ext/gd/libgd/gd_interpolation.c:1659
    #5 0x85ba190 in zif_imagescale /home/user/php/php-70-asan/ext/gd/gd.c:4674
    #6 0x9a388ac in ZEND_DO_ICALL_SPEC_HANDLER /home/user/php/php-70-asan/Zend/zend_vm_execute.h:586
    #7 0x980d06f in execute_ex /home/user/php/php-70-asan/Zend/zend_vm_execute.h:414
    #8 0x9b287c5 in zend_execute /home/user/php/php-70-asan/Zend/zend_vm_execute.h:458
    #9 0x95e4c3c in zend_execute_scripts /home/user/php/php-70-asan/Zend/zend.c:1427
    #10 0x932d58b in php_execute_script /home/user/php/php-70-asan/main/main.c:2494
    #11 0x9b31004 in do_cli /home/user/php/php-70-asan/sapi/cli/php_cli.c:974
    #12 0x80a6e78 in main /home/user/php/php-70-asan/sapi/cli/php_cli.c:1344
    #13 0xf6c34636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
    #14 0x80a755a  (/ram/php-fuzz/phuzzer/php-70-asan/sapi/cli/php+0x80a755a)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/user/php/php-70-asan/ext/gd/libgd/gd_interpolation.c:905 _gdContributionsFree
==31979==ABORTING

-----------------------------------------------------------------
GDB output:

USE_ZEND_ALLOC=0 gdb -q --args /home/user/php/php-70/sapi/cli/php -n poc.php
No symbol table is loaded.  Use the "file" command.
Breakpoint 1 (__asan_report_error) pending.
Reading symbols from /home/user/php/php-70/sapi/cli/php...done.
gdb-peda$ b _gdScaleCol
Breakpoint 2 at 0x8192d0f: file /home/user/php/php-70/ext/gd/libgd/gd_interpolation.c, line 1016.
gdb-peda$ r
Starting program: /home/user/php/php-70/sapi/cli/php -n poc.php

[----------------------------------registers-----------------------------------]
EAX: 0x8b47000 --> 0x8b46db8 --> 0x1
EBX: 0x0
ECX: 0xf7bfa000 --> 0x1b1db0
EDX: 0x0
ESI: 0xf5c08028 --> 0x8c7a1b4 --> 0x84b92de (<ZEND_DO_ICALL_SPEC_HANDLER>:    push   ebp)
EDI: 0x8c7a1b4 --> 0x84b92de (<ZEND_DO_ICALL_SPEC_HANDLER>: push   ebp)
EBP: 0xffff9e88 --> 0xffff9ed8 --> 0xffff9f18 --> 0xffff9f58 --> 0xffff9fc8 --> 0xffff9ff8 (--> ...)
ESP: 0xffff9e50 --> 0x0
EIP: 0x8192d0f (<_gdScaleCol+17>:   mov    DWORD PTR [ebp-0x24],0x0)
EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8192d02 <_gdScaleCol+4>: sub    esp,0x34
   0x8192d05 <_gdScaleCol+7>: call   0x8076e59 <__x86.get_pc_thunk.ax>
   0x8192d0a <_gdScaleCol+12>: add    eax,0x9b42f6
=> 0x8192d0f <_gdScaleCol+17>: mov    DWORD PTR [ebp-0x24],0x0
   0x8192d16 <_gdScaleCol+24>: jmp    0x8192f08 <_gdScaleCol+522>
   0x8192d1b <_gdScaleCol+29>: mov    BYTE PTR [ebp-0x2f],0x0
   0x8192d1f <_gdScaleCol+33>: mov    BYTE PTR [ebp-0x30],0x0
   0x8192d23 <_gdScaleCol+37>: mov    ebx,0x0
[------------------------------------stack-------------------------------------]
0000| 0xffff9e50 --> 0x0
0004| 0xffff9e54 --> 0x3ff00000
0008| 0xffff9e58 --> 0xd1000000
0012| 0xffff9e5c --> 0xbe39d96d
0016| 0xffff9e60 --> 0x0
0020| 0xffff9e64 --> 0x3fe00000
0024| 0xffff9e68 --> 0x5c91d14e
0028| 0xffff9e6c --> 0x4058fffe
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, _gdScaleCol (pSrc=0x8c7fad0, src_width=0x64, pRes=0x8c8e2a0, dst_width=0x64, dst_height=0xf4240, uCol=0x0, contrib=0x0) at /home/user/php/php-70/ext/gd/libgd/gd_interpolation.c:1016         // _gdScaleCol receive NULL contrib pointer
1016  for (y = 0; y < dst_height - 1; y++) {
gdb-peda$ c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x0
ECX: 0xf7bfa000 --> 0x1b1db0
EDX: 0x0
ESI: 0xf5c08028 --> 0x8c7a1b4 --> 0x84b92de (<ZEND_DO_ICALL_SPEC_HANDLER>:    push   ebp)
EDI: 0x8c7a1b4 --> 0x84b92de (<ZEND_DO_ICALL_SPEC_HANDLER>: push   ebp)
EBP: 0xffff9e88 --> 0xffff9ed8 --> 0xffff9f18 --> 0xffff9f58 --> 0xffff9fc8 --> 0xffff9ff8 (--> ...)
ESP: 0xffff9e50 --> 0x0
EIP: 0x8192d2f (<_gdScaleCol+49>:   mov    ecx,DWORD PTR [eax])
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8192d23 <_gdScaleCol+37>: mov    ebx,0x0
   0x8192d28 <_gdScaleCol+42>: mov    BYTE PTR [ebp-0x31],0x0
   0x8192d2c <_gdScaleCol+46>: mov    eax,DWORD PTR [ebp+0x20]
=> 0x8192d2f <_gdScaleCol+49>: mov    ecx,DWORD PTR [eax]
   0x8192d31 <_gdScaleCol+51>: mov    edx,DWORD PTR [ebp-0x24]
   0x8192d34 <_gdScaleCol+54>: mov    eax,edx
   0x8192d36 <_gdScaleCol+56>: add    eax,eax
   0x8192d38 <_gdScaleCol+58>: add    eax,edx
[------------------------------------stack-------------------------------------]
0000| 0xffff9e50 --> 0x0
0004| 0xffff9e54 --> 0xf00000
0008| 0xffff9e58 --> 0xd1000000
0012| 0xffff9e5c --> 0xbe39d96d
0016| 0xffff9e60 --> 0x0
0020| 0xffff9e64 --> 0x0
0024| 0xffff9e68 --> 0x5c91d14e
0028| 0xffff9e6c --> 0x4058fffe
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x08192d2f in _gdScaleCol (pSrc=0x8c7fad0, src_width=0x64, pRes=0x8c8e2a0, dst_width=0x64, dst_height=0xf4240, uCol=0x0, contrib=0x0) at /home/user/php/php-70/ext/gd/libgd/gd_interpolation.c:1018
1018   const int iLeft = contrib->ContribRow[y].Left;    // _gdScaleCol try access to NULL contrib pointer

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-16 00:03 UTC] stas@php.net
-Status: Open +Status: Feedback
 [2016-06-16 00:03 UTC] stas@php.net
This looks like an issue in libgd. Please report to libgd maintainers.
 [2016-06-16 00:40 UTC] marceloje at gmail dot com
-Status: Feedback +Status: Open
 [2016-06-16 00:40 UTC] marceloje at gmail dot com
Currently, GD have a generic function for axis scale: _gdScalePass (https://github.com/libgd/libgd/blob/master/src/gd_interpolation.c#L957). This function checks correctly the return of call to _gdContributionsCalc.


PHP have individuals functions for axis scale: _gdScaleVert and _gdScaleHoriz. _gdScaleHoriz checks correctly the return of call to _gdContributionsCalc, but _gdScaleVert not. This seems an oversight of PHP developers.
 [2016-06-19 04:58 UTC] stas@php.net
-PHP Version: 7.0.7 +PHP Version: 5.5.36 -Assigned To: +Assigned To: stas
 [2016-06-19 04:58 UTC] stas@php.net
Fixed in b9ec171e7d25879d97473ca50197c4207420c276 in security repo and in https://gist.github.com/9d931510dad3f5678a964d84d7d085a3
please verify
 [2016-06-19 07:37 UTC] pajoye@php.net
Fix is correct.

It should be part of 5.5+.

Thanks!
 [2016-06-19 13:28 UTC] marceloje at gmail dot com
Yes. The fix works correctly with the PHP test script.

Thanks
 [2016-06-21 06:48 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b9ec171e7d25879d97473ca50197c4207420c276
Log: Fix bug #72407: NULL Pointer Dereference at _gdScaleVert
 [2016-06-21 06:48 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-06-21 07:03 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b9ec171e7d25879d97473ca50197c4207420c276
Log: Fix bug #72407: NULL Pointer Dereference at _gdScaleVert
 [2016-06-21 07:26 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b9ec171e7d25879d97473ca50197c4207420c276
Log: Fix bug #72407: NULL Pointer Dereference at _gdScaleVert
 [2016-06-21 07:27 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b9ec171e7d25879d97473ca50197c4207420c276
Log: Fix bug #72407: NULL Pointer Dereference at _gdScaleVert
 [2016-06-22 05:58 UTC] krakjoe@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b9ec171e7d25879d97473ca50197c4207420c276
Log: Fix bug #72407: NULL Pointer Dereference at _gdScaleVert
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC