Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -5048,6 +5048,18 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa
}
}

/* Later operands may only be checked when no data comparison is performed. */
if (data_compare_type == INTERSECT_COMP_DATA_NONE) {
for (i = 0; i < argc; i++) {
if (zend_hash_num_elements(Z_ARRVAL(args[i])) == 0) {
RETURN_EMPTY_ARRAY();
}
}
} else if (zend_hash_num_elements(Z_ARRVAL(args[0])) == 0 ||
(argc > 1 && zend_hash_num_elements(Z_ARRVAL(args[1])) == 0)) {
RETURN_EMPTY_ARRAY();
}

array_init(return_value);

/* Iterate over keys of the first array, to compute keys that are in all of the other arrays. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
--TEST--
array_intersect_assoc() with empty operands
--FILE--
<?php

echo "Safe empty operands:\n";
var_dump(array_intersect_assoc([], ['k' => []], ['k' => []]));
var_dump(array_intersect_assoc(['k' => []], [], ['k' => []]));

echo "Single operand:\n";
var_dump(array_intersect_assoc(['k' => 1]));
var_dump(array_intersect_assoc([]));

echo "Warnings before third empty operand:\n";
$warnings = [];
set_error_handler(static function (int $severity, string $message) use (&$warnings): bool {
if ($severity === E_WARNING) {
$warnings[] = $message;
return true;
}
return false;
});
$result = array_intersect_assoc(['k' => []], ['k' => []], []);
restore_error_handler();
var_dump($result);
var_dump($warnings);

echo "Warning converted to exception:\n";
set_error_handler(static function (int $severity, string $message): never {
throw new ErrorException($message, 0, $severity);
});
try {
array_intersect_assoc(['k' => []], ['k' => []], []);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
} finally {
restore_error_handler();
}

echo "Invalid argument after empty operand:\n";
try {
array_intersect_assoc(['k' => 1], [], 42);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

?>
--EXPECT--
Safe empty operands:
array(0) {
}
array(0) {
}
Single operand:
array(1) {
["k"]=>
int(1)
}
array(0) {
}
Warnings before third empty operand:
array(0) {
}
array(2) {
[0]=>
string(26) "Array to string conversion"
[1]=>
string(26) "Array to string conversion"
}
Warning converted to exception:
ErrorException: Array to string conversion
Invalid argument after empty operand:
array_intersect_assoc(): Argument #3 must be of type array, int given
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
--TEST--
array_intersect_key() with empty operands
--FILE--
<?php

echo "Empty operands:\n";
var_dump(array_intersect_key([], ['a' => 1], ['a' => 1]));
var_dump(array_intersect_key(['a' => 1], [], ['a' => 1]));
var_dump(array_intersect_key(['a' => 1], ['a' => 1], []));

echo "Invalid argument after empty operand:\n";
try {
array_intersect_key(['a' => 1], [], 42);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

echo "Single argument:\n";
$single = [3 => 'three', 'a' => 'A', 1 => 'one'];
var_dump(array_intersect_key($single) === $single);

echo "Result order:\n";
$result = array_intersect_key($single, [1 => null, 3 => null, 'a' => null]);
var_dump(array_keys($result));

echo "Append to empty result:\n";
$result = array_intersect_key([9 => 'nine'], []);
$result[] = 'appended';
var_dump(array_keys($result));

echo "Single argument with stale next free index:\n";
$single = [2 => 'two', 100 => 'removed'];
unset($single[100]);
$result = array_intersect_key($single);
$result[] = 'appended';
var_dump(array_keys($result));

?>
--EXPECT--
Empty operands:
array(0) {
}
array(0) {
}
array(0) {
}
Invalid argument after empty operand:
array_intersect_key(): Argument #3 must be of type array, int given
Single argument:
bool(true)
Result order:
array(3) {
[0]=>
int(3)
[1]=>
string(1) "a"
[2]=>
int(1)
}
Append to empty result:
array(1) {
[0]=>
int(0)
}
Single argument with stale next free index:
array(2) {
[0]=>
int(2)
[1]=>
int(3)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--TEST--
array_uintersect_assoc() with empty operands
--FILE--
<?php

$callbackCount = 0;
$compare = static function (mixed $left, mixed $right) use (&$callbackCount): int {
$callbackCount++;
return $left <=> $right;
};

echo "Single operand:\n";
var_dump(array_uintersect_assoc(['k' => 1], $compare));
var_dump($callbackCount);
var_dump(array_uintersect_assoc([], $compare));
var_dump($callbackCount);

echo "Second empty operand:\n";
$result = array_uintersect_assoc(['k' => 1], [], ['k' => 1], $compare);
var_dump($result);
var_dump($callbackCount);

echo "Third empty operand:\n";
$callbackCount = 0;
$result = array_uintersect_assoc(['k' => 1], ['k' => 1], [], $compare);
var_dump($result);
var_dump($callbackCount);

echo "Invalid callback with empty operands:\n";
try {
array_uintersect_assoc([], [], '__missing_array_intersect_callback__');
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

echo "Invalid argument after empty operand:\n";
try {
array_uintersect_assoc(['k' => 1], [], 42, $compare);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

?>
--EXPECT--
Single operand:
array(1) {
["k"]=>
int(1)
}
int(0)
array(0) {
}
int(0)
Second empty operand:
array(0) {
}
int(0)
Third empty operand:
array(0) {
}
int(1)
Invalid callback with empty operands:
array_uintersect_assoc(): Argument #3 must be a valid callback, function "__missing_array_intersect_callback__" not found or invalid function name
Invalid argument after empty operand:
array_uintersect_assoc(): Argument #3 must be of type array, int given
Loading