- Improved upon r309729.

- Extented strategy to remaining the classes on spl_directory.c, even those that don't crash.
- UPGRADING.
- Better bug54384.phpt, with all the classes covered.
This commit is contained in:
Gustavo André dos Santos Lopes 2011-03-27 22:44:34 +00:00
parent 11efb7295e
commit f7b7b6aa9e
4 changed files with 132 additions and 52 deletions

View File

@ -184,6 +184,18 @@ UPGRADE NOTES - PHP X.Y
stream_truncate that will respond to truncation, e.g. through ftruncate.
Strictly speaking, this is an addition to the user-space stream wrapper
template, not a change to an actual class.
- Constructors of userspace subclasses of the following SPL classes are now
required to call the parent constructor and not clear any exceptions they
throw (replacing the thrown exception by another one is permitted):
SplFileInfo, DirectoryIterator, FilesystemIterator, GlobIterator,
SplFileObject, SplTempFileObject, RecursiveDirectoryIterator,
IteratorIterator, FilterIterator, RecursiveFilterIterator, ParentIterator,
LimitIterator, CachingIterator, RecursiveCachingIterator, NoRewindIterator,
AppendIterator, InfiniteIterator, RegexIterator, RecursiveRegexIterator, and
RecursiveTreeIterator.
It is no longer possible to defer the parent constructor call until after the
object is constructed.
=============
7. Deprecated

View File

@ -66,7 +66,7 @@ static PHP_GINIT_FUNCTION(spl)
cwf->type = ZEND_INTERNAL_FUNCTION;
cwf->common.function_name = "internal_construction_wrapper";
cwf->common.scope = NULL; /* to be filled */
cwf->common.scope = NULL; /* to be filled w/ object runtime class */
cwf->common.fn_flags = ZEND_ACC_PRIVATE;
cwf->common.prototype = NULL;
cwf->common.num_args = 0; /* not necessarily true but not enforced */
@ -815,8 +815,18 @@ static void construction_wrapper(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
zval *retval_ptr = NULL;
object_data = zend_object_store_get_object(this TSRMLS_CC);
zf = zend_get_std_object_handlers()->get_constructor(this TSRMLS_CC);
this_ce = Z_OBJCE_P(this);
/* The call of this internal function did not change the scope because
* zend_do_fcall_common_helper doesn't do that for internal instance
* function calls. So the visibility checks on zend_std_get_constructor
* will still work. Reflection refuses to instantiate classes whose
* constructor is not public so we're OK there too*/
zf = zend_std_get_constructor(this TSRMLS_CC);
if (zf == NULL) {
return;
}
fci.size = sizeof(fci);
fci.function_table = &this_ce->function_table;
@ -828,15 +838,17 @@ static void construction_wrapper(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
fci.params = emalloc(fci.param_count * sizeof *fci.params);
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), fci.params) == FAILURE) {
zend_throw_exception(NULL, "Unexpected error fetching arguments", 0 TSRMLS_CC);
return;
goto cleanup;
}
}
fci.object_ptr = this;
fci.no_separation = 0;
fci_cache.initialized = 1;
fci_cache.called_scope = EG(current_execute_data)->called_scope;
fci_cache.calling_scope = EG(current_execute_data)->current_scope;
fci_cache.called_scope = this_ce; /* set called scope to class of this */
/* function->common.scope will replace it, except for
* ZEND_OVERLOADED_FUNCTION, which we won't get */
fci_cache.calling_scope = EG(scope);
fci_cache.function_handler = zf;
fci_cache.object_ptr = this;
@ -852,6 +864,8 @@ static void construction_wrapper(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
"and its exceptions cannot be cleared", this_ce->name);
cleanup:
/* no need to cleanup zf, zend_std_get_constructor never allocates a new
* function (so no ZEND_OVERLOADED_FUNCTION or call-via-handlers) */
if (fci.params != NULL) {
efree(fci.params);
}

View File

