summaryrefslogtreecommitdiff
path: root/ext/spl/spl_iterators.c
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2015-04-02 18:52:32 +0200
committerNikita Popov <nikic@php.net>2015-04-06 11:27:34 +0200
commit122d759618a42bff105971b923fbbb5be02e34b9 (patch)
treefd4487414ffa3f120c77b19b9eb7dc409659c57e /ext/spl/spl_iterators.c
parent884b0365dbe718f667d048dbc3d1cd9d9f12ab84 (diff)
downloadphp-git-122d759618a42bff105971b923fbbb5be02e34b9.tar.gz
Always throw TypeException on throwing zpp failures
Introduces a ZEND_PARSE_PARAMS_THROW flag for zpp, which forces to report FAILURE errors using a TypeException instead of a Warning, like it would happen in strict mode. Adds a zend_parse_parameters_throw() convenience function, which invokes zpp with this flag. Converts all cases I could identify, where we currently have throwing zpp usage in constructors and replaces them with this API. Error handling is still replaced to EH_THROW in some cases to handle other, domain-specific errors in constructors.
Diffstat (limited to 'ext/spl/spl_iterators.c')
-rw-r--r--ext/spl/spl_iterators.c37
1 files changed, 13 insertions, 24 deletions
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 3ffb8f7bec..e2267cfdcd 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -1067,6 +1067,8 @@ static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object *objec
data = iterator->funcs->get_current_data(iterator);
+ /* Replace exception handling so the catchable fatal error that is thrown when a class
+ * without __toString is converted to string is converted into an exception. */
zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
if (data) {
RETVAL_ZVAL(data, 1, 0);
@@ -1459,25 +1461,20 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
return NULL;
}
- zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling);
-
intern->dit_type = dit_type;
switch (dit_type) {
case DIT_LimitIterator: {
intern->u.limit.offset = 0; /* start at beginning */
intern->u.limit.count = -1; /* get all */
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|ll", &zobject, ce_inner, &intern->u.limit.offset, &intern->u.limit.count) == FAILURE) {
- zend_restore_error_handling(&error_handling);
+ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|ll", &zobject, ce_inner, &intern->u.limit.offset, &intern->u.limit.count) == FAILURE) {
return NULL;
}
if (intern->u.limit.offset < 0) {
zend_throw_exception(spl_ce_OutOfRangeException, "Parameter offset must be >= 0", 0);
- zend_restore_error_handling(&error_handling);
return NULL;
}
if (intern->u.limit.count < 0 && intern->u.limit.count != -1) {
zend_throw_exception(spl_ce_OutOfRangeException, "Parameter count must either be -1 or a value greater than or equal 0", 0);
- zend_restore_error_handling(&error_handling);
return NULL;
}
break;
@@ -1485,13 +1482,11 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
case DIT_CachingIterator:
case DIT_RecursiveCachingIterator: {
zend_long flags = CIT_CALL_TOSTRING;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &zobject, ce_inner, &flags) == FAILURE) {
- zend_restore_error_handling(&error_handling);
+ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|l", &zobject, ce_inner, &flags) == FAILURE) {
return NULL;
}
if (spl_cit_check_flags(flags) != SUCCESS) {
zend_throw_exception(spl_ce_InvalidArgumentException, "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER", 0);
- zend_restore_error_handling(&error_handling);
return NULL;
}
intern->u.caching.flags |= flags & CIT_PUBLIC;
@@ -1502,8 +1497,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
zend_class_entry *ce_cast;
zend_string *class_name;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|S", &zobject, ce_inner, &class_name) == FAILURE) {
- zend_restore_error_handling(&error_handling);
+ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|S", &zobject, ce_inner, &class_name) == FAILURE) {
return NULL;
}
ce = Z_OBJCE_P(zobject);
@@ -1514,7 +1508,6 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
|| !ce_cast->get_iterator
) {
zend_throw_exception(spl_ce_LogicException, "Class to downcast to not found or not base class or does not implement Traversable", 0);
- zend_restore_error_handling(&error_handling);
return NULL;
}
ce = ce_cast;
@@ -1523,12 +1516,10 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
zend_call_method_with_0_params(zobject, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval);
if (EG(exception)) {
zval_ptr_dtor(&retval);
- zend_restore_error_handling(&error_handling);
return NULL;
}
if (Z_TYPE(retval) != IS_OBJECT || !instanceof_function(Z_OBJCE(retval), zend_ce_traversable)) {
zend_throw_exception_ex(spl_ce_LogicException, 0, "%s::getIterator() must return an object that implements Traversable", ce->name->val);
- zend_restore_error_handling(&error_handling);
return NULL;
}
zobject = &retval;
@@ -1539,6 +1530,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
break;
}
case DIT_AppendIterator:
+ zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling);
spl_instantiate(spl_ce_ArrayIterator, &intern->u.append.zarrayit);
zend_call_method_with_0_params(&intern->u.append.zarrayit, spl_ce_ArrayIterator, &spl_ce_ArrayIterator->constructor, "__construct", NULL);
intern->u.append.iterator = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, &intern->u.append.zarrayit, 0);
@@ -1553,21 +1545,22 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
intern->u.regex.use_flags = ZEND_NUM_ARGS() >= 5;
intern->u.regex.flags = 0;
intern->u.regex.preg_flags = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|lll", &zobject, ce_inner, &regex, &mode, &intern->u.regex.flags, &intern->u.regex.preg_flags) == FAILURE) {
- zend_restore_error_handling(&error_handling);
+ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "OS|lll", &zobject, ce_inner, &regex, &mode, &intern->u.regex.flags, &intern->u.regex.preg_flags) == FAILURE) {
return NULL;
}
if (mode < 0 || mode >= REGIT_MODE_MAX) {
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Illegal mode %pd", mode);
- zend_restore_error_handling(&error_handling);
return NULL;
}
intern->u.regex.mode = mode;
intern->u.regex.regex = zend_string_copy(regex);
+
+ zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling);
intern->u.regex.pce = pcre_get_compiled_regex_cache(regex);
+ zend_restore_error_handling(&error_handling);
+
if (intern->u.regex.pce == NULL) {
/* pcre_get_compiled_regex_cache has already sent error */
- zend_restore_error_handling(&error_handling);
return NULL;
}
intern->u.regex.pce->refcount++;
@@ -1578,8 +1571,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
case DIT_RecursiveCallbackFilterIterator: {
_spl_cbfilter_it_intern *cfi = emalloc(sizeof(*cfi));
cfi->fci.object = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "Of", &zobject, ce_inner, &cfi->fci, &cfi->fcc) == FAILURE) {
- zend_restore_error_handling(&error_handling);
+ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "Of", &zobject, ce_inner, &cfi->fci, &cfi->fcc) == FAILURE) {
efree(cfi);
return NULL;
}
@@ -1592,15 +1584,12 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
break;
}
default:
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zobject, ce_inner) == FAILURE) {
- zend_restore_error_handling(&error_handling);
+ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O", &zobject, ce_inner) == FAILURE) {
return NULL;
}
break;
}
- zend_restore_error_handling(&error_handling);
-
if (inc_refcount) {
ZVAL_COPY(&intern->inner.zobject, zobject);
} else {