php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81430 Attribute instantiation leaves dangling execute_data pointer
Submitted: 2021-09-10 16:22 UTC Modified: -
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: bwoebi@php.net Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 8.0.10 OS: MacOS 11
Private report: No CVE-ID: None
 [2021-09-10 16:22 UTC] bwoebi@php.net
Description:
------------
I found sporadic crashes in my application upon max_time_limit exhaustion. They were all somewhere within zend_observer_fcall_end_all.

The crashes are all related to invalid contents within current_observed_frame.

In this specific reproducer I found, the issue is related to attributes, which use a stack allocated dummy frame (notably with ex->func being non-NULL, which is unlike the generator dummy frames).

Test script:
---------------
Using zend_test with INI:
zend_test.observer.enabled=1
zend_test.observer.observe_all=1

<?php

namespace X; // avoid cuf() being optimized away

ini_set("memory_limit", "20M");

#[\Attribute]
class A {
        public function __construct() {}
}

#[A]
function B() {}

$r = new \ReflectionFunction("X\\B");
var_dump(call_user_func([$r->getAttributes(A::class)[0], 'newInstance']));

array_map("str_repeat", ["\xFF"], [100000000]); // cause a bailout

Expected result:
----------------
No crash.

Actual result:
--------------
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x0000000100722f16 php`zend_observer_fcall_end(execute_data=0x00007ffeefbfde70, return_value=0x0000000000000000) at zend_observer.c:211:42
    frame #1: 0x00000001007230a3 php`zend_observer_fcall_end_all at zend_observer.c:243:4
    frame #2: 0x00000001004fd7c5 php`php_request_shutdown(dummy=0x0000000000000000) at main.c:1783:3
    frame #3: 0x00000001007a44d1 php`do_cli(argc=4, argv=0x00007ffeefbff930) at php_cli.c:1135:3
(lldb) p execute_data
(zend_execute_data *) $0 = 0x00007ffeefbfde70 // stack memory


Patches

fix81430.patch (last revision 2021-11-12 15:01 UTC by f dot sowade at r9e dot de)

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-11-12 15:01 UTC] f dot sowade at r9e dot de
The following patch has been added/updated:

Patch Name: fix81430.patch
Revision:   1636729289
URL:        https://bugs.php.net/patch-display.php?bug=81430&patch=fix81430.patch&revision=1636729289
 [2021-11-12 15:07 UTC] f dot sowade at r9e dot de
The problem seems to be that func->op_array->run_time_cache__ptr is NULL in the reflection dummy frame. I added a patch that checks for a null pointer before accessing the run_time_cache. This fixes the crash for me.

An alternative solution would be to initialize the run_time_cache in the dummy frame as well. I think this fix would have to be done in the call_attribute_constructor() in ext/reflection/php_reflection.c.

Not sure which of these fixes makes more sense.
 [2021-11-18 15:23 UTC] f dot sowade at r9e dot de
The following pull request has been associated:

Patch Name: Fixed bug #81430 Check if runtime cache pointer is NULL before dereferencing
On GitHub:  https://github.com/php/php-src/pull/7665
Patch:      https://github.com/php/php-src/pull/7665.patch
 [2021-11-29 10:02 UTC] beberlei@php.net
A workaround on PHP extension level is to not register an observer for attribute constructor functions.

We have an example for this in our open-source extension in this PR: https://github.com/tideways/php-xhprof-extension/pull/109/files
 [2022-01-10 11:43 UTC] git@php.net
Automatic comment on behalf of beberlei (author) and cmb69 (committer)
Revision: https://github.com/php/php-src/commit/2f6a06ccb0ef78e6122bb9e67f9b8b1ad07776e1
Log: Fix #81430: Attribute instantiation leaves dangling pointer
 [2022-01-10 11:43 UTC] git@php.net
-Status: Open +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 08:01:29 2024 UTC