php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79885 Backtrace behaviour seems wrong/changed
Submitted: 2020-07-22 14:48 UTC Modified: 2020-07-22 15:23 UTC
From: kenashkov at gmail dot com Assigned:
Status: Wont fix Package: Scripting Engine problem
PHP Version: 7.4.8 OS: Debian 9 4.15.0-91-generic
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2020-07-22 14:48 UTC] kenashkov at gmail dot com
Description:
------------
The backtrace generate at object __destruct() seems has changed. PHP 7.2.24 returns the expected result, while on PHP 7.4.8 a stack frame is missing.

Test script:
---------------
<?php

class ref
{
    public function __destruct() {
	debug_print_backtrace();
	print 'destr';
    }
}

function f1() {
    try {
	f2();
    } catch (\Exception $E) {
	
    }
}


function f2() {
    $o = new ref;
    throw new \Exception('ex');
}

f1();

Expected result:
----------------
#0  ref->__destruct() called at [/t1.php:22]
#1  f2() called at [/t1.php:13]
#2  f1() called at [/t1.php:25]

Actual result:
--------------
#0  ref->__destruct() called at [/t1.php:13]
#1  f1() called at [/t1.php:25]

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-07-22 14:54 UTC] nikic@php.net
-Status: Open +Status: Wont fix
 [2020-07-22 14:54 UTC] nikic@php.net
This is an intentional change, specifically to prevent access to partially destroyed local variables from a destructor backtrace. Local variables are now destroyed after switching to the parent frame, which ensures that they cannot be observed in a partially destroyed state.
 [2020-07-22 15:17 UTC] kenashkov at gmail dot com
Im not sure this is correct as it is breaking existing code and in fact is missing a whole frame. Im using backtrace in destructor to obtain the exact frame/reason for the object destruction (I use Scope based resource management). For example I use it to check why an object was destroyed - because of the local scope being left with return or because of a throw and for this I need the line where actually the destruction was triggered (and then I log the reason why a transaction was rolled back), not just the method in which this happened.

Perhaps we can have a backtrace only with method/class/file/line info without the variables? 
Related to this I have also considered the case when there is an exception thrown and it automatically obtains a complete backtrace (including the local vars) this actually creates a side effect that effectively "pulls" scope reference objects out of the scope they were intended for (again related to the SBRM). Pehraps there needs to be an option/way to indicate whether the vars should be preserved...
For debug_backtrace with DEBUG_BACKTRACE_IGNORE_ARGS provided it could work as before. And it will be great if there was way to throw an exception without dragging all the vars along with it. But that perhaps can be achieved only with one more php INI setting...
 [2020-07-22 15:23 UTC] kenashkov at gmail dot com
Actually looking again at the backtrace - missing the f2() call is very wrong in my opinion. Even thinking outside the wrong __destruct() file&line info, missing a whole call cant be the right thing. I the backtrace is used for some auditing and then missing a function call can be disastrous. An existing solution that is not upgraded for 7.4 may start missing calls and provide wrong audit info without any warning or error...
Is it being considered to be fixed in PHP 8?
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Sun Nov 29 14:01:24 2020 UTC