Merge branch 'PHP-8.4'

This commit is contained in:
David Carlier 2024-12-16 23:00:23 +00:00
commit 4750ce1e6d
No known key found for this signature in database
GPG key ID: 8486F847B4B94EF1
3 changed files with 118 additions and 18 deletions

View file

@ -1970,8 +1970,16 @@ PHP_FUNCTION(socket_set_option)
const char l_onoff_key[] = "l_onoff"; const char l_onoff_key[] = "l_onoff";
const char l_linger_key[] = "l_linger"; const char l_linger_key[] = "l_linger";
convert_to_array(arg4); if (Z_TYPE_P(arg4) != IS_ARRAY) {
if (UNEXPECTED(Z_TYPE_P(arg4) != IS_OBJECT)) {
zend_argument_type_error(4, "must be of type array when argument #3 ($option) is SO_LINGER, %s given", zend_zval_value_name(arg4));
RETURN_THROWS();
} else {
opt_ht = Z_OBJPROP_P(arg4);
}
} else {
opt_ht = Z_ARRVAL_P(arg4); opt_ht = Z_ARRVAL_P(arg4);
}
if ((l_onoff = zend_hash_str_find(opt_ht, l_onoff_key, sizeof(l_onoff_key) - 1)) == NULL) { if ((l_onoff = zend_hash_str_find(opt_ht, l_onoff_key, sizeof(l_onoff_key) - 1)) == NULL) {
zend_argument_value_error(4, "must have key \"%s\"", l_onoff_key); zend_argument_value_error(4, "must have key \"%s\"", l_onoff_key);
@ -1982,11 +1990,21 @@ PHP_FUNCTION(socket_set_option)
RETURN_THROWS(); RETURN_THROWS();
} }
convert_to_long(l_onoff); zend_long val_lonoff = zval_get_long(l_onoff);
convert_to_long(l_linger); zend_long val_linger = zval_get_long(l_linger);
lv.l_onoff = (unsigned short)Z_LVAL_P(l_onoff); if (val_lonoff < 0 || val_lonoff > USHRT_MAX) {
lv.l_linger = (unsigned short)Z_LVAL_P(l_linger); zend_argument_value_error(4, "\"%s\" must be between 0 and %u", l_onoff_key, USHRT_MAX);
RETURN_THROWS();
}
if (val_linger < 0 || val_linger > USHRT_MAX) {
zend_argument_value_error(4, "\"%s\" must be between 0 and %d", l_linger, USHRT_MAX);
RETURN_THROWS();
}
lv.l_onoff = (unsigned short)val_lonoff;
lv.l_linger = (unsigned short)val_linger;
optlen = sizeof(lv); optlen = sizeof(lv);
opt_ptr = &lv; opt_ptr = &lv;
@ -1998,8 +2016,18 @@ PHP_FUNCTION(socket_set_option)
const char sec_key[] = "sec"; const char sec_key[] = "sec";
const char usec_key[] = "usec"; const char usec_key[] = "usec";
convert_to_array(arg4); if (Z_TYPE_P(arg4) != IS_ARRAY) {
if (UNEXPECTED(Z_TYPE_P(arg4) != IS_OBJECT)) {
zend_argument_type_error(4, "must be of type array when argument #3 ($option) is %s, %s given",
optname == SO_RCVTIMEO ? "SO_RCVTIMEO" : "SO_SNDTIMEO",
zend_zval_value_name(arg4));
RETURN_THROWS();
} else {
opt_ht = Z_OBJPROP_P(arg4);
}
} else {
opt_ht = Z_ARRVAL_P(arg4); opt_ht = Z_ARRVAL_P(arg4);
}
if ((sec = zend_hash_str_find(opt_ht, sec_key, sizeof(sec_key) - 1)) == NULL) { if ((sec = zend_hash_str_find(opt_ht, sec_key, sizeof(sec_key) - 1)) == NULL) {
zend_argument_value_error(4, "must have key \"%s\"", sec_key); zend_argument_value_error(4, "must have key \"%s\"", sec_key);
@ -2010,11 +2038,11 @@ PHP_FUNCTION(socket_set_option)
RETURN_THROWS(); RETURN_THROWS();
} }
convert_to_long(sec); zend_long valsec = zval_get_long(sec);
convert_to_long(usec); zend_long valusec = zval_get_long(usec);
#ifndef PHP_WIN32 #ifndef PHP_WIN32
tv.tv_sec = Z_LVAL_P(sec); tv.tv_sec = valsec;
tv.tv_usec = Z_LVAL_P(usec); tv.tv_usec = valusec;
optlen = sizeof(tv); optlen = sizeof(tv);
opt_ptr = &tv; opt_ptr = &tv;
#else #else
@ -2070,15 +2098,15 @@ PHP_FUNCTION(socket_set_option)
#ifdef SO_ATTACH_REUSEPORT_CBPF #ifdef SO_ATTACH_REUSEPORT_CBPF
case SO_ATTACH_REUSEPORT_CBPF: { case SO_ATTACH_REUSEPORT_CBPF: {
convert_to_long(arg4); zend_long cbpf_val = zval_get_long(arg4);
if (!Z_LVAL_P(arg4)) { if (!cbpf_val) {
ov = 1; ov = 1;
optlen = sizeof(ov); optlen = sizeof(ov);
opt_ptr = &ov; opt_ptr = &ov;
optname = SO_DETACH_BPF; optname = SO_DETACH_BPF;
} else { } else {
uint32_t k = (uint32_t)Z_LVAL_P(arg4); uint32_t k = (uint32_t)cbpf_val;
static struct sock_filter cbpf[8] = {0}; static struct sock_filter cbpf[8] = {0};
static struct sock_fprog bpfprog; static struct sock_fprog bpfprog;
@ -2105,8 +2133,7 @@ PHP_FUNCTION(socket_set_option)
default: default:
default_case: default_case:
convert_to_long(arg4); ov = zval_get_long(arg4);
ov = Z_LVAL_P(arg4);
optlen = sizeof(ov); optlen = sizeof(ov);
opt_ptr = &ov; opt_ptr = &ov;

View file

@ -18,13 +18,20 @@ if (!$socket) {
} }
var_dump(socket_set_option( $socket, SOL_SOCKET, SO_REUSEADDR, true)); var_dump(socket_set_option( $socket, SOL_SOCKET, SO_REUSEADDR, true));
var_dump(socket_set_option( $socket, SOL_SOCKET, SO_REUSEPORT, true)); var_dump(socket_set_option( $socket, SOL_SOCKET, SO_REUSEPORT, true));
try {
socket_set_option( $socket, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, array());
} catch (\TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
var_dump(socket_set_option( $socket, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, SKF_AD_CPU)); var_dump(socket_set_option( $socket, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, SKF_AD_CPU));
var_dump(socket_bind($socket, '0.0.0.0')); var_dump(socket_bind($socket, '0.0.0.0'));
socket_listen($socket); socket_listen($socket);
socket_close($socket); socket_close($socket);
?> ?>
--EXPECT-- --EXPECTF--
bool(true) bool(true)
bool(true) bool(true)
Warning: socket_set_option(): Unable to set socket option [2]: No such file or directory in %s on line %d
bool(true) bool(true)
bool(true) bool(true)

View file

@ -0,0 +1,66 @@
--TEST--
socket_set_option() with SO_RCVTIMEO/SO_SNDTIMEO/SO_LINGER
--EXTENSIONS--
sockets
--FILE--
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$socket) {
die('Unable to create AF_INET socket [socket]');
}
$options_1 = array("sec" => 1, "usec" => "aaaaa");
$options_2 = array("sec" => new stdClass(), "usec" => "1");
$options_3 = array("l_onoff" => "aaaa", "l_linger" => "1");
$options_4 = array("l_onoff" => "1", "l_linger" => []);
$options_5 = array("l_onoff" => PHP_INT_MAX, "l_linger" => "1");
try {
socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, new stdClass);
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, $options_1);
} catch (\TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
socket_set_option( $socket, SOL_SOCKET, SO_SNDTIMEO, $options_2);
} catch (\TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, "not good");
} catch (\TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
socket_set_option( $socket, SOL_SOCKET, SO_LINGER, "not good neither");
} catch (\TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_3);
} catch (\TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_4);
} catch (\TypeError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_5);
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
?>
--EXPECTF--
socket_set_option(): Argument #4 ($value) must have key "sec"
Warning: Object of class stdClass could not be converted to int in %s on line %d
socket_set_option(): Argument #4 ($value) must be of type array when argument #3 ($option) is SO_RCVTIMEO, string given
socket_set_option(): Argument #4 ($value) must be of type array when argument #3 ($option) is SO_LINGER, string given
socket_set_option(): Argument #4 ($value) "l_onoff" must be between 0 and %d