summaryrefslogtreecommitdiff
path: root/ext/spl
diff options
context:
space:
mode:
Diffstat (limited to 'ext/spl')
-rw-r--r--ext/spl/spl_array.c13
-rw-r--r--ext/spl/spl_directory.c2
-rw-r--r--ext/spl/spl_iterators.c2
-rw-r--r--ext/spl/spl_observer.c2
-rw-r--r--ext/spl/tests/SplObjectStorage_unserialize_bad.phpt5
-rw-r--r--ext/spl/tests/bug66127.phpt25
-rw-r--r--ext/spl/tests/bug67359.phpt28
-rw-r--r--ext/spl/tests/bug67360.phpt34
-rw-r--r--ext/spl/tests/iterator_035.phpt2
9 files changed, 108 insertions, 5 deletions
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index f41d0fb9c..8392e7271 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -402,7 +402,7 @@ static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval
/* When in a write context,
* ZE has to be fooled into thinking this is in a reference set
* by separating (if necessary) and returning as an is_ref=1 zval (even if refcount == 1) */
- if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && !Z_ISREF_PP(ret)) {
+ if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && !Z_ISREF_PP(ret) && ret != &EG(uninitialized_zval_ptr)) {
if (Z_REFCOUNT_PP(ret) > 1) {
zval *newval;
@@ -922,7 +922,14 @@ static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSR
if (Z_TYPE_P(intern->array) == IS_OBJECT) {
do {
if (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 0, &intern->pos) == HASH_KEY_IS_STRING) {
- if (!string_length || string_key[0]) {
+ /* zend_hash_get_current_key_ex() should never set
+ * string_length to 0 when returning HASH_KEY_IS_STRING, but we
+ * may as well be defensive and consider that successful.
+ * Beyond that, we're looking for protected keys (which will
+ * have a null byte at string_key[0]), but want to avoid
+ * skipping completely empty keys (which will also have the
+ * null byte, but a string_length of 1). */
+ if (!string_length || string_key[0] || string_length == 1) {
return SUCCESS;
}
} else {
@@ -1789,7 +1796,7 @@ SPL_METHOD(Array, unserialize)
++p;
ALLOC_INIT_ZVAL(pmembers);
- if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC)) {
+ if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pmembers) != IS_ARRAY) {
zval_ptr_dtor(&pmembers);
goto outexcept;
}
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index 3fbf2ce12..b6109ddf3 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -829,6 +829,7 @@ SPL_METHOD(DirectoryIterator, seek)
zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.dir.func_rewind, "rewind", &retval);
if (retval) {
zval_ptr_dtor(&retval);
+ retval = NULL;
}
}
@@ -838,6 +839,7 @@ SPL_METHOD(DirectoryIterator, seek)
if (retval) {
valid = zend_is_true(retval);
zval_ptr_dtor(&retval);
+ retval = NULL;
}
if (!valid) {
break;
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 047b47f26..7c20352e9 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -848,6 +848,8 @@ static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, char
*object_ptr = zobj;
function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len, key TSRMLS_CC);
}
+ } else {
+ *object_ptr = zobj;
}
}
return function_handler;
diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c
index 1a706f764..da9110bf1 100644
--- a/ext/spl/spl_observer.c
+++ b/ext/spl/spl_observer.c
@@ -898,7 +898,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
++p;
ALLOC_INIT_ZVAL(pmembers);
- if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC)) {
+ if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pmembers) != IS_ARRAY) {
zval_ptr_dtor(&pmembers);
goto outexcept;
}
diff --git a/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt b/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
index a52531709..8f0676de3 100644
--- a/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
+++ b/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
@@ -7,6 +7,7 @@ $badblobs = array(
'x:i:2;i:0;,i:1;;i:0;,i:2;;m:a:0:{}',
'x:i:3;O:8:"stdClass":0:{},O:8:"stdClass":0:{};R:2;,i:1;;O:8:"stdClass":0:{},r:2;;m:a:0:{}',
'x:i:3;O:8:"stdClass":0:{},O:8:"stdClass":0:{};r:2;,i:1;;O:8:"stdClass":0:{},r:2;;m:a:0:{}',
+'x:i:1;O:8:"stdClass":0:{},N;;m:s:40:"1234567890123456789012345678901234567890"',
);
foreach($badblobs as $blob) {
try {
@@ -17,6 +18,7 @@ try {
echo $e->getMessage()."\n";
}
}
+echo "DONE\n";
--EXPECTF--
Error at offset 6 of 34 bytes
Error at offset 46 of 89 bytes
@@ -42,4 +44,5 @@ object(SplObjectStorage)#2 (1) {
}
}
}
-
+Error at offset 79 of 78 bytes
+DONE
diff --git a/ext/spl/tests/bug66127.phpt b/ext/spl/tests/bug66127.phpt
new file mode 100644
index 000000000..b5d1dcac4
--- /dev/null
+++ b/ext/spl/tests/bug66127.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #66127 (Segmentation fault with ArrayObject unset)
+--INI--
+error_reporting = E_ALL & ~E_NOTICE
+--FILE--
+<?php
+function crash()
+{
+ set_error_handler(function () {});
+ $var = 1;
+ trigger_error('error');
+ $var2 = $var;
+ $var3 = $var;
+ trigger_error('error');
+}
+
+$items = new ArrayObject();
+
+unset($items[0]);
+unset($items[0][0]);
+crash();
+echo "Worked!\n";
+?>
+--EXPECT--
+Worked!
diff --git a/ext/spl/tests/bug67359.phpt b/ext/spl/tests/bug67359.phpt
new file mode 100644
index 000000000..e2e61133f
--- /dev/null
+++ b/ext/spl/tests/bug67359.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #67359 (Segfault in recursiveDirectoryIterator)
+--FILE--
+<?php
+try
+{
+ $rdi = new recursiveDirectoryIterator(dirname(__FILE__), FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS);
+ $it = new recursiveIteratorIterator( $rdi );
+ $it->seek(1);
+ while( $it->valid())
+ {
+ if( $it->isFile() )
+ {
+ $it->current();
+ }
+
+ $it->next();
+ }
+
+ $it->current();
+}
+catch(Exception $e)
+{
+}
+echo "okey"
+?>
+--EXPECTF--
+okey
diff --git a/ext/spl/tests/bug67360.phpt b/ext/spl/tests/bug67360.phpt
new file mode 100644
index 000000000..552c02ad7
--- /dev/null
+++ b/ext/spl/tests/bug67360.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #67360 (Missing element after ArrayObject::getIterator)
+--FILE--
+<?php
+
+$array = array('' => 1, 1 => 2, 3 => 4);
+$ArrayObject = new ArrayObject($array);
+var_dump($ArrayObject);
+$Iterator = $ArrayObject->getIterator();
+var_dump(count($Iterator) === count($array));
+var_dump(iterator_to_array($Iterator));
+
+?>
+--EXPECTF--
+object(ArrayObject)#%d (1) {
+ ["storage":"ArrayObject":private]=>
+ array(3) {
+ [""]=>
+ int(1)
+ [1]=>
+ int(2)
+ [3]=>
+ int(4)
+ }
+}
+bool(true)
+array(3) {
+ [""]=>
+ int(1)
+ [1]=>
+ int(2)
+ [3]=>
+ int(4)
+}
diff --git a/ext/spl/tests/iterator_035.phpt b/ext/spl/tests/iterator_035.phpt
index 9ce098b69..fc0271e38 100644
--- a/ext/spl/tests/iterator_035.phpt
+++ b/ext/spl/tests/iterator_035.phpt
@@ -12,4 +12,6 @@ $a[] = &$tmp;
echo "Done\n";
?>
--EXPECTF--
+Notice: Indirect modification of overloaded element of ArrayIterator has no effect in %s on line %d
+
Fatal error: Cannot assign by reference to overloaded object in %s on line %d