Skip to content

Instantly share code, notes, and snippets.

@arjenschol arjenschol/backtrace
Last active Dec 22, 2015

Embed
What would you like to do?
Fatal error: Cannot destroy active lambda function in /mnt/serve-a-lot_arjen/public_html/php/bug-ob-start-closure/test2.php on line 549
Program received signal SIGSEGV, Segmentation fault.
zend_mm_remove_from_free_list (heap=0xf43290, mm_block=0x7ffff6139d60) at /home/arjen/php/php-5.4/php-src/Zend/zend_alloc.c:805
warning: Source file is more recent than executable.
805 ZEND_MM_CHECK_TREE(mm_block);
(gdb) bt full
#0 zend_mm_remove_from_free_list (heap=0xf43290, mm_block=0x7ffff6139d60) at /home/arjen/php/php-5.4/php-src/Zend/zend_alloc.c:805
index = 14
rp = <optimized out>
cp = <optimized out>
prev = <optimized out>
next = 0x7ffff6139d60
#1 0x00000000006fd403 in _zend_mm_free_int (heap=0xf43290, p=0x7ffff6141d30) at /home/arjen/php/php-5.4/php-src/Zend/zend_alloc.c:2106
mm_block = 0x7ffff6139d60
next_block = 0x7ffff6146178
size = 205536
#2 0x000000000071813c in destroy_op_array (op_array=0x7ffff7fc9aa8) at /home/arjen/php/php-5.4/php-src/Zend/zend_opcode.c:381
literal = 0x7ffff6146178
end = 0x7ffff6146178
i = <optimized out>
#3 0x000000000072e778 in zend_hash_destroy (ht=0x7ffff7fc1690) at /home/arjen/php/php-5.4/php-src/Zend/zend_hash.c:560
p = 0x7ffff7fc9920
q = 0x7ffff7fc91b8
#4 0x0000000000717ee5 in destroy_zend_class (pce=<optimized out>) at /home/arjen/php/php-5.4/php-src/Zend/zend_opcode.c:296
ce = 0x7ffff7fc1668
#5 0x000000000072d11b in zend_hash_apply_deleter (ht=ht@entry=0xf43bf0, p=p@entry=0xfa9940) at /home/arjen/php/php-5.4/php-src/Zend/zend_hash.c:650
retval = <optimized out>
#6 0x000000000072ec69 in zend_hash_reverse_apply (ht=0xf43bf0, apply_func=apply_func@entry=0x712fa0 <clean_non_persistent_class>)
at /home/arjen/php/php-5.4/php-src/Zend/zend_hash.c:804
result = 1
p = 0x10ef940
q = 0xfa9940
#7 0x0000000000713609 in shutdown_executor () at /home/arjen/php/php-5.4/php-src/Zend/zend_execute_API.c:303
__orig_bailout = 0x7fffffffe5b0
__bailout = {{__jmpbuf = {15998512, -2946347727049205886, 0, 140737488349847, 0, 0, 2946346250059110274, -2946346671174985854},
__mask_was_saved = 0, __saved_mask = {__val = {0, 0, 0, 140737353793640, 12750417304, 128, 140737353870744, 0, 140737488349847,
140737353870696, 17769168, 15976928, 17769168, 15998512, 15998512, 0}}}}
#8 0x0000000000721776 in zend_deactivate () at /home/arjen/php/php-5.4/php-src/Zend/zend.c:938
No locals.
#9 0x00000000006c5100 in php_request_shutdown (dummy=dummy@entry=0x0) at /home/arjen/php/php-5.4/php-src/main/main.c:1808
report_memleaks = 1 '\001'
#10 0x00000000007c6994 in do_cli (argc=3, argv=0x7fffffffe798) at /home/arjen/php/php-5.4/php-src/sapi/cli/php_cli.c:1172
c = <optimized out>
file_handle = {type = ZEND_HANDLE_MAPPED, filename = 0x7fffffffea97 "/mnt/serve-a-lot_arjen/public_html/php/bug-ob-start-closure/test2.php",
opened_path = 0x0, handle = {fd = -134478856, fp = 0x7ffff7fc03f8, stream = {handle = 0x7ffff7fc03f8, isatty = 0, mmap = {len = 16117,
pos = 0, map = 0x7ffff7fec000, buf = 0x7ffff7fec000 <Address 0x7ffff7fec000 out of bounds>, old_handle = 0x10f1df0,
old_closer = 0x736710 <zend_stream_stdio_closer>}, reader = 0x736730 <zend_stream_stdio_reader>,
fsizer = 0x7366b0 <zend_stream_stdio_fsizer>, closer = 0x736630 <zend_stream_mmap_closer>}}, free_filename = 0 '\000'}
behavior = <optimized out>
reflection_what = <optimized out>
request_started = 1
exit_status = 0
php_optarg = 0x0
php_optind = 3
exec_direct = <optimized out>
exec_run = <optimized out>
exec_begin = <optimized out>
exec_end = <optimized out>
arg_free = <optimized out>
arg_excp = <optimized out>
script_file = <optimized out>
translated_path = 0x10f22d0 "/mnt/serve-a-lot_arjen/public_html/php/bug-ob-start-closure/test2.php"
interactive = <optimized out>
lineno = 1
param_error = <optimized out>
hide_argv = <optimized out>
#11 0x0000000000428cf8 in main (argc=3, argv=0x7fffffffe798) at /home/arjen/php/php-5.4/php-src/sapi/cli/php_cli.c:1365
---Type <return> to continue, or q <return> to quit---
__orig_bailout = 0x0
__bailout = {{__jmpbuf = {16003568, -2946346248848550014, 1, 0, 15884512, 0, 2946346249700497282, -2946346777465727102},
__mask_was_saved = 0, __saved_mask = {__val = {140737325995136, 140737328163744, 140737354125312, 0, 140737354130568, 140737488348752,
140737488348736, 4131212846, 4270962, 4294967295, 140737488349112, 140737328251304, 140737353943456, 140737354129712, 0, 1}}}}
c = <optimized out>
exit_status = 0
module_started = 1
sapi_started = 1
php_optarg = 0x0
php_optind = 2
use_extended_info = 1
ini_path_override = 0x0
ini_entries = 0xf431f0 "html_errors=0\nregister_argc_argv=1\nimplicit_flush=1\noutput_buffering=0\nmax_execution_time=0\nmax_input_time=-1\n"
ini_entries_len = <optimized out>
ini_ignore = 0
sapi_module = <optimized out>
<?php
function ciao()
{
$out = '<pre>';
$args = func_get_args();
if(!empty($args))
{
// var_export() causes fatal errors on recursion...
ob_start();
ini_set('xdebug.var_display_max_depth', 4);
var_dump($args);
$out .= ob_get_contents()."\n\n";
ob_end_clean();
}
$out .= get_backtrace(1);
die($out);
}
class A {
function B()
{
while (ob_get_level() > 1)
ob_end_flush();
// store possible trailing content
$content = ob_get_clean();
// start an output buffer which cannot be flushed (3rd parameter is false)
// callback function get all output and corrects Content-Length header
ob_start(function($buffer) {
ciao($buffer);
}, 0, false);
}
}
$a = new A;
$a->B();
<?php
class FirePHP {
/**
* Gets singleton instance of FirePHP
*
* @param boolean $AutoCreate
* @return FirePHP
*/
public static function getInstance($AutoCreate=false) {
if($AutoCreate===true && !self::$instance) {
self::init();
}
return self::$instance;
}
/**
* Creates FirePHP object and stores it for singleton access
*
* @return FirePHP
*/
public static function init() {
return self::$instance = new self();
}
/**
* Enable and disable logging to Firebug
*
* @param boolean $Enabled TRUE to enable, FALSE to disable
* @return void
*/
public function setEnabled($Enabled) {
$this->enabled = $Enabled;
}
/**
* Check if logging is enabled
*
* @return boolean TRUE if enabled
*/
public function getEnabled() {
return $this->enabled;
}
/**
* Specify a filter to be used when encoding an object
*
* Filters are used to exclude object members.
*
* @param string $Class The class name of the object
* @param array $Filter An array or members to exclude
* @return void
*/
public function setObjectFilter($Class, $Filter) {
$this->objectFilters[$Class] = $Filter;
}
/**
* Register FirePHP as your error handler
*
* Will throw exceptions for each php error.
*/
public function registerErrorHandler()
{
//NOTE: The following errors will not be caught by this error handler:
// E_ERROR, E_PARSE, E_CORE_ERROR,
// E_CORE_WARNING, E_COMPILE_ERROR,
// E_COMPILE_WARNING, E_STRICT
set_error_handler(array($this,'errorHandler'));
}
/**
* FirePHP's error handler
*
* Throws exception for each php error that will occur.
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param array $errcontext
*/
public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
{
// Don't throw exception if error reporting is switched off
if (error_reporting() == 0) {
return;
}
// Only throw exceptions for errors we are asking for
if (error_reporting() & $errno) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
}
/**
* Register FirePHP as your exception handler
*/
public function registerExceptionHandler()
{
set_exception_handler(array($this,'exceptionHandler'));
}
/**
* FirePHP's exception handler
*
* Logs all exceptions to your firebug console and then stops the script.
*
* @param Exception $Exception
* @throws Exception
*/
function exceptionHandler($Exception) {
$this->fb($Exception);
}
/**
* Set custom processor url for FirePHP
*
* @param string $URL
*/
public function setProcessorUrl($URL)
{
$this->setHeader('X-FirePHP-ProcessorURL', $URL);
}
/**
* Set custom renderer url for FirePHP
*
* @param string $URL
*/
public function setRendererUrl($URL)
{
$this->setHeader('X-FirePHP-RendererURL', $URL);
}
/**
* Start a group for following messages
*
* @param string $Name
* @return true
* @throws Exception
*/
public function group($Name) {
return $this->fb(null, $Name, FirePHP::GROUP_START);
}
/**
* Ends a group you have started before
*
* @return true
* @throws Exception
*/
public function groupEnd() {
return $this->fb(null, null, FirePHP::GROUP_END);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::LOG
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public function log($Object, $Label=null) {
return $this->fb($Object, $Label, FirePHP::LOG);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::INFO
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public function info($Object, $Label=null) {
return $this->fb($Object, $Label, FirePHP::INFO);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::WARN
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public function warn($Object, $Label=null) {
return $this->fb($Object, $Label, FirePHP::WARN);
}
/**
* Log object with label to firebug console
*
* @see FirePHP::ERROR
* @param mixes $Object
* @param string $Label
* @return true
* @throws Exception
*/
public function error($Object, $Label=null) {
return $this->fb($Object, $Label, FirePHP::ERROR);
}
/**
* Dumps key and variable to firebug server panel
*
* @see FirePHP::DUMP
* @param string $Key
* @param mixed $Variable
* @return true
* @throws Exception
*/
public function dump($Key, $Variable) {
return $this->fb($Variable, $Key, FirePHP::DUMP);
}
/**
* Log a trace in the firebug console
*
* @see FirePHP::TRACE
* @param string $Label
* @return true
* @throws Exception
*/
public function trace($Label) {
return $this->fb($Label, FirePHP::TRACE);
}
public function table($Label, $Table) {
return $this->fb($Table, $Label, FirePHP::TABLE);
}
public function detectClientExtension() {
/* Check if FirePHP is installed on client */
if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) ||
!version_compare($m[1][0],'0.0.6','>=')) {
return false;
}
return true;
}
public function fb($Object) {
if(!$this->enabled) {
return false;
}
if (headers_sent($filename, $linenum)) {
throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.');
}
$Type = null;
$Label = null;
if(func_num_args()==1) {
} else
if(func_num_args()==2) {
switch(func_get_arg(1)) {
case self::LOG:
case self::INFO:
case self::WARN:
case self::ERROR:
case self::DUMP:
case self::TRACE:
case self::EXCEPTION:
case self::TABLE:
case self::GROUP_START:
case self::GROUP_END:
$Type = func_get_arg(1);
break;
default:
$Label = func_get_arg(1);
break;
}
} else
if(func_num_args()==3) {
$Type = func_get_arg(2);
$Label = func_get_arg(1);
} else {
throw $this->newException('Wrong number of arguments to fb() function!');
}
if(!$this->detectClientExtension()) {
return false;
}
$meta = array();
$skipFinalObjectEncode = false;
if($Object instanceof Exception) {
$meta['file'] = $this->_escapeTraceFile($Object->getFile());
$meta['line'] = $Object->getLine();
$trace = $Object->getTrace();
if($Object instanceof ErrorException
&& isset($trace[0]['function'])
&& $trace[0]['function']=='errorHandler'
&& isset($trace[0]['class'])
&& $trace[0]['class']=='FirePHP') {
$severity = false;
switch($Object->getSeverity()) {
case E_WARNING: $severity = 'E_WARNING'; break;
case E_NOTICE: $severity = 'E_NOTICE'; break;
case E_USER_ERROR: $severity = 'E_USER_ERROR'; break;
case E_USER_WARNING: $severity = 'E_USER_WARNING'; break;
case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break;
case E_STRICT: $severity = 'E_STRICT'; break;
case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break;
case E_DEPRECATED: $severity = 'E_DEPRECATED'; break;
case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break;
}
$Object = array('Class'=>get_class($Object),
'Message'=>$severity.': '.$Object->getMessage(),
'File'=>$this->_escapeTraceFile($Object->getFile()),
'Line'=>$Object->getLine(),
'Type'=>'trigger',
'Trace'=>$this->_escapeTrace(array_splice($trace,2)));
$skipFinalObjectEncode = true;
} else {
$Object = array('Class'=>get_class($Object),
'Message'=>$Object->getMessage(),
'File'=>$this->_escapeTraceFile($Object->getFile()),
'Line'=>$Object->getLine(),
'Type'=>'throw',
'Trace'=>$this->_escapeTrace($trace));
$skipFinalObjectEncode = true;
}
$Type = self::EXCEPTION;
} else
if($Type==self::TRACE) {
$trace = debug_backtrace();
if(!$trace) return false;
for( $i=0 ; $i<sizeof($trace) ; $i++ ) {
if(isset($trace[$i]['class'])
&& isset($trace[$i]['file'])
&& ($trace[$i]['class']=='FirePHP'
|| $trace[$i]['class']=='FB')
&& (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
|| substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
/* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
} else
if(isset($trace[$i]['class'])
&& isset($trace[$i+1]['file'])
&& $trace[$i]['class']=='FirePHP'
&& substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
/* Skip fb() */
} else
if($trace[$i]['function']=='fb'
|| $trace[$i]['function']=='trace'
|| $trace[$i]['function']=='send') {
$Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'',
'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'',
'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'',
'Message'=>$trace[$i]['args'][0],
'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'',
'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'',
'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'',
'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1)));
$skipFinalObjectEncode = true;
$meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
$meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
break;
}
}
} else
if($Type==self::TABLE) {
if(isset($Object[0]) && is_string($Object[0])) {
$Object[1] = $this->encodeTable($Object[1]);
} else {
$Object = $this->encodeTable($Object);
}
$skipFinalObjectEncode = true;
} else {
if($Type===null) {
$Type = self::LOG;
}
}
if($this->options['includeLineNumbers']) {
if(!isset($meta['file']) || !isset($meta['line'])) {
$trace = debug_backtrace();
for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) {
if(isset($trace[$i]['class'])
&& isset($trace[$i]['file'])
&& ($trace[$i]['class']=='FirePHP'
|| $trace[$i]['class']=='FB')
&& (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
|| substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
/* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
} else
if(isset($trace[$i]['class'])
&& isset($trace[$i+1]['file'])
&& $trace[$i]['class']=='FirePHP'
&& substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
/* Skip fb() */
} else
if(isset($trace[$i]['file'])
&& substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') {
/* Skip FB::fb() */
} else {
$meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
$meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
break;
}
}
}
} else {
unset($meta['file']);
unset($meta['line']);
}
$this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
$this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION);
$structure_index = 1;
if($Type==self::DUMP) {
$structure_index = 2;
$this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
} else {
$this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
}
if($Type==self::DUMP) {
$msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}';
} else {
$msg_meta = array('Type'=>$Type);
if($Label!==null) {
$msg_meta['Label'] = $Label;
}
if(isset($meta['file'])) {
$msg_meta['File'] = $meta['file'];
}
if(isset($meta['line'])) {
$msg_meta['Line'] = $meta['line'];
}
$msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']';
}
$parts = explode("\n",chunk_split($msg, 5000, "\n"));
for( $i=0 ; $i<count($parts) ; $i++) {
$part = $parts[$i];
if ($part) {
if(count($parts)>2) {
// Message needs to be split into multiple parts
$this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
(($i==0)?strlen($msg):'')
. '|' . $part . '|'
. (($i<count($parts)-2)?'\\':''));
} else {
$this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
strlen($part) . '|' . $part . '|');
}
$this->messageIndex++;
if ($this->messageIndex > 99999) {
throw new Exception('Maximum number (99,999) of messages reached!');
}
}
}
$this->setHeader('X-Wf-1-Index',$this->messageIndex-1);
return true;
}
protected function _standardizePath($Path) {
}
protected function _escapeTrace($Trace) {
if(!$Trace) return $Trace;
for( $i=0 ; $i<sizeof($Trace) ; $i++ ) {
if(isset($Trace[$i]['file'])) {
$Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']);
}
if(isset($Trace[$i]['args'])) {
$Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']);
}
}
return $Trace;
}
protected function _escapeTraceFile($File) {
/* Check if we have a windows filepath */
if(strpos($File,'\\')) {
/* First strip down to single \ */
$file = preg_replace('/\\\\+/','\\',$File);
return $file;
}
return $File;
}
protected function setHeader($Name, $Value) {
return header($Name.': '.$Value);
}
protected function getUserAgent() {
if(!isset($_SERVER['HTTP_USER_AGENT'])) return false;
return $_SERVER['HTTP_USER_AGENT'];
}
}
function ciao()
{
$out = '<pre>';
$args = func_get_args();
if(!empty($args))
{
// var_export() causes fatal errors on recursion...
ob_start();
ini_set('xdebug.var_display_max_depth', 4);
var_dump($args);
$out .= ob_get_contents()."\n\n";
ob_end_clean();
}
$out .= get_backtrace(1);
die($out);
}
class A {
function B()
{
while (ob_get_level() > 1)
ob_end_flush();
// store possible trailing content
$content = ob_get_clean();
// start an output buffer which cannot be flushed (3rd parameter is false)
// callback function get all output and corrects Content-Length header
ob_start(function($buffer) {
ciao($buffer);
}, 0, false);
}
}
$a = new A;
$a->B();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.