Skip to content

Commit ad90308

Browse files
committed
ext/curl: Convert handlers.sshhostkey to just be a FCC
1 parent 9235663 commit ad90308

File tree

3 files changed

+33
-41
lines changed

3 files changed

+33
-41
lines changed

ext/curl/curl_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ typedef struct {
7676
php_curl_callback *xferinfo;
7777
php_curl_callback *fnmatch;
7878
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
79-
php_curl_callback *sshhostkey;
79+
zend_fcall_info_cache sshhostkey;
8080
#endif
8181
} php_curl_handlers;
8282

ext/curl/interface.c

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,8 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
500500
}
501501

502502
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
503-
if (curl->handlers.sshhostkey) {
504-
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.sshhostkey->func_name);
503+
if (ZEND_FCC_INITIALIZED(curl->handlers.sshhostkey)) {
504+
zend_get_gc_buffer_add_fcc(gc_buffer, &curl->handlers.sshhostkey);
505505
}
506506
#endif
507507

@@ -750,39 +750,27 @@ static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
750750
static int curl_ssh_hostkeyfunction(void *clientp, int keytype, const char *key, size_t keylen)
751751
{
752752
php_curl *ch = (php_curl *)clientp;
753-
php_curl_callback *t = ch->handlers.sshhostkey;
754753
int rval = CURLKHMATCH_MISMATCH; /* cancel connection in case of an exception */
755754

756755
#if PHP_CURL_DEBUG
757756
fprintf(stderr, "curl_ssh_hostkeyfunction() called\n");
758757
fprintf(stderr, "clientp = %x, keytype = %d, key = %s, keylen = %zu\n", clientp, keytype, key, keylen);
759758
#endif
760759

761-
zval argv[4];
760+
zval args[4];
762761
zval retval;
763-
zend_result error;
764-
zend_fcall_info fci;
765762

766763
GC_ADDREF(&ch->std);
767-
ZVAL_OBJ(&argv[0], &ch->std);
768-
ZVAL_LONG(&argv[1], keytype);
769-
ZVAL_STRINGL(&argv[2], key, keylen);
770-
ZVAL_LONG(&argv[3], keylen);
764+
ZVAL_OBJ(&args[0], &ch->std);
765+
ZVAL_LONG(&args[1], keytype);
766+
ZVAL_STRINGL(&args[2], key, keylen);
767+
ZVAL_LONG(&args[3], keylen);
771768

772-
fci.size = sizeof(fci);
773-
ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
774-
fci.object = NULL;
775-
fci.retval = &retval;
776-
fci.param_count = 4;
777-
fci.params = argv;
778-
fci.named_params = NULL;
769+
ch->in_callback = true;
770+
zend_call_known_fcc(&ch->handlers.sshhostkey, &retval, /* param_count */ sizeof(args), args, /* named_params */ NULL);
771+
ch->in_callback = false;
779772

780-
ch->in_callback = 1;
781-
error = zend_call_function(&fci, &t->fci_cache);
782-
ch->in_callback = 0;
783-
if (error == FAILURE) {
784-
php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_SSH_HOSTKEYFUNCTION");
785-
} else if (!Z_ISUNDEF(retval)) {
773+
if (!Z_ISUNDEF(retval)) {
786774
_php_curl_verify_handlers(ch, /* reporterror */ true);
787775
if (Z_TYPE(retval) == IS_LONG) {
788776
zend_long retval_long = Z_LVAL(retval);
@@ -795,8 +783,9 @@ static int curl_ssh_hostkeyfunction(void *clientp, int keytype, const char *key,
795783
zend_throw_error(NULL, "The CURLOPT_SSH_HOSTKEYFUNCTION callback must return either CURLKHMATCH_OK or CURLKHMATCH_MISMATCH");
796784
}
797785
}
798-
zval_ptr_dtor(&argv[0]);
799-
zval_ptr_dtor(&argv[2]);
786+
787+
zval_ptr_dtor(&args[0]);
788+
zval_ptr_dtor(&args[2]);
800789
return rval;
801790
}
802791
#endif
@@ -1048,7 +1037,7 @@ void init_curl_handle(php_curl *ch)
10481037
ch->handlers.xferinfo = NULL;
10491038
ch->handlers.fnmatch = NULL;
10501039
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
1051-
ch->handlers.sshhostkey = NULL;
1040+
ch->handlers.sshhostkey = empty_fcall_info_cache;
10521041
#endif
10531042
ch->clone = emalloc(sizeof(uint32_t));
10541043
*ch->clone = 1;
@@ -1232,7 +1221,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12321221
_php_copy_callback(ch, &ch->handlers.xferinfo, source->handlers.xferinfo, CURLOPT_XFERINFODATA);
12331222
_php_copy_callback(ch, &ch->handlers.fnmatch, source->handlers.fnmatch, CURLOPT_FNMATCH_DATA);
12341223
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
1235-
_php_copy_callback(ch, &ch->handlers.sshhostkey, source->handlers.sshhostkey, CURLOPT_SSH_HOSTKEYDATA);
1224+
php_curl_copy_fcc_with_option(ch, CURLOPT_SSH_HOSTKEYDATA, &ch->handlers.sshhostkey, &source->handlers.sshhostkey);
12361225
#endif
12371226

12381227
ZVAL_COPY(&ch->private_data, &source->private_data);
@@ -2109,17 +2098,17 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
21092098
}
21102099

21112100
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2112-
case CURLOPT_SSH_HOSTKEYFUNCTION:
2101+
case CURLOPT_SSH_HOSTKEYFUNCTION: {
2102+
/* Check value is actually a callable and set it */
2103+
const char option_name[] = "CURLOPT_SSH_HOSTKEYFUNCTION";
2104+
bool result = php_curl_set_callable_handler(&ch->handlers.sshhostkey, zvalue, is_array_config, option_name);
2105+
if (!result) {
2106+
return FAILURE;
2107+
}
21132108
curl_easy_setopt(ch->cp, CURLOPT_SSH_HOSTKEYFUNCTION, curl_ssh_hostkeyfunction);
21142109
curl_easy_setopt(ch->cp, CURLOPT_SSH_HOSTKEYDATA, ch);
2115-
if (ch->handlers.sshhostkey == NULL) {
2116-
ch->handlers.sshhostkey = ecalloc(1, sizeof(php_curl_callback));
2117-
} else if (!Z_ISUNDEF(ch->handlers.sshhostkey->func_name)) {
2118-
zval_ptr_dtor(&ch->handlers.sshhostkey->func_name);
2119-
ch->handlers.sshhostkey->fci_cache = empty_fcall_info_cache;
2120-
}
2121-
ZVAL_COPY(&ch->handlers.sshhostkey->func_name, zvalue);
21222110
break;
2111+
}
21232112
#endif
21242113

21252114
case CURLOPT_READFUNCTION:
@@ -2803,7 +2792,9 @@ static void curl_free_obj(zend_object *object)
28032792
_php_curl_free_callback(ch->handlers.xferinfo);
28042793
_php_curl_free_callback(ch->handlers.fnmatch);
28052794
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2806-
_php_curl_free_callback(ch->handlers.sshhostkey);
2795+
if (ZEND_FCC_INITIALIZED(ch->handlers.sshhostkey)) {
2796+
zend_fcc_dtor(&ch->handlers.sshhostkey);
2797+
}
28072798
#endif
28082799

28092800
zval_ptr_dtor(&ch->postfields);
@@ -2884,10 +2875,8 @@ static void _php_curl_reset_handlers(php_curl *ch)
28842875
}
28852876

