php / php-src

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

Segmentation fault on unknown address 0x600000000018 in ext/opcache/jit/zend_jit.c #14082

Open YuanchengJiang opened 3 months ago

YuanchengJiang commented 3 months ago

Description

The following code:

test.php:

<?php
Foo::test();
?>

preload.inc:

<?php
class Foo {
    public static function test() {
        static $i = 0;
        var_dump(++$i);
    }
}

Foo::test();
eval("class Bar extends Foo {}"); // Avoid early binding.
Foo::test();
Bar::test();

Resulted in this output:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==1568876==ERROR: AddressSanitizer: SEGV on unknown address 0x600000000018 (pc 0x7fd3be7a109d bp 0x7ffd1346c4d0 sp 0x7ffd1346c360 T0)
==1568876==The signal is caused by a READ memory access.
    #0 0x7fd3be7a109d in zend_jit_cleanup_func_info /php-src/ext/opcache/jit/zend_jit.c:2751:8
    #1 0x7fd3be7a0f34 in zend_jit_cleanup_func_info /php-src/ext/opcache/jit/zend_jit.c:2746:5
    #2 0x7fd3be70c744 in zend_real_jit_func /php-src/ext/opcache/jit/zend_jit.c:2799:2
    #3 0x7fd3be70d273 in zend_jit_hot_func /php-src/ext/opcache/jit/zend_jit.c:2908:4
    #4 0x7fd3bebe725f in zend_jit_func_counter_helper /php-src/ext/opcache/jit/zend_jit_vm_helpers.c:256:3
    #5 0x5607f3146b87 in execute_ex /php-src/Zend/zend_vm_execute.h:57144:7
    #6 0x5607f3147f52 in zend_execute /php-src/Zend/zend_vm_execute.h:62776:2
    #7 0x5607f2f93bc8 in zend_execute_script /php-src/Zend/zend.c:1899:3
    #8 0x5607f2afcf86 in php_execute_script_ex /php-src/main/main.c:2507:13
    #9 0x5607f2afd828 in php_execute_script /php-src/main/main.c:2547:9
    #10 0x5607f3ec66c3 in do_cli /php-src/sapi/cli/php_cli.c:966:5
    #11 0x5607f3ec2c52 in main /php-src/sapi/cli/php_cli.c:1340:18
    #12 0x7fd3c478bd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #13 0x7fd3c478be3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #14 0x5607f0e031f4 in _start (/php-src/sapi/cli/php+0x1c031f4) (BuildId: efef4313e9b3f9c29ffacbb2357a940caebf48b7)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /php-src/ext/opcache/jit/zend_jit.c:2751:8 in zend_jit_cleanup_func_info
==1568876==ABORTING

To reproduce:

/php-src/sapi/cli/php  -n -c '/php-src/tmp-php.ini'   -d "opcache.cache_id=worker19" -d "output_handler=" -d "open_basedir=" -d "disable_functions=" -d "output_buffering=Off" -d "error_reporting=32767" -d "display_errors=1" -d "display_startup_errors=1" -d "log_errors=0" -d "html_errors=0" -d "track_errors=0" -d "report_memleaks=1" -d "report_zend_debug=0" -d "docref_root=" -d "docref_ext=.html" -d "error_prepend_string=" -d "error_append_string=" -d "auto_prepend_file=" -d "auto_append_file=" -d "ignore_repeated_errors=0" -d "precision=14" -d "serialize_precision=-1" -d "memory_limit=128M" -d "opcache.fast_shutdown=0" -d "opcache.file_update_protection=0" -d "opcache.revalidate_freq=0" -d "opcache.jit_hot_loop=1" -d "opcache.jit_hot_func=1" -d "opcache.jit_hot_return=1" -d "opcache.jit_hot_side_exit=1" -d "opcache.jit_max_root_traces=100000" -d "opcache.jit_max_side_traces=100000" -d "opcache.jit_max_exit_counters=100000" -d "opcache.protect_memory=1" -d "zend.assertions=1" -d "zend.exception_ignore_args=0" -d "zend.exception_string_param_max_len=15" -d "short_open_tag=0" -d "extension_dir=/php-src/modules/" -d "zend_extension=/php-src/modules/opcache.so" -d "session.auto_start=0" -d "opcache.enable=1" -d "opcache.enable_cli=1" -d "opcache.optimization_level=-1" -d "opcache.preload=/tmp/preload.inc" -d "opcache.jit=1235" -d "session.save_path=\"123;:/really\\\\completely:::/invalid;;,23123;213\"" -d "opcache.record_warnings=0" -f ./test.php

