php / php-src

The PHP Interpreter
https://www.php.net
Other
37.67k stars 7.71k forks source link

Closing a userspace stream inside a userspace handler causes heap corruption #14506

Open nielsdos opened 1 month ago

nielsdos commented 1 month ago

Description

The following code:

<?php

class Bomb {

    public $context;

    function stream_open($path, $mode, $options, &$opened_path): bool
    {
        return true;
    }

    function stream_read(int $count): false|string|null
    {
        global $readStream;
        fclose($readStream);
        return "";
    }
}

stream_register_wrapper('bomb', Bomb::class);
$readStream = fopen('bomb://1', 'r');
fread($readStream, 1);

Resulted in this output:

==21643==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x7fda60e161dd bp 0x7ffda947edf0 sp 0x7ffda947e578 T0)
==21643==The signal is caused by a READ memory access.
==21643==Hint: this fault was caused by a dereference of a high value address (see register values below).  Disassemble the provided pc to learn which register was used.
    #0 0x7fda60e161dd  (/usr/lib/libc.so.6+0x16a1dd) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #1 0x7fda618766bc in strlen /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:389
    #2 0x5d49d745d0f0 in xbuf_format_converter /run/media/niels/MoreData/php-src/main/spprintf.c:555
    #3 0x5d49d745edd9 in php_printf_to_smart_str /run/media/niels/MoreData/php-src/main/spprintf.c:784
    #4 0x5d49d75cd6ab in zend_vstrpprintf /run/media/niels/MoreData/php-src/Zend/zend.c:330
    #5 0x5d49d7449f5c in php_verror /run/media/niels/MoreData/php-src/main/main.c:965
    #6 0x5d49d744ae7e in php_error_docref /run/media/niels/MoreData/php-src/main/main.c:1133
    #7 0x5d49d74b6c10 in php_userstreamop_read /run/media/niels/MoreData/php-src/main/streams/userspace.c:678
    #8 0x5d49d7497985 in _php_stream_fill_read_buffer /run/media/niels/MoreData/php-src/main/streams/streams.c:684
    #9 0x5d49d74980ff in _php_stream_read /run/media/niels/MoreData/php-src/main/streams/streams.c:747
    #10 0x5d49d7498411 in php_stream_read_to_str /run/media/niels/MoreData/php-src/main/streams/streams.c:795
    #11 0x5d49d7282eeb in zif_fread /run/media/niels/MoreData/php-src/ext/standard/file.c:1636
    #12 0x5d49d767e8ae in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER /run/media/niels/MoreData/php-src/Zend/zend_vm_execute.h:1287
    #13 0x5d49d77d9a6d in execute_ex /run/media/niels/MoreData/php-src/Zend/zend_vm_execute.h:57364
    #14 0x5d49d77ed958 in zend_execute /run/media/niels/MoreData/php-src/Zend/zend_vm_execute.h:62776
    #15 0x5d49d75d6252 in zend_execute_script /run/media/niels/MoreData/php-src/Zend/zend.c:1899
    #16 0x5d49d7450e8e in php_execute_script_ex /run/media/niels/MoreData/php-src/main/main.c:2512
    #17 0x5d49d7451296 in php_execute_script /run/media/niels/MoreData/php-src/main/main.c:2552
    #18 0x5d49d79d2f9d in do_cli /run/media/niels/MoreData/php-src/sapi/cli/php_cli.c:966
    #19 0x5d49d79d4d6a in main /run/media/niels/MoreData/php-src/sapi/cli/php_cli.c:1340
    #20 0x7fda60cd1c87  (/usr/lib/libc.so.6+0x25c87) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #21 0x7fda60cd1d4b in __libc_start_main (/usr/lib/libc.so.6+0x25d4b) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #22 0x5d49d6a058c4 in _start (/run/media/niels/MoreData/php-src/sapi/cli/php+0x6058c4) (BuildId: 6fe72432c731063b9117e84b7b9c658178936dc0)

But I expected this output instead:

No crash

PHP Version

8.2+

Operating System

Linux

lucasnetau commented 1 month ago

To add to the reproducer, this only occurs if stream_eof() function is not defined in the stream wrapper class.