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 (profile)
Status: Closed Package: GD related
PHP Version: 5.5.36 OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Tue Dec 03 17:01:29 2024 UTC