Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Stack-use-after-return with lazy objects and hooks #17941

Open
nielsdos opened this issue Feb 26, 2025 · 1 comment
Open

Stack-use-after-return with lazy objects and hooks #17941

nielsdos opened this issue Feb 26, 2025 · 1 comment

Comments

@nielsdos
Copy link
Member

Description

The following code:

<?php

class SubClass {
    public $prop {get => $this->prop; set($x) => $this->prop = $x;}
}

$rc = new ReflectionClass(SubClass::class);
$obj = $rc->newLazyProxy(function ($object) {
    echo "init\n";
    return new SubClass;
});

function foo(SubClass $x) {
    $x->prop = 1;
    var_dump($x->prop);
}

foo($obj);

Resulted in this output:

==461162==ERROR: AddressSanitizer: stack-use-after-return on address 0x7ffff2b19588 at pc 0x5555567e8be8 bp 0x7fffffffa840 sp 0x7fffffffa830
READ of size 4 at 0x7ffff2b19588 thread T0
    #0 0x5555567e8be7 in ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER /run/media/niels/MoreData/php-8.4/Zend/zend_vm_execute.h:34704
    #1 0x55555686f78a in execute_ex /run/media/niels/MoreData/php-8.4/Zend/zend_vm_execute.h:62411
    #2 0x5555566c87b1 in zend_call_function /run/media/niels/MoreData/php-8.4/Zend/zend_execute_API.c:1000
    #3 0x5555566c97d4 in zend_call_known_function /run/media/niels/MoreData/php-8.4/Zend/zend_execute_API.c:1094
    #4 0x5555569546b2 in zend_call_known_instance_method /run/media/niels/MoreData/php-8.4/Zend/zend_API.h:860
    #5 0x555556954727 in zend_call_known_instance_method_with_1_params /run/media/niels/MoreData/php-8.4/Zend/zend_API.h:872
    #6 0x55555695c411 in zend_std_write_property /run/media/niels/MoreData/php-8.4/Zend/zend_object_handlers.c:1115
    #7 0x5555568195b9 in ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_HANDLER /run/media/niels/MoreData/php-8.4/Zend/zend_vm_execute.h:43448
    #8 0x555556872aa9 in execute_ex /run/media/niels/MoreData/php-8.4/Zend/zend_vm_execute.h:63270
    #9 0x555556876266 in zend_execute /run/media/niels/MoreData/php-8.4/Zend/zend_vm_execute.h:64236
    #10 0x5555569d2261 in zend_execute_script /run/media/niels/MoreData/php-8.4/Zend/zend.c:1934
    #11 0x55555642c29c in php_execute_script_ex /run/media/niels/MoreData/php-8.4/main/main.c:2575
    #12 0x55555642c6a4 in php_execute_script /run/media/niels/MoreData/php-8.4/main/main.c:2615
    #13 0x5555569d7922 in do_cli /run/media/niels/MoreData/php-8.4/sapi/cli/php_cli.c:935
    #14 0x5555569d97c1 in main /run/media/niels/MoreData/php-8.4/sapi/cli/php_cli.c:1310
    #15 0x7ffff727f487  (/usr/lib/libc.so.6+0x27487) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0)
    #16 0x7ffff727f54b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0)
    #17 0x555555a03eb4 in _start (/run/media/niels/MoreData/php-8.4/sapi/cli/php+0x603eb4) (BuildId: 43bd49ea8b46359c52d4ca22813ac5995a8ba67e)

Address 0x7ffff2b19588 is located in stack of thread T0 at offset 136 in frame
    #0 0x55555695ab4e in zend_std_write_property /run/media/niels/MoreData/php-8.4/Zend/zend_object_handlers.c:960

  This frame has 4 object(s):
    [32, 40) 'prop_info' (line 963)
    [64, 72) 'garbage' (line 1023)
    [96, 112) 'tmp' (line 961)
    [128, 144) 'backup' (line 1189) <== Memory access at offset 136 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-return /run/media/niels/MoreData/php-8.4/Zend/zend_vm_execute.h:34704 in ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER
Shadow bytes around the buggy address:
  0x7ffff2b19300: f1 f1 f1 f1 f1 f1 00 00 f2 f2 00 00 00 00 00 f2
  0x7ffff2b19380: f2 f2 f2 f2 00 00 00 00 00 00 00 00 f3 f3 f3 f3
  0x7ffff2b19400: f1 f1 f1 f1 04 f2 00 f2 f2 f2 00 f2 f2 f2 00 00
  0x7ffff2b19480: 00 00 00 f2 f2 f2 f2 f2 00 00 f3 f3 00 00 00 00
  0x7ffff2b19500: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
=>0x7ffff2b19580: f5[f5]f5 f5 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ffff2b19600: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7ffff2b19680: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7ffff2b19700: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x7ffff2b19780: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 00 00 00 00
  0x7ffff2b19800: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==461162==ABORTING

But I expected this output instead:

Not that

PHP Version

8.4+

Operating System

Linux

@iluuu1994
Copy link
Member

iluuu1994 commented Feb 26, 2025

I can't reproduce this one on c8bead8 (before my recent hook changes), nor on the latest commit. I tried ASan and Valgrind, opcache and JITs. Edit: Ah, nevermind. I made some changes to the test I thought wouldn't make a difference. 😄

nielsdos added a commit to nielsdos/php-src that referenced this issue Feb 27, 2025
zend_std_write_property() can return the variable pointer, but the code
was using a local variable, and so a pointer to a local variable could
be returned. Fix this by using the value pointer instead.
This can be more efficient on master by using the safe_assign helper.
nielsdos added a commit to nielsdos/php-src that referenced this issue Feb 27, 2025
zend_std_write_property() can return the variable pointer, but the code
was using a local variable, and so a pointer to a local variable could
be returned. Fix this by using the value pointer instead of the backup
value was written.
This can be more efficient on master by using the safe_assign helper.
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants