diff options
Diffstat (limited to 'ext/spl')
-rw-r--r-- | ext/spl/spl_array.c | 92 | ||||
-rw-r--r-- | ext/spl/spl_iterators.c | 3 | ||||
-rw-r--r-- | ext/spl/tests/bug66702.phpt | 40 | ||||
-rw-r--r-- | ext/spl/tests/bug66834.phpt | 163 |
4 files changed, 259 insertions, 39 deletions
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index f41d0fb9cd..0611cfe38f 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -593,64 +593,80 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o { spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); long index; - zval *rv, **tmp; + zval *rv, *value = NULL, **tmp; if (check_inherited && intern->fptr_offset_has) { - SEPARATE_ARG_IF_REF(offset); - zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_has, "offsetExists", &rv, offset); - zval_ptr_dtor(&offset); + zval *offset_tmp = offset; + SEPARATE_ARG_IF_REF(offset_tmp); + zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_has, "offsetExists", &rv, offset_tmp); + zval_ptr_dtor(&offset_tmp); + if (rv && zend_is_true(rv)) { zval_ptr_dtor(&rv); - return 1; - } - if (rv) { - zval_ptr_dtor(&rv); + if (check_empty == 2) { + return 1; + } else if (intern->fptr_offset_get) { + value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R TSRMLS_CC); + } + } else { + if (rv) { + zval_ptr_dtor(&rv); + } + return 0; } - return 0; } - switch(Z_TYPE_P(offset)) { - case IS_STRING: - { - HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + if (!value) { + HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + + switch(Z_TYPE_P(offset)) { + case IS_STRING: if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &tmp) != FAILURE) { - switch (check_empty) { - case 0: - return Z_TYPE_PP(tmp) != IS_NULL; - case 2: - return 1; - default: - return zend_is_true(*tmp); + if (check_empty == 2) { + return 1; } + } else { + return 0; } - } - return 0; - case IS_DOUBLE: - case IS_RESOURCE: - case IS_BOOL: - case IS_LONG: - { - HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + break; + case IS_DOUBLE: + case IS_RESOURCE: + case IS_BOOL: + case IS_LONG: if (offset->type == IS_DOUBLE) { index = (long)Z_DVAL_P(offset); } else { index = Z_LVAL_P(offset); } if (zend_hash_index_find(ht, index, (void **)&tmp) != FAILURE) { - switch (check_empty) { - case 0: - return Z_TYPE_PP(tmp) != IS_NULL; - case 2: - return 1; - default: - return zend_is_true(*tmp); + if (check_empty == 2) { + return 1; } + } else { + return 0; } + break; + default: + zend_error(E_WARNING, "Illegal offset type"); return 0; - } - default: - zend_error(E_WARNING, "Illegal offset type"); + } + + if (check_inherited && intern->fptr_offset_get) { + value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R TSRMLS_CC); + } else { + value = *tmp; + } + } + + switch (check_empty) { + case 0: + return Z_TYPE_P(value) != IS_NULL; + case 2: + return 1; + case 1: + return zend_is_true(value); } + return 0; } /* }}} */ diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index a89fd548c5..679fc85af1 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -2055,7 +2055,7 @@ SPL_METHOD(RegexIterator, accept) } if (intern->u.regex.flags & REGIT_INVERTED) { - RETVAL_BOOL(Z_LVAL_P(return_value)); + RETVAL_BOOL(! Z_LVAL_P(return_value)); } if (use_copy) { @@ -3692,6 +3692,7 @@ PHP_MINIT_FUNCTION(spl_iterators) #if HAVE_PCRE || HAVE_BUNDLED_PCRE REGISTER_SPL_SUB_CLASS_EX(RegexIterator, FilterIterator, spl_dual_it_new, spl_funcs_RegexIterator); REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "USE_KEY", REGIT_USE_KEY); + REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "INVERT_MATCH",REGIT_INVERTED); REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "MATCH", REGIT_MODE_MATCH); REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "GET_MATCH", REGIT_MODE_GET_MATCH); REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "ALL_MATCHES", REGIT_MODE_ALL_MATCHES); diff --git a/ext/spl/tests/bug66702.phpt b/ext/spl/tests/bug66702.phpt new file mode 100644 index 0000000000..fedfc869a8 --- /dev/null +++ b/ext/spl/tests/bug66702.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #66702 (RegexIterator inverted result works as expected) +--FILE-- +<?php +/** + * @author Joshua Thijssen <jthijssen+php@noxlogic.nl> + */ + +$it = new \ArrayIterator(array("foo", "bar", "baz")); +$it2 = new \RegexIterator($it, "/^ba/", \RegexIterator::MATCH); +print_r(iterator_to_array($it2)); +$it2 = new \RegexIterator($it, "/^ba/", \RegexIterator::MATCH, \RegexIterator::INVERT_MATCH); +print_r(iterator_to_array($it2)); + +$it = new \ArrayIterator(array("foo" => 1, "bar" => 2, "baz" => 3)); +$it2 = new \RegexIterator($it, "/^ba/", \RegexIterator::MATCH, \RegexIterator::USE_KEY); +print_r(iterator_to_array($it2)); +$it2 = new \RegexIterator($it, "/^ba/", \RegexIterator::MATCH, \RegexIterator::USE_KEY | \RegexIterator::INVERT_MATCH); +print_r(iterator_to_array($it2)); + +--EXPECTF-- +Array +( + [1] => bar + [2] => baz +) +Array +( + [0] => foo +) +Array +( + [bar] => 2 + [baz] => 3 +) +Array +( + [foo] => 1 +) + diff --git a/ext/spl/tests/bug66834.phpt b/ext/spl/tests/bug66834.phpt new file mode 100644 index 0000000000..6d944b274a --- /dev/null +++ b/ext/spl/tests/bug66834.phpt @@ -0,0 +1,163 @@ +--TEST-- +SPL: Bug #66834 +--FILE-- +<?php + +// overrides both offsetExists and offsetGet +class ArrayObjectBoth extends ArrayObject +{ + public function offsetExists($offset) { + var_dump('Called: '.__METHOD__); + return parent::offsetExists($offset); + } + + public function offsetGet($offset) { + var_dump('Called: '.__METHOD__); + return parent::offsetGet($offset); + } +} + +// overrides only offsetExists +class ArrayObjectExists extends ArrayObject +{ + public function offsetExists($offset) { + var_dump('Called: '.__METHOD__); + return parent::offsetExists($offset); + } +} + +// overrides only offsetGet +class ArrayObjectGet extends ArrayObject +{ + public function offsetGet($offset) { + var_dump('Called: '.__METHOD__); + return parent::offsetGet($offset); + } +} + +// overrides only offsetGet and offsetSet +class ArrayObjectGetSet extends ArrayObject +{ + public function offsetGet($offset) + { + return parent::offsetGet(str_rot13($offset)); + } + + public function offsetSet($offset, $value) + { + return parent::offsetSet(str_rot13($offset), $value); + } +} + +$values = ['foo' => '', 'bar' => null, 'baz' => 42]; + +echo "==== class with offsetExists() and offsetGet() ====\n"; +$object = new ArrayObjectBoth($values); +var_dump($object->offsetExists('foo'), isset($object['foo']), empty($object['foo'])); +var_dump($object->offsetExists('bar'), isset($object['bar']), empty($object['bar'])); +var_dump($object->offsetexists('baz'), isset($object['baz']), empty($object['baz'])); +var_dump($object->offsetexists('qux'), isset($object['qux']), empty($object['qux'])); + +echo "==== class with offsetExists() ====\n"; +$object = new ArrayObjectExists($values); +var_dump($object->offsetExists('foo'), isset($object['foo']), empty($object['foo'])); +var_dump($object->offsetExists('bar'), isset($object['bar']), empty($object['bar'])); +var_dump($object->offsetexists('baz'), isset($object['baz']), empty($object['baz'])); +var_dump($object->offsetexists('qux'), isset($object['qux']), empty($object['qux'])); + +echo "==== class with offsetGet() ====\n"; +$object = new ArrayObjectGet($values); +var_dump($object->offsetExists('foo'), isset($object['foo']), empty($object['foo'])); +var_dump($object->offsetExists('bar'), isset($object['bar']), empty($object['bar'])); +var_dump($object->offsetexists('baz'), isset($object['baz']), empty($object['baz'])); +var_dump($object->offsetexists('qux'), isset($object['qux']), empty($object['qux'])); + +echo "==== class with offsetGet() and offsetSet() ====\n"; +$object = new ArrayObjectGetSet; +$object['foo'] = 42; +var_dump($object->offsetExists('foo'), $object->offsetExists('sbb'), isset($object['foo']), isset($object['sbb'])); + +?> +--EXPECTF-- +==== class with offsetExists() and offsetGet() ==== +string(37) "Called: ArrayObjectBoth::offsetExists" +string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" +string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" +bool(true) +bool(true) +bool(true) +string(37) "Called: ArrayObjectBoth::offsetExists" +string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" +string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" +bool(true) +bool(false) +bool(true) +string(37) "Called: ArrayObjectBoth::offsetExists" +string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" +string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" +bool(true) +bool(true) +bool(false) +string(37) "Called: ArrayObjectBoth::offsetExists" +string(37) "Called: ArrayObjectBoth::offsetExists" +string(37) "Called: ArrayObjectBoth::offsetExists" +bool(false) +bool(false) +bool(true) +==== class with offsetExists() ==== +string(39) "Called: ArrayObjectExists::offsetExists" +string(39) "Called: ArrayObjectExists::offsetExists" +string(39) "Called: ArrayObjectExists::offsetExists" +bool(true) +bool(true) +bool(true) +string(39) "Called: ArrayObjectExists::offsetExists" +string(39) "Called: ArrayObjectExists::offsetExists" +string(39) "Called: ArrayObjectExists::offsetExists" +bool(true) +bool(false) +bool(true) +string(39) "Called: ArrayObjectExists::offsetExists" +string(39) "Called: ArrayObjectExists::offsetExists" +string(39) "Called: ArrayObjectExists::offsetExists" +bool(true) +bool(true) +bool(false) +string(39) "Called: ArrayObjectExists::offsetExists" +string(39) "Called: ArrayObjectExists::offsetExists" +string(39) "Called: ArrayObjectExists::offsetExists" +bool(false) +bool(false) +bool(true) +==== class with offsetGet() ==== +string(33) "Called: ArrayObjectGet::offsetGet" +string(33) "Called: ArrayObjectGet::offsetGet" +bool(true) +bool(true) +bool(true) +string(33) "Called: ArrayObjectGet::offsetGet" +string(33) "Called: ArrayObjectGet::offsetGet" +bool(true) +bool(false) +bool(true) +string(33) "Called: ArrayObjectGet::offsetGet" +string(33) "Called: ArrayObjectGet::offsetGet" +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +bool(true) +==== class with offsetGet() and offsetSet() ==== + +Notice: Undefined index: foo in %s on line %d +bool(false) +bool(true) +bool(false) +bool(false) |