summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-04-29 10:35:44 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-05-11 14:16:24 +0200
commit091d53c1310c78a47edcc7eaef5b7b005b3856ab (patch)
tree1bb7abe2830962f2bd67b92fa5ea440c3fe7b9ae
parentb111674383fb638830193da672908a3abd5afe4e (diff)
downloadphp-git-091d53c1310c78a47edcc7eaef5b7b005b3856ab.tar.gz
Use standard key behavior in array_column()
array_column() reimplements array key handling in a way that does not match standard array key behavior in PHP. Avoid this by making use of the standard API. Of course, there is a minor backwards compatibilty break here, e.g. people could be relying on objects getting cast to string instead of throwing. Closes GH-5487.
-rw-r--r--ext/standard/array.c41
-rw-r--r--ext/standard/tests/array/array_column_object_cast.phpt18
-rw-r--r--ext/standard/tests/array/bug68553.phpt15
3 files changed, 23 insertions, 51 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 3e54946cd0..fd0ceaa600 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -4174,48 +4174,11 @@ PHP_FUNCTION(array_column)
continue;
}
- /* Failure will leave keyval alone which will land us on the final else block below
- * which is to append the value as next_index
- */
zval rv;
zval *keyval = array_column_fetch_prop(data, index_str, index_long, &rv);
-
if (keyval) {
- switch (Z_TYPE_P(keyval)) {
- case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(keyval), colval);
- break;
- case IS_LONG:
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(keyval), colval);
- break;
- case IS_OBJECT:
- {
- zend_string *tmp_key;
- zend_string *key = zval_get_tmp_string(keyval, &tmp_key);
- zend_symtable_update(Z_ARRVAL_P(return_value), key, colval);
- zend_tmp_string_release(tmp_key);
- break;
- }
- case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(return_value), ZSTR_EMPTY_ALLOC(), colval);
- break;
- case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(return_value),
- zend_dval_to_lval(Z_DVAL_P(keyval)), colval);
- break;
- case IS_TRUE:
- zend_hash_index_update(Z_ARRVAL_P(return_value), 1, colval);
- break;
- case IS_FALSE:
- zend_hash_index_update(Z_ARRVAL_P(return_value), 0, colval);
- break;
- case IS_RESOURCE:
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_RES_HANDLE_P(keyval), colval);
- break;
- default:
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);
- break;
- }
+ array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval);
+ zval_ptr_dtor(colval);
zval_ptr_dtor(keyval);
} else {
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);
diff --git a/ext/standard/tests/array/array_column_object_cast.phpt b/ext/standard/tests/array/array_column_object_cast.phpt
index 762aaa81f4..5e80b1da59 100644
--- a/ext/standard/tests/array/array_column_object_cast.phpt
+++ b/ext/standard/tests/array/array_column_object_cast.phpt
@@ -10,20 +10,15 @@ class IndexKeyClass {
function __toString() { return 'id'; }
}
-class ValueClass {
- function __toString() { return '2135'; }
-}
-
$column_key = new ColumnKeyClass();
$index_key = new IndexKeyClass();
-$value = new ValueClass();
// Array representing a possible record set returned from a database
$records = array(
array(
- 'id' => $value,
+ 'id' => 2135,
'first_name' => 'John',
'last_name' => 'XXX'
),
@@ -37,16 +32,15 @@ $firstNames = array_column($records, $column_key, $index_key);
print_r($firstNames);
var_dump($column_key);
var_dump($index_key);
-var_dump($value);
---EXPECTF--
+
+?>
+--EXPECT--
Array
(
[2135] => John
[3245] => Sally
)
-object(ColumnKeyClass)#%d (0) {
-}
-object(IndexKeyClass)#%d (0) {
+object(ColumnKeyClass)#1 (0) {
}
-object(ValueClass)#%d (0) {
+object(IndexKeyClass)#2 (0) {
}
diff --git a/ext/standard/tests/array/bug68553.phpt b/ext/standard/tests/array/bug68553.phpt
index 966c98b544..1d8f7f1b0b 100644
--- a/ext/standard/tests/array/bug68553.phpt
+++ b/ext/standard/tests/array/bug68553.phpt
@@ -21,7 +21,20 @@ $a = [
];
var_dump(array_column($a, null, 'a'));
+
+try {
+ var_dump(array_column([['a' => new stdClass]], null, 'a'));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(array_column([['a' => []]], null, 'a'));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+?>
--EXPECTF--
+Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
array(8) {
[10]=>
array(1) {
@@ -64,3 +77,5 @@ array(8) {
NULL
}
}
+Illegal offset type
+Illegal offset type