Skip to content
Merged
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
9 changes: 9 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ PHP 8.6 UPGRADE NOTES
1. Backward Incompatible Changes
========================================

- PCRE:
. preg_grep() now returns false instead of a partial array when a PCRE
execution error occurs (e.g. malformed UTF-8 input with the /u modifier).
This is consistent with other preg_* functions.

- Phar:
. Invalid values now throw in Phar::mungServer() instead of being silently
ignored.
Expand Down Expand Up @@ -100,6 +105,10 @@ PHP 8.6 UPGRADE NOTES
. Output of openssl_x509_parse() contains criticalExtensions listing all
critical certificate extensions.

- PCNTL:
. pcntl_alarm() now throws a ValueError if the seconds argument is
lower than zero or greater than platform's UINT_MAX.

- Phar:
. Phar::mungServer() now supports reference values.

Expand Down
22 changes: 9 additions & 13 deletions ext/pcntl/pcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ PHP_RINIT_FUNCTION(pcntl)
PCNTL_G(last_error) = 0;
PCNTL_G(num_signals) = NSIG;
#ifdef SIGRTMAX
/* At least FreeBSD reports an incorrecrt NSIG that does not include realtime signals.
/* At least FreeBSD reports an incorrect NSIG that does not include realtime signals.
* As SIGRTMAX may be a dynamic value, adjust the value in INIT. */
if (NSIG < SIGRTMAX + 1) {
PCNTL_G(num_signals) = SIGRTMAX + 1;
Expand Down Expand Up @@ -314,6 +314,11 @@ PHP_FUNCTION(pcntl_alarm)
Z_PARAM_LONG(seconds);
ZEND_PARSE_PARAMETERS_END();

if (seconds < 0 || seconds > UINT_MAX) {
zend_argument_value_error(1, "must be between 0 and %u", UINT_MAX);
RETURN_THROWS();
}

RETURN_LONG((zend_long) alarm(seconds));
}
/* }}} */
Expand Down Expand Up @@ -870,17 +875,8 @@ PHP_FUNCTION(pcntl_signal_get_handler)
Z_PARAM_LONG(signo)
ZEND_PARSE_PARAMETERS_END();

// note: max signal on mac is SIGUSR2 (31), no real time signals.
int sigmax = NSIG - 1;
#if defined(SIGRTMAX)
// oddily enough, NSIG on freebsd reports only 32 whereas SIGRTMIN starts at 65.
if (sigmax < SIGRTMAX) {
sigmax = SIGRTMAX;
}
#endif

if (signo < 1 || signo > sigmax) {
zend_argument_value_error(1, "must be between 1 and %d", sigmax);
if (signo < 1 || signo >= PCNTL_G(num_signals)) {
zend_argument_value_error(1, "must be between 1 and %d", PCNTL_G(num_signals) - 1);
RETURN_THROWS();
}

Expand Down Expand Up @@ -1153,7 +1149,7 @@ static void pcntl_siginfo_to_zval(int signo, siginfo_t *siginfo, zval *user_sigi
case SIGFPE:
case SIGSEGV:
case SIGBUS:
add_assoc_double_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo->si_addr);
add_assoc_long_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo->si_addr);
break;
#if defined(SIGPOLL) && !defined(__CYGWIN__)
case SIGPOLL:
Expand Down
35 changes: 35 additions & 0 deletions ext/pcntl/tests/pcntl_alarm_invalid_value.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
pcntl_alarm() rejects invalid values
--EXTENSIONS--
pcntl
--SKIPIF--
<?php if (PHP_INT_SIZE < 8) die("skip 64-bit only"); ?>
--FILE--
<?php

try {
pcntl_alarm(-1);
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}

try {
pcntl_alarm(PHP_INT_MIN);
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}

try {
pcntl_alarm(PHP_INT_MAX);
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}

var_dump(pcntl_alarm(0));

