mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
ext/sockets: socket_set_option switch from convert_to_long to zval_get_long.
to be explicit when the expected type is not met. Check SO_LINGER values for possible overflow. close GH-17135
This commit is contained in:
3
NEWS
3
NEWS
@@ -48,6 +48,9 @@ PHP NEWS
|
||||
- Sockets:
|
||||
. Fixed bug GH-16276 (socket_strerror overflow handling with INT_MIN).
|
||||
(David Carlier / cmb)
|
||||
. Fixed overflow on SO_LINGER values setting, strengthening values check
|
||||
on SO_SNDTIMEO/SO_RCVTIMEO for socket_set_option().
|
||||
(David Carlier)
|
||||
|
||||
- Streams:
|
||||
. Fixed bug GH-17037 (UAF in user filter when adding existing filter name due
|
||||
|
||||
@@ -1871,8 +1871,16 @@ PHP_FUNCTION(socket_set_option)
|
||||
const char l_onoff_key[] = "l_onoff";
|
||||
const char l_linger_key[] = "l_linger";
|
||||
|
||||
convert_to_array(arg4);
|
||||
opt_ht = Z_ARRVAL_P(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);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -1883,11 +1891,21 @@ PHP_FUNCTION(socket_set_option)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
convert_to_long(l_onoff);
|
||||
convert_to_long(l_linger);
|
||||
zend_long val_lonoff = zval_get_long(l_onoff);
|
||||
zend_long val_linger = zval_get_long(l_linger);
|
||||
|
||||
lv.l_onoff = (unsigned short)Z_LVAL_P(l_onoff);
|
||||
lv.l_linger = (unsigned short)Z_LVAL_P(l_linger);
|
||||
if (val_lonoff < 0 || val_lonoff > USHRT_MAX) {
|
||||
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);
|
||||
opt_ptr = &lv;
|
||||
@@ -1899,8 +1917,18 @@ PHP_FUNCTION(socket_set_option)
|
||||
const char sec_key[] = "sec";
|
||||
const char usec_key[] = "usec";
|
||||
|
||||
convert_to_array(arg4);
|
||||
opt_ht = Z_ARRVAL_P(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);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -1911,15 +1939,16 @@ PHP_FUNCTION(socket_set_option)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
convert_to_long(sec);
|
||||
convert_to_long(usec);
|
||||
zend_long valsec = zval_get_long(sec);
|
||||
zend_long valusec = zval_get_long(usec);
|
||||
#ifndef PHP_WIN32
|
||||
tv.tv_sec = Z_LVAL_P(sec);
|
||||
tv.tv_usec = Z_LVAL_P(usec);
|
||||
tv.tv_sec = valsec;
|
||||
tv.tv_usec = valusec;
|
||||
optlen = sizeof(tv);
|
||||
opt_ptr = &tv;
|
||||
#else
|
||||
timeout = Z_LVAL_P(sec) * 1000 + Z_LVAL_P(usec) / 1000;
|
||||
timeout = valsec * 1000 + valusec / 1000;
|
||||
|
||||
optlen = sizeof(int);
|
||||
opt_ptr = &timeout;
|
||||
#endif
|
||||
@@ -1971,15 +2000,15 @@ PHP_FUNCTION(socket_set_option)
|
||||
|
||||
#ifdef 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;
|
||||
optlen = sizeof(ov);
|
||||
opt_ptr = &ov;
|
||||
optname = SO_DETACH_BPF;
|
||||
} 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_fprog bpfprog;
|
||||
|
||||
@@ -2006,8 +2035,7 @@ PHP_FUNCTION(socket_set_option)
|
||||
|
||||
default:
|
||||
default_case:
|
||||
convert_to_long(arg4);
|
||||
ov = Z_LVAL_P(arg4);
|
||||
ov = zval_get_long(arg4);
|
||||
|
||||
optlen = sizeof(ov);
|
||||
opt_ptr = &ov;
|
||||
|
||||
@@ -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_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_bind($socket, '0.0.0.0'));
|
||||
socket_listen($socket);
|
||||
socket_close($socket);
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
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)
|
||||
|
||||
66
ext/sockets/tests/socket_set_option_timeo_error.phpt
Normal file
66
ext/sockets/tests/socket_set_option_timeo_error.phpt
Normal 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
|
||||
Reference in New Issue
Block a user