28862877
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2887-
if (ch->handlers.sshhostkey) {
2888-
zval_ptr_dtor(&ch->handlers.sshhostkey->func_name);
2889-
efree(ch->handlers.sshhostkey);
2890-
ch->handlers.sshhostkey = NULL;
2878+
if (ZEND_FCC_INITIALIZED(ch->handlers.sshhostkey)) {
2879+
zend_fcc_dtor(&ch->handlers.sshhostkey);
28912880
}
28922881
#endif
28932882
}

ext/curl/tests/curl_setopt_callables.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ function testOption(CurlHandle $handle, int $option) {
2424
$url = "{$host}/get.inc";
2525
$ch = curl_init($url);
2626
testOption($ch, CURLOPT_PROGRESSFUNCTION);
27+
testOption($ch, CURLOPT_SSH_HOSTKEYFUNCTION);
2728

2829
?>
2930
--EXPECT--
3031
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_PROGRESSFUNCTION, function "undefined" not found or invalid function name
3132
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_PROGRESSFUNCTION, function "undefined" not found or invalid function name
33+
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_SSH_HOSTKEYFUNCTION, function "undefined" not found or invalid function name
34+
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_SSH_HOSTKEYFUNCTION, function "undefined" not found or invalid function name

0 commit comments

Comments
 (0)