@ -48,7 +48,6 @@
/* declare the class handlers */
static zend_object_handlers spl_filesystem_object_handlers;
static zend_object_handlers spl_filesystem_object_constru_check_handlers;
/* declare the class entry */
PHPAPI zend_class_entry *spl_ce_SplFileInfo;
@ -133,7 +132,7 @@ static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */
- clone
- new
*/
static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_type, zend_object_handlers *handlers, spl_filesystem_object **obj TSRMLS_DC)
static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_type, spl_filesystem_object **obj TSRMLS_DC)
{
zend_object_value retval;
spl_filesystem_object *intern;
@ -151,11 +150,8 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC);
if (!handlers) {
retval.handlers = &spl_filesystem_object_handlers;
} else {
retval.handlers = handlers;
}
retval.handlers = &spl_filesystem_object_handlers;
return retval;
}
/* }}} */
@ -164,13 +160,7 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
/* See spl_filesystem_object_new_ex */
static zend_object_value spl_filesystem_object_new(zend_class_entry *class_type TSRMLS_DC)
{
return spl_filesystem_object_new_ex(class_type, NULL /* spl_filesystem_object_handlers */, NULL TSRMLS_CC);
}
/* }}} */
static zend_object_value spl_filesystem_object_constru_check_new(zend_class_entry *class_type TSRMLS_DC)
{
return spl_filesystem_object_new_ex(class_type, &spl_filesystem_object_constru_check_handlers, NULL TSRMLS_CC);
return spl_filesystem_object_new_ex(class_type, NULL TSRMLS_CC);
}
/* }}} */
@ -320,7 +310,7 @@ static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC)
old_object = zend_objects_get_address(zobject TSRMLS_CC);
source = (spl_filesystem_object*)old_object;
new_obj_val = spl_filesystem_object_new_ex(old_object->ce, NULL, &intern TSRMLS_CC);
new_obj_val = spl_filesystem_object_new_ex(old_object->ce, &intern TSRMLS_CC);
new_object = &intern->std;
intern->flags = source->flags;
@ -419,7 +409,7 @@ static spl_filesystem_object * spl_filesystem_object_create_info(spl_filesystem_
zend_update_class_constants(ce TSRMLS_CC);
return_value->value.obj = spl_filesystem_object_new_ex(ce, NULL, &intern TSRMLS_CC);
return_value->value.obj = spl_filesystem_object_new_ex(ce, &intern TSRMLS_CC);
Z_TYPE_P(return_value) = IS_OBJECT;
if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
@ -462,7 +452,7 @@ static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_fil
zend_update_class_constants(ce TSRMLS_CC);
return_value->value.obj = spl_filesystem_object_new_ex(ce, NULL, &intern TSRMLS_CC);
return_value->value.obj = spl_filesystem_object_new_ex(ce, &intern TSRMLS_CC);
Z_TYPE_P(return_value) = IS_OBJECT;
spl_filesystem_object_get_file_name(source TSRMLS_CC);
@ -483,7 +473,7 @@ static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_fil
zend_update_class_constants(ce TSRMLS_CC);
return_value->value.obj = spl_filesystem_object_new_ex(ce, NULL, &intern TSRMLS_CC);
return_value->value.obj = spl_filesystem_object_new_ex(ce, &intern TSRMLS_CC);
Z_TYPE_P(return_value) = IS_OBJECT;
spl_filesystem_object_get_file_name(source TSRMLS_CC);
@ -2975,6 +2965,8 @@ PHP_MINIT_FUNCTION(spl_directory)
spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone;
spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast;
spl_filesystem_object_handlers.get_debug_info = spl_filesystem_object_get_debug_info;
spl_filesystem_object_handlers.get_constructor = spl_filesystem_object_get_constructor;
spl_ce_SplFileInfo->serialize = zend_class_serialize_deny;
spl_ce_SplFileInfo->unserialize = zend_class_unserialize_deny;
@ -3003,17 +2995,12 @@ PHP_MINIT_FUNCTION(spl_directory)
REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, FilesystemIterator, spl_filesystem_object_new, spl_RecursiveDirectoryIterator_functions);
REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator);
/* These need the parent constructor call check if extended in userspace.
* The previous ones probably don't work very well if */
memcpy(&spl_filesystem_object_constru_check_handlers, &spl_filesystem_object_handlers, sizeof(zend_object_handlers));
spl_filesystem_object_constru_check_handlers.get_constructor = spl_filesystem_object_get_constructor;
#ifdef HAVE_GLOB
REGISTER_SPL_SUB_CLASS_EX(GlobIterator, FilesystemIterator, spl_filesystem_object_constru_check_new, spl_GlobIterator_functions);
REGISTER_SPL_SUB_CLASS_EX(GlobIterator, FilesystemIterator, spl_filesystem_object_new, spl_GlobIterator_functions);
REGISTER_SPL_IMPLEMENTS(GlobIterator, Countable);
#endif
REGISTER_SPL_SUB_CLASS_EX(SplFileObject, SplFileInfo, spl_filesystem_object_constru_check_new, spl_SplFileObject_functions);
REGISTER_SPL_SUB_CLASS_EX(SplFileObject, SplFileInfo, spl_filesystem_object_new, spl_SplFileObject_functions);
REGISTER_SPL_IMPLEMENTS(SplFileObject, RecursiveIterator);
REGISTER_SPL_IMPLEMENTS(SplFileObject, SeekableIterator);
@ -3022,7 +3009,7 @@ PHP_MINIT_FUNCTION(spl_directory)
REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "SKIP_EMPTY", SPL_FILE_OBJECT_SKIP_EMPTY);
REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_CSV", SPL_FILE_OBJECT_READ_CSV);
REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_constru_check_new, spl_SplTempFileObject_functions);
REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_new, spl_SplTempFileObject_functions);
return SUCCESS;
}
/* }}} */