PHP Version

PHP 8.4.0-dev

Operating System

ubuntu 22.04

nielsdos commented 3 months ago

Can confirm:

==208366== Invalid read of size 8
==208366==    at 0x7888BB4: zend_jit_cleanup_func_info (zend_jit.c:2745)
==208366==    by 0x7888DC8: zend_real_jit_func (zend_jit.c:2799)
==208366==    by 0x788944A: zend_jit_hot_func (zend_jit.c:2908)
==208366==    by 0xFE00283: ???
==208366==    by 0x8F32E0: zend_execute (zend_vm_execute.h:62776)
==208366==    by 0x82B332: zend_execute_script (zend.c:1899)
==208366==    by 0x778520: php_execute_script_ex (main.c:2507)
==208366==    by 0x77869E: php_execute_script (main.c:2547)
==208366==    by 0x9B8EAC: do_cli (php_cli.c:966)
==208366==    by 0x9B9C04: main (php_cli.c:1340)
==208366==  Address 0x7c58298 is 36,568 bytes inside a block of size 65,536 free'd
==208366==    at 0x48468CF: free (vg_replace_malloc.c:985)
==208366==    by 0x7E7D6B: __zend_free (zend_alloc.c:3115)
==208366==    by 0x7E6958: _efree (zend_alloc.c:2596)
==208366==    by 0x772E76: zend_arena_destroy (zend_arena.h:48)
==208366==    by 0x777827: php_request_shutdown (main.c:1920)
==208366==    by 0x7804F68: accel_finish_startup_preload (ZendAccelerator.c:4645)
==208366==    by 0x78053C5: accel_finish_startup (ZendAccelerator.c:4778)
==208366==    by 0x7800016: accel_post_startup (ZendAccelerator.c:3335)
==208366==    by 0x829046: zend_post_startup (zend.c:1081)
==208366==    by 0x777E6A: php_module_startup (main.c:2256)
==208366==    by 0x9B7DB2: php_cli_startup (php_cli.c:410)
==208366==    by 0x9B9B68: main (php_cli.c:1307)
==208366==  Block was alloc'd at
==208366==    at 0x4843788: malloc (vg_replace_malloc.c:442)
==208366==    by 0x7E7C39: __zend_malloc (zend_alloc.c:3087)
==208366==    by 0x7E68D2: _emalloc (zend_alloc.c:2586)
==208366==    by 0x7E9806: zend_arena_create (zend_arena.h:36)
==208366==    by 0x7EA6AB: init_compiler (zend_compile.c:434)
==208366==    by 0x829430: zend_activate (zend.c:1282)
==208366==    by 0x777301: php_request_startup (main.c:1778)
==208366==    by 0x7804E72: accel_finish_startup_preload (ZendAccelerator.c:4610)
==208366==    by 0x78053C5: accel_finish_startup (ZendAccelerator.c:4778)
==208366==    by 0x7800016: accel_post_startup (ZendAccelerator.c:3335)
==208366==    by 0x829046: zend_post_startup (zend.c:1081)
==208366==    by 0x777E6A: php_module_startup (main.c:2256)

Simplified command line: valgrind ./sapi/cli/php -c . -d "opcache.jit_hot_loop=1" -d "opcache.jit_hot_func=1" -d "opcache.jit_hot_return=1" -d "opcache.jit_hot_side_exit=1" -d "opcache.enable=1" -d "opcache.enable_cli=1" -d "opcache.preload=./preload.inc" -d "opcache.jit=1235" -f ./test.php

EDIT: preload.inc can be simplified to:

<?php
class Foo {
    public static function test() {
        static $i = 0;
        var_dump(++$i);
    }
}

Foo::test();
nielsdos commented 3 months ago

The problem seems to be that the caller_info, callee_info and possibly call_map is allocated on the arena but not reset before being used by the next request? So we should probably set that to NULL somewhere although I'm not sure where.