|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2005-03-03 12:37 UTC] jr at terragate dot net
Description:
------------
PEAR's HTTP_WebDAV_Client causes PHP 5 to trow a deprecated warning as Exception:
Fatal error: Uncaught exception 'Exception' with message 'is_a(): Deprecated. Please use the instanceof operator' in /usr/lib/php/PEAR.php:248
Stack trace:
#0 /usr/lib/php/PEAR.php(248): is_a(true, 'PEAR_Error')
#1 /usr/lib/php/HTTP/Request.php(591): HTTP_Request->isError(true)
#2 /usr/lib/php/HTTP/WebDAV/Client/Stream.php(796): HTTP_Request->sendRequest()
#3 /usr/lib/php/HTTP/WebDAV/Client/Stream.php(446): HTTP_WebDAV_Client_Stream->_check_options()
#4 /var/www/localhost/htdocs/crash.php(5): HTTP_WebDAV_Client_Stream->dir_opendir('webdav://test:t...', 4)
#5 /var/www/localhost/htdocs/crash.php(5): DirectoryIterator->__construct('webdav://test:t...')
#6 {main}
thrown in /usr/lib/php/PEAR.php on line 248
Is this a bug or a feature (deprecation messages thrown as Exceptions)?
Changing the is_a in PEAR.php to instanceof causes a segfault.
Reproduce code:
---------------
<?php
require_once('HTTP/WebDAV/Client.php');
$it = new DirectoryIterator('webdav://test:test@webdav-host/');
echo 'Done';
?>
for the 'deprecation exception' and a additional change for the segfault:
PEAR.php ~line 248:
if ($data instanceof PEAR_Error) {
instead of:
if (is_a($data, 'PEAR_Error')) {
This requires a valid webdav URL (I can provide one if necessary).
Expected result:
----------------
Clean shutdown
Actual result:
--------------
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 22648)]
Done
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 22648)]
0x00000019 in ?? ()
#0 0x00000019 in ?? ()
#1 0x0829ca06 in _php_stream_free (stream=0x8652714, close_options=3)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/main/streams/streams.c:351
#2 0x081b0d74 in spl_ce_dir_object_free_storage (object=0x85e067c)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/ext/spl/spl_directory.c:66
#3 0x082e939d in zend_objects_store_del_ref (zobject=0x85f4430)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend_objects_API.c:159
#4 0x082cc90f in _zval_dtor (zvalue=0x85da6ac,
__zend_filename=0x84a0800 "/var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend_execute_API.c", __zend_lineno=392)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend_variables.c:61
#5 0x082c19cb in _zval_ptr_dtor (zval_ptr=0x85ddda8,
__zend_filename=0x85f4430 "xA_\b\uffff\001^\b", __zend_lineno=140461104)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend_execute_API.c:392
#6 0x082ccce2 in _zval_ptr_dtor_wrapper (zval_ptr=0x85f4430)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend_variables.c:193
#7 0x082d976f in zend_hash_apply_deleter (ht=0x85131b0, p=0x85ddd9c)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend_hash.c:574
#8 0x082d707c in zend_hash_graceful_reverse_destroy (ht=0x85131b0)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend_hash.c:640
#9 0x082c123a in shutdown_executor ()
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend_execute_API.c:208
#10 0x082cddde in zend_deactivate ()
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/Zend/zend.c:818
#11 0x08288352 in php_request_shutdown (dummy=0x0)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/main/main.c:1212
#12 0x083111b7 in main (argc=2, argv=0xbffff844)
at /var/tmp/portage/php-5.0.3/work/php-5.0.3/sapi/cli/php_cli.c:1046
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 03:00:01 2025 UTC |
I was able to create a smaller example for the exception: <?php class StreamWrapper { public function dir_opendir($path, $options) { return is_a(null, 'AKnownOrUnknownClass'); } } stream_wrapper_register('test', 'StreamWrapper'); $it = new DirectoryIterator('test://path/'); ?> This will raise the following exception: Fatal error: Uncaught exception 'Exception' with message 'is_a(): Deprecated. Please use the instanceof operator' in /var/www/localhost/htdocs/splexception.php:6 Stack trace: #0 /var/www/localhost/htdocs/splexception.php(6): is_a(NULL, 'AKnownOrUnknown...') #1 /var/www/localhost/htdocs/splexception.php(13): StreamWrapper->dir_opendir('test://path/', 4) #2 /var/www/localhost/htdocs/splexception.php(13): DirectoryIterator->__construct('test://path/') #3 {main} thrown in /var/www/localhost/htdocs/splexception.php on line 6 This problem does not occur when using opendir so this seems to be SPL related. Category changed accordingly I wasn't able to reproduce the instanceof crash with this small snippet.I already tested the bug against yesterdays snapshot of 5.0.x. Using the 5.1.0 snap does not resolve the exception issue. I will test the instanceof segfault on monday against the 5.1 branch. Maybe I should create a seperate bug for it. voyager:~/Downloads/php5-200503041530/result/bin jr$ uname -a Darwin voyager.starbase12.sfn 7.8.0 Darwin Kernel Version 7.8.0: Wed Dec 22 14:26:17 PST 2004; root:xnu/ xnu-517.11.1.obj~1/RELEASE_PPC Power Macintosh powerpc voyager:~/Downloads/php5-200503041530/result/bin jr$ ./ php -v PHP 5.1.0-dev (cgi) (built: Mar 4 2005 18:33:26) (DEBUG) Copyright (c) 1997-2004 The PHP Group Zend Engine v2.1.0-dev, Copyright (c) 1998-2004 Zend Technologies voyager:~/Downloads/php5-200503041530/result/bin jr$ ./ php test.php Content-type: text/html X-Powered-By: PHP/5.1.0-dev <br /> <b>Fatal error</b>: Uncaught exception 'Exception' with message 'is_a(): Deprecated. Please use the instanceof operator' in /Volumes/Data/Users/jr/Downloads/php5 -200503041530/result/bin/test.php:6 Stack trace: #0 /Volumes/Data/Users/jr/Downloads/php5-200503041530/ result/bin/test.php(12): StreamWrapper- >dir_opendir(NULL, 'AKnownOrUnknown...') #1 /Volumes/Data/Users/jr/Downloads/php5-200503041530/ result/bin/test.php(12): DirectoryIterator- >__construct('test://path/', 4) #2 {main} thrown in <b>/Volumes/Data/Users/jr/Downloads/php5 -200503041530/result/bin/test.php</b> on line <b>6</ b><br /> /Volumes/Data/Users/jr/Downloads/php5-200503041530/ result/bin/test.php(6) : Fatal error - Uncaught exception 'Exception' with message 'is_a(): Deprecated. Please use the instanceof operator' in /Volumes/Data/ Users/jr/Downloads/php5-200503041530/result/bin/ test.php:6 Stack trace: #0 /Volumes/Data/Users/jr/Downloads/php5-200503041530/ result/bin/test.php(12): StreamWrapper- >dir_opendir(NULL, 'AKnownOrUnknown...') #1 /Volumes/Data/Users/jr/Downloads/php5-200503041530/ result/bin/test.php(12): DirectoryIterator- >__construct('test://path/', 4) #2 {main} thrownFinally I was able to create a smaller test case for the segfault (with error_reporting = E_ALL): <?php class StreamWrapper { public function dir_opendir($path, $options) { return TRUE; } public function dir_readdir() { return FALSE; } } stream_wrapper_register('test', 'StreamWrapper'); $it = new DirectoryIterator('test://path/'); echo "Done\n"; ?> Trace: (gdb) r crash.php Starting program: /usr/local/bin/php crash.php warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code. [Thread debugging using libthread_db enabled] [New Thread 16384 (LWP 15212)] Done Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 16384 (LWP 15212)] 0x00000019 in ?? () Current language: auto; currently asm (gdb) bt #0 0x00000019 in ?? () #1 0x081abc73 in _php_stream_free (stream=0x82fdce4, close_options=3) at /root/compile/php5-STABLE-200503091530/main/streams/streams.c:351 #2 0x080b3fb8 in spl_ce_dir_object_free_storage (object=0x82f76c4) at /root/compile/php5-STABLE-200503091530/ext/spl/spl_directory.c:66 #3 0x081fa906 in zend_objects_store_del_ref (zobject=0x82fd4e4) at /root/compile/php5-STABLE-200503091530/Zend/zend_objects_API.c:159 #4 0x081deb76 in _zval_dtor (zvalue=0x82fd4e4, __zend_filename=0x82549e0 "/root/compile/php5-STABLE-200503091530/Zend/zend_execute_API.c", __zend_lineno=392) at /root/compile/php5-STABLE-200503091530/Zend/zend_variables.c:61 #5 0x081d36f8 in _zval_ptr_dtor (zval_ptr=0x82fdda0, __zend_filename=0x8255940 "/root/compile/php5-STABLE-200503091530/Zend/zend_variables.c", __zend_lineno=193) at /root/compile/php5-STABLE-200503091530/Zend/zend_execute_API.c:392 #6 0x081dee88 in _zval_ptr_dtor_wrapper (zval_ptr=0x82fdda0) at /root/compile/php5-STABLE-200503091530/Zend/zend_variables.c:193 #7 0x081e8f13 in zend_hash_apply_deleter (ht=0x82761d0, p=0x82fdd94) at /root/compile/php5-STABLE-200503091530/Zend/zend_hash.c:574 #8 0x081e9164 in zend_hash_graceful_reverse_destroy (ht=0x82761d0) at /root/compile/php5-STABLE-200503091530/Zend/zend_hash.c:640 #9 0x081d302f in shutdown_executor () at /root/compile/php5-STABLE-200503091530/Zend/zend_execute_API.c:208 #10 0x081e0264 in zend_deactivate () at /root/compile/php5-STABLE-200503091530/Zend/zend.c:817 #11 0x081996e1 in php_request_shutdown (dummy=0x0) at /root/compile/php5-STABLE-200503091530/main/main.c:1214 #12 0x082155d0 in main (argc=2, argv=0xbffff844) at /root/compile/php5-STABLE-200503091530/sapi/cli/php_cli.c:1046 The script will be fully executed but php segfaults on shutdown. The behavior in the complex test case (with the WebDAV stream wrapper) was the same: Using instaneof instead of is_a caused the script to be fully executed but with a segfault on shutdown. To answer your second question I modified the test case above: <?php class StreamWrapper { public function dir_opendir($path, $options) { is_a(null, 'AKnownOrUnknownClass'); return TRUE; } public function dir_readdir() { return FALSE; } } stream_wrapper_register('test', 'StreamWrapper'); $it = new DirectoryIterator('test://path/'); echo "Done\n"; ?> Running this script with error_reporting set to E_ALL (or even E_ALL & ~E_NOTICE & ~E_STRICT) will lead to the behaviour already mentioned (deprecation warning thrown as exception). Running the script with error_reporting = 0 will terminate the script with exit code 0377 and without outputting 'Done'. Using gdb I figured out that php_error_cb is still called with the deprecation warning and zend_throw_exception will abort the script. We have two issues here: 1. A wrong free causing a segfault on shutdown 2. PHP notices and warnings thrown as exception I dont't know what to do with the segfault (my knowledge about PHP's internals is too limited to debug this yet). IMHO the second problem could be solved in 2 ways: 1. Modifying php_error_cb's behavior (as my patch does) 2. Do not set error_mode to EH_THROW in spl_directory.c if a user space stream wrapper is used.