Check parameters on compact() and throw warning if not string or array of strings (#6921)

compact() is documented (https://www.php.net/manual/en/function.compact) as a variadic function accepting parameters which are strings or arrays of strings referencing defined symbols.

In actuality, passing nonsense parameters e.g. compact(true, 42) merely returns an empty array. I propose throwing a warning in these cases, to prevent silent bugs.
This commit is contained in:
dwgebler 2021-05-11 08:36:12 +01:00 committed by GitHub
parent 32aff25ceb
commit f5139878f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 13 deletions

View file

@ -2447,7 +2447,7 @@ PHP_FUNCTION(extract)
} }
/* }}} */ /* }}} */
static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_value, zval *entry) /* {{{ */ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_value, zval *entry, uint32_t pos) /* {{{ */
{ {
zval *value_ptr, data; zval *value_ptr, data;
@ -2475,11 +2475,14 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu
Z_PROTECT_RECURSION_P(entry); Z_PROTECT_RECURSION_P(entry);
} }
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(entry), value_ptr) { ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(entry), value_ptr) {
php_compact_var(eg_active_symbol_table, return_value, value_ptr); php_compact_var(eg_active_symbol_table, return_value, value_ptr, pos);
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
if (Z_REFCOUNTED_P(entry)) { if (Z_REFCOUNTED_P(entry)) {
Z_UNPROTECT_RECURSION_P(entry); Z_UNPROTECT_RECURSION_P(entry);
} }
} else {
php_error_docref(NULL, E_WARNING, "Argument #%d must be string or array of strings, %s given", pos, zend_zval_type_name(entry));
return;
} }
} }
/* }}} */ /* }}} */
@ -2512,7 +2515,7 @@ PHP_FUNCTION(compact)
} }
for (i = 0; i < num_args; i++) { for (i = 0; i < num_args; i++) {
php_compact_var(symbol_table, return_value, &args[i]); php_compact_var(symbol_table, return_value, &args[i], i + 1);
} }
} }
/* }}} */ /* }}} */

View file

@ -11,6 +11,13 @@ $location_vars = array("c\\u0327ity", "state");
$result = compact("event", $location_vars); $result = compact("event", $location_vars);
var_dump($result); var_dump($result);
$result = compact(true);
$foo = 'bar';
$bar = 'baz';
$result = compact($foo, [42]);
var_dump($result);
?> ?>
--EXPECTF-- --EXPECTF--
Warning: compact(): Undefined variable $c\u0327ity in %s on line %d Warning: compact(): Undefined variable $c\u0327ity in %s on line %d
@ -20,3 +27,11 @@ array(2) {
["state"]=> ["state"]=>
string(2) "CA" string(2) "CA"
} }
Warning: compact(): Argument #1 must be string or array of strings, bool given in %s on line %d
Warning: compact(): Argument #2 must be string or array of strings, int given in %s on line %d
array(1) {
["bar"]=>
string(3) "baz"
}

View file

@ -19,12 +19,8 @@ $f="string";
var_dump (compact(array("a", "b", "c", "d", "e", "f"))); var_dump (compact(array("a", "b", "c", "d", "e", "f")));
// simple parameter test // simple parameter test
var_dump (compact("a", "b", "c", "d", "e", "f")); var_dump (compact("a", "b", "c", "d", "e", "f"));
var_dump (compact(array("keyval"=>"a", "b"=>"b", "c"=>1))); var_dump (compact(array("keyval"=>"a", "b"=>"b")));
var_dump(compact(array("g")));
// cases which should not yield any output.
var_dump (compact(array(10, 0.3, true, array(20), NULL)));
var_dump (compact(10, 0.3, true, array(20), NULL));
var_dump (compact(array("g")));
echo "Done"; echo "Done";
?> ?>
@ -70,10 +66,6 @@ array(2) {
["b"]=> ["b"]=>
float(0.2) float(0.2)
} }
array(0) {
}
array(0) {
}
Warning: compact(): Undefined variable $g in %s on line %d Warning: compact(): Undefined variable $g in %s on line %d
array(0) { array(0) {