@@ -1970,8 +1970,16 @@ PHP_FUNCTION(socket_set_option)
19701970 const char l_onoff_key [] = "l_onoff" ;
19711971 const char l_linger_key [] = "l_linger" ;
19721972
1973- convert_to_array (arg4 );
1974- opt_ht = Z_ARRVAL_P (arg4 );
1973+ if (Z_TYPE_P (arg4 ) != IS_ARRAY ) {
1974+ if (UNEXPECTED (Z_TYPE_P (arg4 ) != IS_OBJECT )) {
1975+ zend_argument_type_error (4 , "must be of type array when argument #3 ($option) is SO_LINGER, %s given" , zend_zval_value_name (arg4 ));
1976+ RETURN_THROWS ();
1977+ } else {
1978+ opt_ht = Z_OBJPROP_P (arg4 );
1979+ }
1980+ } else {
1981+ opt_ht = Z_ARRVAL_P (arg4 );
1982+ }
19751983
19761984 if ((l_onoff = zend_hash_str_find (opt_ht , l_onoff_key , sizeof (l_onoff_key ) - 1 )) == NULL ) {
19771985 zend_argument_value_error (4 , "must have key \"%s\"" , l_onoff_key );
@@ -1982,11 +1990,21 @@ PHP_FUNCTION(socket_set_option)
19821990 RETURN_THROWS ();
19831991 }
19841992
1985- convert_to_long (l_onoff );
1986- convert_to_long (l_linger );
1993+ zend_long val_lonoff = zval_get_long (l_onoff );
1994+ zend_long val_linger = zval_get_long (l_linger );
1995+
1996+ if (val_lonoff < 0 || val_lonoff > USHRT_MAX ) {
1997+ zend_argument_value_error (4 , "\"%s\" must be between 0 and %u" , l_onoff_key , USHRT_MAX );
1998+ RETURN_THROWS ();
1999+ }
2000+
2001+ if (val_linger < 0 || val_linger > USHRT_MAX ) {
2002+ zend_argument_value_error (4 , "\"%s\" must be between 0 and %d" , l_linger , USHRT_MAX );
2003+ RETURN_THROWS ();
2004+ }
19872005
1988- lv .l_onoff = (unsigned short )Z_LVAL_P ( l_onoff ) ;
1989- lv .l_linger = (unsigned short )Z_LVAL_P ( l_linger ) ;
2006+ lv .l_onoff = (unsigned short )val_lonoff ;
2007+ lv .l_linger = (unsigned short )val_linger ;
19902008
19912009 optlen = sizeof (lv );
19922010 opt_ptr = & lv ;
@@ -1998,8 +2016,18 @@ PHP_FUNCTION(socket_set_option)
19982016 const char sec_key [] = "sec" ;
19992017 const char usec_key [] = "usec" ;
20002018
2001- convert_to_array (arg4 );
2002- opt_ht = Z_ARRVAL_P (arg4 );
2019+ if (Z_TYPE_P (arg4 ) != IS_ARRAY ) {
2020+ if (UNEXPECTED (Z_TYPE_P (arg4 ) != IS_OBJECT )) {
2021+ zend_argument_type_error (4 , "must be of type array when argument #3 ($option) is %s, %s given" ,
2022+ optname == SO_RCVTIMEO ? "SO_RCVTIMEO" : "SO_SNDTIMEO" ,
2023+ zend_zval_value_name (arg4 ));
2024+ RETURN_THROWS ();
2025+ } else {
2026+ opt_ht = Z_OBJPROP_P (arg4 );
2027+ }
2028+ } else {
2029+ opt_ht = Z_ARRVAL_P (arg4 );
2030+ }
20032031
20042032 if ((sec = zend_hash_str_find (opt_ht , sec_key , sizeof (sec_key ) - 1 )) == NULL ) {
20052033 zend_argument_value_error (4 , "must have key \"%s\"" , sec_key );
@@ -2010,11 +2038,11 @@ PHP_FUNCTION(socket_set_option)
20102038 RETURN_THROWS ();
20112039 }
20122040
2013- convert_to_long (sec );
2014- convert_to_long (usec );
2041+ zend_long valsec = zval_get_long (sec );
2042+ zend_long valusec = zval_get_long (usec );
20152043#ifndef PHP_WIN32
2016- tv .tv_sec = Z_LVAL_P ( sec ) ;
2017- tv .tv_usec = Z_LVAL_P ( usec ) ;
2044+ tv .tv_sec = valsec ;
2045+ tv .tv_usec = valusec ;
20182046 optlen = sizeof (tv );
20192047 opt_ptr = & tv ;
20202048#else
@@ -2070,15 +2098,15 @@ PHP_FUNCTION(socket_set_option)
20702098
20712099#ifdef SO_ATTACH_REUSEPORT_CBPF
20722100 case SO_ATTACH_REUSEPORT_CBPF : {
2073- convert_to_long (arg4 );
2101+ zend_long cbpf_val = zval_get_long (arg4 );
20742102
2075- if (!Z_LVAL_P ( arg4 ) ) {
2103+ if (!cbpf_val ) {
20762104 ov = 1 ;
20772105 optlen = sizeof (ov );
20782106 opt_ptr = & ov ;
20792107 optname = SO_DETACH_BPF ;
20802108 } else {
2081- uint32_t k = (uint32_t )Z_LVAL_P ( arg4 ) ;
2109+ uint32_t k = (uint32_t )cbpf_val ;
20822110 static struct sock_filter cbpf [8 ] = {0 };
20832111 static struct sock_fprog bpfprog ;
20842112
@@ -2105,8 +2133,7 @@ PHP_FUNCTION(socket_set_option)
21052133
21062134 default :
21072135default_case :
2108- convert_to_long (arg4 );
2109- ov = Z_LVAL_P (arg4 );
2136+ ov = zval_get_long (arg4 );
21102137
21112138 optlen = sizeof (ov );
21122139 opt_ptr = & ov ;
0 commit comments