View File

@ -132,42 +132,46 @@ $o->rewind();
} );
function test2($f) {
try {
$f();
echo "ran normally (expected)\n";
} catch (LogicException $e) {
echo "exception (unexpected)\n\n";
}
}
echo "SplFileInfo... ";
class SplFileInfoTest extends SplFileInfo {
function __construct(){}
}
test2 ( function() {
test ( function() {
$o = new SplFileInfoTest;
/* handles with fatal error */
/* echo $o->getMTime(), " : "; */
$o->getMTime();
} );
echo "DirectoryIterator... ";
class DirectoryIteratortest extends DirectoryIterator {
function __construct(){}
}
test2 ( function() {
test ( function() {
$o = new DirectoryIteratorTest;
foreach ($o as $a) {
echo $a,"\n";
}
} );
echo "DirectoryIterator (exception cleared)... ";
class DirectoryIteratorTest2 extends DirectoryIterator {
function __construct(){
try {
parent::__construct();
} catch (Exception $e) { }
}
}
test ( function() {
$o = new DirectoryIteratorTest2;
foreach ($o as $a) {
echo $a,"\n";
}
} );
echo "FileSystemIterator... ";
class FileSystemIteratorTest extends DirectoryIterator {
function __construct(){}
}
test2 ( function() {
test ( function() {
$o = new FileSystemIteratorTest;
foreach ($o as $a) {
echo $a,"\n";
@ -178,12 +182,69 @@ echo "RecursiveDirectoryIterator... ";
class RecursiveDirectoryIteratorTest extends RecursiveDirectoryIterator {
function __construct(){}
}
test2 ( function() {
test ( function() {
$o = new RecursiveDirectoryIteratorTest;
foreach ($o as $a) {
echo $a,"\n";
}
} );
echo "RecursiveTreeIterator... ";
class RecursiveTreeIteratorTest extends RecursiveDirectoryIterator {
function __construct(){}
}
test ( function() {
$o = new RecursiveTreeIteratorTest;
foreach ($o as $a) {
echo $a,"\n";
}
} );
echo "AppendIterator... ";
class AppendIteratorTest extends AppendIterator {
function __construct(){}
}
test ( function() {
$o = new AppendIteratorTest;
foreach ($o as $a) {
echo $a,"\n";
}
} );
echo "InfiniteIterator... ";
class InfiniteIteratorTest extends InfiniteIterator {
function __construct(){}
}
test ( function() {
$o = new InfiniteIteratorTest;
foreach ($o as $a) {
echo $a,"\n";
}
} );
echo "CallbackFilterIterator... ";
class CallbackFilterIteratorTest extends CallbackFilterIterator {
function __construct(){}
}
test ( function() {
$o = new CallbackFilterIteratorTest;
foreach ($o as $a) {
echo $a,"\n";
}
} );
echo "RecursiveCallbackFilterIterator... ";
class RecursiveCallbackFilterIteratorTest extends RecursiveCallbackFilterIterator {
function __construct(){}
}
test ( function() {
$o = new RecursiveCallbackFilterIteratorTest;
foreach ($o as $a) {
echo $a,"\n";
}
} );
--EXPECT--
IteratorIterator... exception (expected)
FilterIterator... exception (expected)
@ -198,7 +259,13 @@ RecursiveRegexIterator... exception (expected)
GlobIterator... exception (expected)
SplFileObject... exception (expected)
SplTempFileObject... exception (expected)
SplFileInfo... ran normally (expected)
DirectoryIterator... ran normally (expected)
FileSystemIterator... ran normally (expected)
RecursiveDirectoryIterator... ran normally (expected)
SplFileInfo... exception (expected)
DirectoryIterator... exception (expected)
DirectoryIterator (exception cleared)... exception (expected)
FileSystemIterator... exception (expected)
RecursiveDirectoryIterator... exception (expected)
RecursiveTreeIterator... exception (expected)
AppendIterator... exception (expected)
InfiniteIterator... exception (expected)
CallbackFilterIterator... exception (expected)
RecursiveCallbackFilterIterator... exception (expected)