Skip to content

Commit 537a63a

Browse files
committed
ext/curl: Convert handlers.sshhostkey to just be a FCC
1 parent ac7dd35 commit 537a63a

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
@@ -501,8 +501,8 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
501501
}
502502

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

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

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

762-
zval argv[4];
761+
zval args[4];
763762
zval retval;
764-
zend_result error;
765-
zend_fcall_info fci;
766763

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

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

781-
ch->in_callback = 1;
782-
error = zend_call_function(&fci, &t->fci_cache);
783-
ch->in_callback = 0;
784-
if (error == FAILURE) {
785-
php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_SSH_HOSTKEYFUNCTION");
786-
} else if (!Z_ISUNDEF(retval)) {
774+
if (!Z_ISUNDEF(retval)) {
787775
_php_curl_verify_handlers(ch, /* reporterror */ true);
788776
if (Z_TYPE(retval) == IS_LONG) {
789777
zend_long retval_long = Z_LVAL(retval);
@@ -796,8 +784,9 @@ static int curl_ssh_hostkeyfunction(void *clientp, int keytype, const char *key,
796784
zend_throw_error(NULL, "The CURLOPT_SSH_HOSTKEYFUNCTION callback must return either CURLKHMATCH_OK or CURLKHMATCH_MISMATCH");
797785
}
798786
}
799-
zval_ptr_dtor(&argv[0]);
800-
zval_ptr_dtor(&argv[2]);
787+
788+
zval_ptr_dtor(&args[0]);
789+
zval_ptr_dtor(&args[2]);
801790
return rval;
802791
}
803792
#endif
@@ -1111,7 +1100,7 @@ void init_curl_handle(php_curl *ch)
11111100
ch->handlers.xferinfo = NULL;
11121101
ch->handlers.fnmatch = NULL;
11131102
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
1114-
ch->handlers.sshhostkey = NULL;
1103+
ch->handlers.sshhostkey = empty_fcall_info_cache;
11151104
#endif
11161105
ch->clone = emalloc(sizeof(uint32_t));
11171106
*ch->clone = 1;
@@ -1295,7 +1284,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12951284
_php_copy_callback(ch, &ch->handlers.xferinfo, source->handlers.xferinfo, CURLOPT_XFERINFODATA);
12961285
_php_copy_callback(ch, &ch->handlers.fnmatch, source->handlers.fnmatch, CURLOPT_FNMATCH_DATA);
12971286
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
1298-
_php_copy_callback(ch, &ch->handlers.sshhostkey, source->handlers.sshhostkey, CURLOPT_SSH_HOSTKEYDATA);
1287+
php_curl_copy_fcc_with_option(ch, CURLOPT_SSH_HOSTKEYDATA, &ch->handlers.sshhostkey, &source->handlers.sshhostkey);
12991288
#endif
13001289

13011290
ZVAL_COPY(&ch->private_data, &source->private_data);
@@ -2172,17 +2161,17 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
21722161
}
21732162

21742163
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2175-
case CURLOPT_SSH_HOSTKEYFUNCTION:
2164+
case CURLOPT_SSH_HOSTKEYFUNCTION: {
2165+
/* Check value is actually a callable and set it */
2166+
const char option_name[] = "CURLOPT_SSH_HOSTKEYFUNCTION";
2167+
bool result = php_curl_set_callable_handler(&ch->handlers.sshhostkey, zvalue, is_array_config, option_name);
2168+
if (!result) {
2169+
return FAILURE;
2170+
}
21762171
curl_easy_setopt(ch->cp, CURLOPT_SSH_HOSTKEYFUNCTION, curl_ssh_hostkeyfunction);
21772172
curl_easy_setopt(ch->cp, CURLOPT_SSH_HOSTKEYDATA, ch);
2178-
if (ch->handlers.sshhostkey == NULL) {
2179-
ch->handlers.sshhostkey = ecalloc(1, sizeof(php_curl_callback));
2180-
} else if (!Z_ISUNDEF(ch->handlers.sshhostkey->func_name)) {
2181-
zval_ptr_dtor(&ch->handlers.sshhostkey->func_name);
2182-
ch->handlers.sshhostkey->fci_cache = empty_fcall_info_cache;
2183-
}
2184-
ZVAL_COPY(&ch->handlers.sshhostkey->func_name, zvalue);
21852173
break;
2174+
}
21862175
#endif
21872176

21882177
case CURLOPT_READFUNCTION:
@@ -2866,7 +2855,9 @@ static void curl_free_obj(zend_object *object)
28662855
_php_curl_free_callback(ch->handlers.xferinfo);
28672856
_php_curl_free_callback(ch->handlers.fnmatch);
28682857
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2869-
_php_curl_free_callback(ch->handlers.sshhostkey);
2858+
if (ZEND_FCC_INITIALIZED(ch->handlers.sshhostkey)) {
2859+
zend_fcc_dtor(&ch->handlers.sshhostkey);
2860+
}
28702861
#endif
28712862

28722863
zval_ptr_dtor(&ch->postfields);
@@ -2947,10 +2938,8 @@ static void _php_curl_reset_handlers(php_curl *ch)
29472938
}
29482939

29492940
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2950-
if (ch->handlers.sshhostkey) {
2951-
zval_ptr_dtor(&ch->handlers.sshhostkey->func_name);
2952-
efree(ch->handlers.sshhostkey);
2953-
ch->handlers.sshhostkey = NULL;
2941+
if (ZEND_FCC_INITIALIZED(ch->handlers.sshhostkey)) {
2942+
zend_fcc_dtor(&ch->handlers.sshhostkey);
29542943
}
29552944
#endif
29562945
}

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)