diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index c1e7ead55465..db0401c03942 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -1881,7 +1881,7 @@ PHP_FUNCTION(socket_set_option) #endif zend_long level, optname; void *opt_ptr; - HashTable *opt_ht, *opt_props = NULL; + HashTable *opt_ht; zval *l_onoff, *l_linger; zval *sec, *usec; @@ -1951,31 +1951,22 @@ PHP_FUNCTION(socket_set_option) const char l_linger_key[] = "l_linger"; 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_props = zend_get_properties_for(arg4, ZEND_PROP_PURPOSE_ARRAY_CAST); - opt_ht = opt_props ? opt_props : (HashTable *) &zend_empty_array; - } - } else { - opt_ht = Z_ARRVAL_P(arg4); + 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(); } + opt_ht = Z_ARRVAL_P(arg4); - if ((l_onoff = zend_hash_str_find_ind(opt_ht, l_onoff_key, sizeof(l_onoff_key) - 1)) == NULL) { - zend_release_properties(opt_props); + 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); RETURN_THROWS(); } - if ((l_linger = zend_hash_str_find_ind(opt_ht, l_linger_key, sizeof(l_linger_key) - 1)) == NULL) { - zend_release_properties(opt_props); + if ((l_linger = zend_hash_str_find(opt_ht, l_linger_key, sizeof(l_linger_key) - 1)) == NULL) { zend_argument_value_error(4, "must have key \"%s\"", l_linger_key); RETURN_THROWS(); } zend_long val_lonoff = zval_get_long(l_onoff); zend_long val_linger = zval_get_long(l_linger); - zend_release_properties(opt_props); 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); @@ -1983,7 +1974,7 @@ PHP_FUNCTION(socket_set_option) } if (val_linger < 0 || val_linger > USHRT_MAX) { - zend_argument_value_error(4, "\"%s\" must be between 0 and %d", l_linger_key, USHRT_MAX); + zend_argument_value_error(4, "\"%s\" must be between 0 and %d", l_linger, USHRT_MAX); RETURN_THROWS(); } @@ -2001,33 +1992,24 @@ PHP_FUNCTION(socket_set_option) const char usec_key[] = "usec"; 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_props = zend_get_properties_for(arg4, ZEND_PROP_PURPOSE_ARRAY_CAST); - opt_ht = opt_props ? opt_props : (HashTable *) &zend_empty_array; - } - } else { - opt_ht = Z_ARRVAL_P(arg4); + 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(); } + opt_ht = Z_ARRVAL_P(arg4); - if ((sec = zend_hash_str_find_ind(opt_ht, sec_key, sizeof(sec_key) - 1)) == NULL) { - zend_release_properties(opt_props); + 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); RETURN_THROWS(); } - if ((usec = zend_hash_str_find_ind(opt_ht, usec_key, sizeof(usec_key) - 1)) == NULL) { - zend_release_properties(opt_props); + if ((usec = zend_hash_str_find(opt_ht, usec_key, sizeof(usec_key) - 1)) == NULL) { zend_argument_value_error(4, "must have key \"%s\"", usec_key); RETURN_THROWS(); } zend_long valsec = zval_get_long(sec); zend_long valusec = zval_get_long(usec); - zend_release_properties(opt_props); #ifndef PHP_WIN32 tv.tv_sec = valsec; tv.tv_usec = valusec; diff --git a/ext/sockets/tests/gh24748.phpt b/ext/sockets/tests/gh24748.phpt deleted file mode 100644 index 84f2f127d005..000000000000 --- a/ext/sockets/tests/gh24748.phpt +++ /dev/null @@ -1,64 +0,0 @@ ---TEST-- -GH-24748 (socket_set_option() crashes when the value is an object with declared properties) ---EXTENSIONS-- -sockets ---FILE-- -getMessage(), "\n"; -} - -$timeout = new Timeout(); -$timeout->usec = 0; -var_dump(socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout)); -var_dump(socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, $timeout)); -var_dump(socket_get_option($socket, SOL_SOCKET, SO_SNDTIMEO)); - -$linger = new stdClass(); -$linger->l_onoff = new stdClass(); -$linger->l_linger = 5; -set_error_handler(function () use ($linger) { - $tmp = (array) $linger; - $linger->extra = 1; - unset($tmp); - return true; -}); -var_dump(socket_set_option($socket, SOL_SOCKET, SO_LINGER, $linger)); -restore_error_handler(); - -try { - socket_set_option($socket, SOL_SOCKET, SO_LINGER, new ArrayObject(['l_onoff' => 1, 'l_linger' => 70000])); -} catch (ValueError $e) { - echo $e->getMessage(), "\n"; -} -?> ---EXPECT-- -bool(true) -int(5) -socket_set_option(): Argument #4 ($value) must have key "usec" -bool(true) -bool(true) -array(2) { - ["sec"]=> - int(1) - ["usec"]=> - int(0) -} -bool(true) -socket_set_option(): Argument #4 ($value) "l_linger" must be between 0 and 65535 diff --git a/ext/sockets/tests/socket_set_option_timeo_error.phpt b/ext/sockets/tests/socket_set_option_timeo_error.phpt index 1db5e01c3622..1d0dcdf556d5 100644 --- a/ext/sockets/tests/socket_set_option_timeo_error.phpt +++ b/ext/sockets/tests/socket_set_option_timeo_error.phpt @@ -16,49 +16,49 @@ $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) { +} catch (\Throwable $e) { echo $e->getMessage() . PHP_EOL; } try { socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, $options_1); -} catch (\TypeError $e) { +} catch (\Throwable $e) { echo $e->getMessage() . PHP_EOL; } try { socket_set_option( $socket, SOL_SOCKET, SO_SNDTIMEO, $options_2); -} catch (\TypeError $e) { +} catch (\Throwable $e) { echo $e->getMessage() . PHP_EOL; } try { socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, "not good"); -} catch (\TypeError $e) { +} catch (\Throwable $e) { echo $e->getMessage() . PHP_EOL; } try { socket_set_option( $socket, SOL_SOCKET, SO_LINGER, "not good neither"); -} catch (\TypeError $e) { +} catch (\Throwable $e) { echo $e->getMessage() . PHP_EOL; } try { socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_3); -} catch (\TypeError $e) { +} catch (\Throwable $e) { echo $e->getMessage() . PHP_EOL; } try { socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_4); -} catch (\TypeError $e) { +} catch (\Throwable $e) { echo $e->getMessage() . PHP_EOL; } try { socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_5); -} catch (\ValueError $e) { +} catch (\Throwable $e) { echo $e->getMessage() . PHP_EOL; } ?> --EXPECTF-- -socket_set_option(): Argument #4 ($value) must have key "sec" +socket_set_option(): Argument #4 ($value) must be of type array when argument #3 ($option) is SO_RCVTIMEO, stdClass given 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