Skip to content
New issue

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

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

Already on GitHub? Sign in 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants