Skip to content

Commit 0e4eeda

Browse files
committed
ext/sockets: socket_set_option switch from convert_to_long to zval_try_get_long.
to be explicit when the expected type is not met.
1 parent e7af08d commit 0e4eeda

File tree

2 files changed

+81
-14
lines changed

2 files changed

+81
-14
lines changed

ext/sockets/sockets.c

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,7 @@ PHP_FUNCTION(socket_set_option)
18111811
HashTable *opt_ht;
18121812
zval *l_onoff, *l_linger;
18131813
zval *sec, *usec;
1814+
bool failed;
18141815

18151816
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ollz", &arg1, socket_ce, &level, &optname, &arg4) == FAILURE) {
18161817
RETURN_THROWS();
@@ -1883,11 +1884,19 @@ PHP_FUNCTION(socket_set_option)
18831884
RETURN_THROWS();
18841885
}
18851886

1886-
convert_to_long(l_onoff);
1887-
convert_to_long(l_linger);
1887+
zend_long zl_onoff = zval_try_get_long(l_onoff, &failed);
1888+
if (failed) {
1889+
zend_argument_type_error(4, "\"%s\" must be an int, %s given", l_onoff_key, zend_zval_value_name(l_onoff));
1890+
RETURN_THROWS();
1891+
}
1892+
zend_long zl_linger = zval_try_get_long(l_linger, &failed);
1893+
if (failed) {
1894+
zend_argument_type_error(4, "\"%s\" must be an int, %s given", l_linger_key, zend_zval_value_name(l_linger));
1895+
RETURN_THROWS();
1896+
}
18881897

1889-
lv.l_onoff = (unsigned short)Z_LVAL_P(l_onoff);
1890-
lv.l_linger = (unsigned short)Z_LVAL_P(l_linger);
1898+
lv.l_onoff = (unsigned short)zl_onoff;
1899+
lv.l_linger = (unsigned short)zl_linger;
18911900

18921901
optlen = sizeof(lv);
18931902
opt_ptr = &lv;
@@ -1898,6 +1907,7 @@ PHP_FUNCTION(socket_set_option)
18981907
case SO_SNDTIMEO: {
18991908
const char sec_key[] = "sec";
19001909
const char usec_key[] = "usec";
1910+
bool failed;
19011911

19021912
convert_to_array(arg4);
19031913
opt_ht = Z_ARRVAL_P(arg4);
@@ -1911,15 +1921,23 @@ PHP_FUNCTION(socket_set_option)
19111921
RETURN_THROWS();
19121922
}
19131923

1914-
convert_to_long(sec);
1915-
convert_to_long(usec);
1924+
zend_long zsec = zval_try_get_long(sec, &failed);
1925+
if (failed) {
1926+
zend_argument_type_error(4, "\"%s\" must be an int, %s given", sec_key, zend_zval_value_name(sec));
1927+
RETURN_THROWS();
1928+
}
1929+
zend_long zusec = zval_try_get_long(usec, &failed);
1930+
if (failed) {
1931+
zend_argument_type_error(4, "\"%s\" must be an int, %s given", usec_key, zend_zval_value_name(usec));
1932+
RETURN_THROWS();
1933+
}
19161934
#ifndef PHP_WIN32
1917-
tv.tv_sec = Z_LVAL_P(sec);
1918-
tv.tv_usec = Z_LVAL_P(usec);
1935+
tv.tv_sec = zsec;
1936+
tv.tv_usec = zusec;
19191937
optlen = sizeof(tv);
19201938
opt_ptr = &tv;
19211939
#else
1922-
timeout = Z_LVAL_P(sec) * 1000 + Z_LVAL_P(usec) / 1000;
1940+
timeout = zsec * 1000 + zusec / 1000;
19231941
optlen = sizeof(int);
19241942
opt_ptr = &timeout;
19251943
#endif
@@ -1971,15 +1989,19 @@ PHP_FUNCTION(socket_set_option)
19711989

19721990
#ifdef SO_ATTACH_REUSEPORT_CBPF
19731991
case SO_ATTACH_REUSEPORT_CBPF: {
1974-
convert_to_long(arg4);
1992+
zend_long fval = zval_try_get_long(arg4, &failed);
1993+
if (failed) {
1994+
zend_argument_type_error(4, "must be an int, %s given", zend_zval_value_name(arg4));
1995+
RETURN_THROWS();
1996+
}
19751997

1976-
if (!Z_LVAL_P(arg4)) {
1998+
if (!fval) {
19771999
ov = 1;
19782000
optlen = sizeof(ov);
19792001
opt_ptr = &ov;
19802002
optname = SO_DETACH_BPF;
19812003
} else {
1982-
uint32_t k = (uint32_t)Z_LVAL_P(arg4);
2004+
uint32_t k = (uint32_t)fval;
19832005
static struct sock_filter cbpf[8] = {0};
19842006
static struct sock_fprog bpfprog;
19852007

@@ -2006,8 +2028,11 @@ PHP_FUNCTION(socket_set_option)
20062028

20072029
default:
20082030
default_case:
2009-
convert_to_long(arg4);
2010-
ov = Z_LVAL_P(arg4);
2031+
ov = zval_try_get_long(arg4, &failed);
2032+
if (failed) {
2033+
zend_argument_type_error(4, "must be an int, %s given", zend_zval_value_name(arg4));
2034+
RETURN_THROWS();
2035+
}
20112036

20122037
optlen = sizeof(ov);
20132038
opt_ptr = &ov;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
socket_set_option() with SO_RCVTIMEO/SO_SNDTIMEO/SO_LINGER
3+
--EXTENSIONS--
4+
sockets
5+
--FILE--
6+
<?php
7+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
8+
if (!$socket) {
9+
die('Unable to create AF_INET socket [socket]');
10+
}
11+
$options_1 = array("sec" => 1, "usec" => "aaaaa");
12+
$options_2 = array("sec" => new stdClass(), "usec" => "1");
13+
$options_3 = array("l_onoff" => "aaaa", "l_linger" => "1");
14+
$options_4 = array("l_onoff" => "1", "l_linger" => []);
15+
16+
try {
17+
socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, $options_1);
18+
} catch (\TypeError $e) {
19+
echo $e->getMessage() . PHP_EOL;
20+
}
21+
22+
try {
23+
socket_set_option( $socket, SOL_SOCKET, SO_SNDTIMEO, $options_2);
24+
} catch (\TypeError $e) {
25+
echo $e->getMessage() . PHP_EOL;
26+
}
27+
try {
28+
socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_3);
29+
} catch (\TypeError $e) {
30+
echo $e->getMessage() . PHP_EOL;
31+
}
32+
try {
33+
socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_4);
34+
} catch (\TypeError $e) {
35+
echo $e->getMessage() . PHP_EOL;
36+
}
37+
?>
38+
--EXPECT--
39+
socket_set_option(): Argument #4 ($value) "usec" must be an int, string given
40+
socket_set_option(): Argument #4 ($value) "sec" must be an int, stdClass given
41+
socket_set_option(): Argument #4 ($value) "l_onoff" must be an int, string given
42+
socket_set_option(): Argument #4 ($value) "l_linger" must be an int, array given

0 commit comments

Comments
 (0)