Skip to content

Commit 9b01f51

Browse files
committed
ext/pcntl: Reject negative values in pcntl_alarm()
internal refactorings: - pcntl_signal_get_handler() max signals handling simplification, reusing the num_signals global. - pcntl_alarm() accepts a zend_long (signed) but passes it to alarm(), which takes an unsigned int. Negative values silently wrap to large unsigned values, scheduling an alarm far in the future instead of raising an error. Also reject large values above unsigned long max value. close GH-21282
1 parent e045b88 commit 9b01f51

3 files changed

Lines changed: 48 additions & 13 deletions

File tree

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ PHP 8.6 UPGRADE NOTES
105105
. Output of openssl_x509_parse() contains criticalExtensions listing all
106106
critical certificate extensions.
107107

108+
- PCNTL:
109+
. pcntl_alarm() now throws a ValueError if the seconds argument is
110+
lower than zero or greater than platform's UINT_MAX.
111+
108112
- Phar:
109113
. Phar::mungServer() now supports reference values.
110114

ext/pcntl/pcntl.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ PHP_RINIT_FUNCTION(pcntl)
212212
PCNTL_G(last_error) = 0;
213213
PCNTL_G(num_signals) = NSIG;
214214
#ifdef SIGRTMAX
215-
/* At least FreeBSD reports an incorrecrt NSIG that does not include realtime signals.
215+
/* At least FreeBSD reports an incorrect NSIG that does not include realtime signals.
216216
* As SIGRTMAX may be a dynamic value, adjust the value in INIT. */
217217
if (NSIG < SIGRTMAX + 1) {
218218
PCNTL_G(num_signals) = SIGRTMAX + 1;
@@ -314,6 +314,11 @@ PHP_FUNCTION(pcntl_alarm)
314314
Z_PARAM_LONG(seconds);
315315
ZEND_PARSE_PARAMETERS_END();
316316

317+
if (seconds < 0 || seconds > UINT_MAX) {
318+
zend_argument_value_error(1, "must be between 0 and %u", UINT_MAX);
319+
RETURN_THROWS();
320+
}
321+
317322
RETURN_LONG((zend_long) alarm(seconds));
318323
}
319324
/* }}} */
@@ -870,17 +875,8 @@ PHP_FUNCTION(pcntl_signal_get_handler)
870875
Z_PARAM_LONG(signo)
871876
ZEND_PARSE_PARAMETERS_END();
872877

873-
// note: max signal on mac is SIGUSR2 (31), no real time signals.
874-
int sigmax = NSIG - 1;
875-
#if defined(SIGRTMAX)
876-
// oddily enough, NSIG on freebsd reports only 32 whereas SIGRTMIN starts at 65.
877-
if (sigmax < SIGRTMAX) {
878-
sigmax = SIGRTMAX;
879-
}
880-
#endif
881-
882-
if (signo < 1 || signo > sigmax) {
883-
zend_argument_value_error(1, "must be between 1 and %d", sigmax);
878+
if (signo < 1 || signo >= PCNTL_G(num_signals)) {
879+
zend_argument_value_error(1, "must be between 1 and %d", PCNTL_G(num_signals) - 1);
884880
RETURN_THROWS();
885881
}
886882

@@ -1153,7 +1149,7 @@ static void pcntl_siginfo_to_zval(int signo, siginfo_t *siginfo, zval *user_sigi
11531149
case SIGFPE:
11541150
case SIGSEGV:
11551151
case SIGBUS:
1156-
add_assoc_double_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo->si_addr);
1152+
add_assoc_long_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo->si_addr);
11571153
break;
11581154
#if defined(SIGPOLL) && !defined(__CYGWIN__)
11591155
case SIGPOLL:
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
pcntl_alarm() rejects invalid values
3+
--EXTENSIONS--
4+
pcntl
5+
--SKIPIF--
6+
<?php if (PHP_INT_SIZE < 8) die("skip 64-bit only"); ?>
7+
--FILE--
8+
<?php
9+
10+
try {
11+
pcntl_alarm(-1);
12+
} catch (\ValueError $e) {
13+
echo $e->getMessage() . \PHP_EOL;
14+
}
15+
16+
try {
17+
pcntl_alarm(PHP_INT_MIN);
18+
} catch (\ValueError $e) {
19+
echo $e->getMessage() . \PHP_EOL;
20+
}
21+
22+
try {
23+
pcntl_alarm(PHP_INT_MAX);
24+
} catch (\ValueError $e) {
25+
echo $e->getMessage() . \PHP_EOL;
26+
}
27+
28+
var_dump(pcntl_alarm(0));
29+
30+
?>
31+
--EXPECTF--
32+
pcntl_alarm(): Argument #1 ($seconds) must be between 0 and %d
33+
pcntl_alarm(): Argument #1 ($seconds) must be between 0 and %d
34+
pcntl_alarm(): Argument #1 ($seconds) must be between 0 and %d
35+
int(0)

0 commit comments

Comments
 (0)