-
Notifications
You must be signed in to change notification settings - Fork 7.9k
ext/sockets: socket_set_option switch from convert_to_long to zval_tr… #17135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
0e4eeda
45270c6
695861e
6c5f436
1a14443
e18fbb3
d6e64e6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1811,6 +1811,7 @@ PHP_FUNCTION(socket_set_option) | |
HashTable *opt_ht; | ||
zval *l_onoff, *l_linger; | ||
zval *sec, *usec; | ||
bool failed; | ||
|
||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ollz", &arg1, socket_ce, &level, &optname, &arg4) == FAILURE) { | ||
RETURN_THROWS(); | ||
|
@@ -1871,6 +1872,11 @@ PHP_FUNCTION(socket_set_option) | |
const char l_onoff_key[] = "l_onoff"; | ||
const char l_linger_key[] = "l_linger"; | ||
|
||
if (Z_TYPE_P(arg4) != IS_ARRAY) { | ||
zend_argument_type_error(4, "must be of type array, %s given", zend_zval_value_name(arg4)); | ||
RETURN_THROWS(); | ||
} | ||
|
||
convert_to_array(arg4); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This appears to be superfluous, since we just checked that it is an array (and otherwise bailed out). |
||
opt_ht = Z_ARRVAL_P(arg4); | ||
|
||
|
@@ -1883,11 +1889,29 @@ PHP_FUNCTION(socket_set_option) | |
RETURN_THROWS(); | ||
} | ||
|
||
convert_to_long(l_onoff); | ||
convert_to_long(l_linger); | ||
zend_long zl_onoff = zval_try_get_long(l_onoff, &failed); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might also use |
||
if (failed) { | ||
zend_argument_type_error(4, "\"%s\" must be of type int, %s given", l_onoff_key, zend_zval_value_name(l_onoff)); | ||
RETURN_THROWS(); | ||
} | ||
zend_long zl_linger = zval_try_get_long(l_linger, &failed); | ||
if (failed) { | ||
zend_argument_type_error(4, "\"%s\" must be of type int, %s given", l_linger_key, zend_zval_value_name(l_linger)); | ||
RETURN_THROWS(); | ||
} | ||
|
||
if (zl_onoff < 0 || zl_onoff > USHRT_MAX) { | ||
zend_argument_value_error(4, "\"%s\" must be between 0 and %u", l_onoff_key, USHRT_MAX); | ||
RETURN_THROWS(); | ||
} | ||
|
||
if (zl_linger < 0 || zl_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)Z_LVAL_P(l_onoff); | ||
lv.l_linger = (unsigned short)Z_LVAL_P(l_linger); | ||
lv.l_onoff = (unsigned short)zl_onoff; | ||
lv.l_linger = (unsigned short)zl_linger; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably the zend_long should be checked to see if it fits in an unsigned short before. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already happens in the lines above. |
||
|
||
optlen = sizeof(lv); | ||
opt_ptr = &lv; | ||
|
@@ -1899,6 +1923,11 @@ PHP_FUNCTION(socket_set_option) | |
const char sec_key[] = "sec"; | ||
const char usec_key[] = "usec"; | ||
|
||
if (Z_TYPE_P(arg4) != IS_ARRAY) { | ||
zend_argument_type_error(4, "must be of type array, %s given", zend_zval_value_name(arg4)); | ||
RETURN_THROWS(); | ||
} | ||
|
||
convert_to_array(arg4); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could also be updated to check that the value is an array, as if it is not the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This |
||
opt_ht = Z_ARRVAL_P(arg4); | ||
|
||
|
@@ -1911,15 +1940,23 @@ PHP_FUNCTION(socket_set_option) | |
RETURN_THROWS(); | ||
} | ||
|
||
convert_to_long(sec); | ||
convert_to_long(usec); | ||
zend_long zsec = zval_try_get_long(sec, &failed); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming is confusing here. |
||
if (failed) { | ||
zend_argument_type_error(4, "\"%s\" must be of type int, %s given", sec_key, zend_zval_value_name(sec)); | ||
RETURN_THROWS(); | ||
} | ||
zend_long zusec = zval_try_get_long(usec, &failed); | ||
if (failed) { | ||
zend_argument_type_error(4, "\"%s\" must be of type int, %s given", usec_key, zend_zval_value_name(usec)); | ||
RETURN_THROWS(); | ||
} | ||
#ifndef PHP_WIN32 | ||
tv.tv_sec = Z_LVAL_P(sec); | ||
tv.tv_usec = Z_LVAL_P(usec); | ||
tv.tv_sec = zsec; | ||
tv.tv_usec = zusec; | ||
optlen = sizeof(tv); | ||
opt_ptr = &tv; | ||
#else | ||
timeout = Z_LVAL_P(sec) * 1000 + Z_LVAL_P(usec) / 1000; | ||
timeout = zsec * 1000 + zusec / 1000; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I've missed that in the other PR: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
DWORD on master tough here still int but issue can definitively occur very much. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops, I've mixed that up! If this targets PHP-8.3, we cannot change |
||
optlen = sizeof(int); | ||
opt_ptr = &timeout; | ||
#endif | ||
|
@@ -1971,15 +2008,19 @@ PHP_FUNCTION(socket_set_option) | |
|
||
#ifdef SO_ATTACH_REUSEPORT_CBPF | ||
case SO_ATTACH_REUSEPORT_CBPF: { | ||
convert_to_long(arg4); | ||
zend_long fval = zval_try_get_long(arg4, &failed); | ||
if (failed) { | ||
zend_argument_type_error(4, "must be of type int, %s given", zend_zval_value_name(arg4)); | ||
RETURN_THROWS(); | ||
} | ||
|
||
if (!Z_LVAL_P(arg4)) { | ||
if (!fval) { | ||
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)fval; | ||
static struct sock_filter cbpf[8] = {0}; | ||
static struct sock_fprog bpfprog; | ||
|
||
|
@@ -2006,8 +2047,11 @@ PHP_FUNCTION(socket_set_option) | |
|
||
default: | ||
default_case: | ||
convert_to_long(arg4); | ||
ov = Z_LVAL_P(arg4); | ||
ov = zval_try_get_long(arg4, &failed); | ||
if (failed) { | ||
zend_argument_type_error(4, "must be an int, %s given", zend_zval_value_name(arg4)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto |
||
RETURN_THROWS(); | ||
} | ||
|
||
optlen = sizeof(ov); | ||
opt_ptr = &ov; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
--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 (\TypeError $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_LINGER, "not good"); | ||
} 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 be of type array, stdClass given | ||
socket_set_option(): Argument #4 ($value) "usec" must be of type int, string given | ||
socket_set_option(): Argument #4 ($value) "sec" must be of type int, stdClass given | ||
socket_set_option(): Argument #4 ($value) must be of type array, string given | ||
socket_set_option(): Argument #4 ($value) "l_onoff" must be of type int, string given | ||
socket_set_option(): Argument #4 ($value) "l_linger" must be of type int, array given | ||
socket_set_option(): Argument #4 ($value) "l_onoff" must be between 0 and %d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think adding what option we are talking about would help the error message.
And ditto for the other error cases.