?>
--EXPECTF--
pcntl_alarm(): Argument #1 ($seconds) must be between 0 and %d
pcntl_alarm(): Argument #1 ($seconds) must be between 0 and %d
pcntl_alarm(): Argument #1 ($seconds) must be between 0 and %d
int(0)
20 changes: 19 additions & 1 deletion ext/pcre/php_pcre.c
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, bo
if (key != regex) {
zend_string_release_ex(key, 0);
}
pcre2_code_free(new_entry.re);
php_error_docref(NULL, E_WARNING, "Internal pcre2_pattern_info() error %d", rc);
pcre_handle_exec_error(PCRE2_ERROR_INTERNAL);
return NULL;
Expand All @@ -841,6 +842,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, bo
if (key != regex) {
zend_string_release_ex(key, 0);
}
pcre2_code_free(new_entry.re);
php_error_docref(NULL, E_WARNING, "Internal pcre_pattern_info() error %d", rc);
pcre_handle_exec_error(PCRE2_ERROR_INTERNAL);
return NULL;
Expand Down Expand Up @@ -1286,7 +1288,18 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, zend_string *subject_str,
if (subpats != NULL) {
/* Try to get the list of substrings and display a warning if failed. */
if (UNEXPECTED(offsets[1] < offsets[0])) {
if (match_sets) efree(match_sets);
if (match_sets) {
for (i = 0; i < num_subpats; i++) {
zend_array_destroy(match_sets[i]);
}
efree(match_sets);
}
if (marks) {
zend_array_destroy(marks);
}
if (match_data != mdata) {
pcre2_match_data_free(match_data);
}
php_error_docref(NULL, E_WARNING, "Get subpatterns list failed");
RETURN_FALSE;
}
Expand Down Expand Up @@ -2987,6 +3000,11 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return
if (match_data != mdata) {
pcre2_match_data_free(match_data);
}

if (PCRE_G(error_code) != PHP_PCRE_NO_ERROR) {
zend_array_destroy(Z_ARR_P(return_value));
RETURN_FALSE;
}
}
/* }}} */

Expand Down
44 changes: 44 additions & 0 deletions ext/pcre/tests/preg_grep_error_utf8.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
--TEST--
preg_grep() returns false on match execution error (e.g. malformed UTF-8)
--FILE--
<?php
// preg_grep should return false when a match execution error occurs,
// consistent with preg_match behavior. See GH-11936.

// Test 1: preg_match returns false on malformed UTF-8 with /u modifier
var_dump(preg_match('/.*/u', hex2bin('ff')));
var_dump(preg_last_error() === PREG_BAD_UTF8_ERROR);

// Test 2: preg_grep should also return false (not an empty/partial array)
var_dump(preg_grep('/.*/u', [hex2bin('ff')]));
var_dump(preg_last_error() === PREG_BAD_UTF8_ERROR);

// Test 3: preg_grep with valid entries before the invalid one should
// return false, not a partial array
var_dump(preg_grep('/.*/u', ['foo', hex2bin('ff'), 'bar']));
var_dump(preg_last_error() === PREG_BAD_UTF8_ERROR);

// Test 4: preg_grep with PREG_GREP_INVERT should also return false on error
var_dump(preg_grep('/.*/u', [hex2bin('ff')], PREG_GREP_INVERT));
var_dump(preg_last_error() === PREG_BAD_UTF8_ERROR);

// Test 5: preg_grep without error still returns an array
var_dump(preg_grep('/.*/u', ['foo', 'bar']));
var_dump(preg_last_error() === PREG_NO_ERROR);
?>
--EXPECTF--
bool(false)
bool(true)
bool(false)
bool(true)
bool(false)
bool(true)
bool(false)
bool(true)
array(2) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
}
bool(true)
10 changes: 10 additions & 0 deletions ext/pcre/tests/preg_match_all_negative_length_match.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
preg_match_all() resource cleanup when \K in lookahead causes negative-length match
--FILE--
<?php
$result = preg_match_all('/(?=ab\K)a/', 'ab', $matches);
var_dump($result);
?>
--EXPECTF--
Warning: preg_match_all(): Compilation failed: \K is not allowed in lookarounds (but see PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) at offset %d in %s
bool(false)
10 changes: 10 additions & 0 deletions ext/pcre/tests/preg_match_negative_length_match.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
preg_match() resource cleanup when \K in lookahead causes negative-length match
--FILE--
<?php
$result = preg_match('/(?=ab\K)a/', 'ab', $matches);
var_dump($result);
?>
--EXPECTF--
Warning: preg_match(): Compilation failed: \K is not allowed in lookarounds (but see PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) at offset %d in %s
bool(false)
2 changes: 1 addition & 1 deletion run-tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ function write_information(array $user_tests, $phpdbg): void
$exts = get_loaded_extensions();
$ext_dir = ini_get('extension_dir');
foreach (scandir($ext_dir) as $file) {
if (preg_match('/^(?:php_)?([_a-zA-Z0-9]+)\.(?:so|dll)$/', $file, $matches)) {
if (preg_match('/^(?:php_)?([_a-zA-Z0-9]+)\.(?:' . PHP_SHLIB_SUFFIX . ')$/', $file, $matches)) {
if (!extension_loaded($matches[1])) {
$exts[] = $matches[1];
}
Expand Down