Skip to content

Commit 80ab6a2

Browse files
committed
ext/curl: Convert handlers.xferinfo to just be a FCC
1 parent ad90308 commit 80ab6a2

File tree

4 files changed

+48
-50
lines changed

4 files changed

+48
-50
lines changed

ext/curl/curl_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ typedef struct {
7373
php_curl_read *read;
7474
zval std_err;
7575
zend_fcall_info_cache progress;
76-
php_curl_callback *xferinfo;
76+
zend_fcall_info_cache xferinfo;
7777
php_curl_callback *fnmatch;
7878
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
7979
zend_fcall_info_cache sshhostkey;

ext/curl/interface.c

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,8 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
491491
zend_get_gc_buffer_add_fcc(gc_buffer, &curl->handlers.progress);
492492
}
493493

494-
if (curl->handlers.xferinfo) {
495-
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.xferinfo->func_name);
494+
if (ZEND_FCC_INITIALIZED(curl->handlers.xferinfo)) {
495+
zend_get_gc_buffer_add_fcc(gc_buffer, &curl->handlers.xferinfo);
496496
}
497497

498498
if (curl->handlers.fnmatch) {
@@ -702,7 +702,6 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double
702702
static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
703703
{
704704
php_curl *ch = (php_curl *)clientp;
705-
php_curl_callback *t = ch->handlers.xferinfo;
706705
size_t rval = 0;
707706

708707
#if PHP_CURL_DEBUG
@@ -712,8 +711,6 @@ static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
712711

713712
zval argv[5];
714713
zval retval;
715-
zend_result error;
716-
zend_fcall_info fci;
717714

718715
GC_ADDREF(&ch->std);
719716
ZVAL_OBJ(&argv[0], &ch->std);
@@ -722,25 +719,18 @@ static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
722719
ZVAL_LONG(&argv[3], ultotal);
723720
ZVAL_LONG(&argv[4], ulnow);
724721

725-
fci.size = sizeof(fci);
726-
ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
727-
fci.object = NULL;
728-
fci.retval = &retval;
729-
fci.param_count = 5;
730-
fci.params = argv;
731-
fci.named_params = NULL;
722+
ch->in_callback = true;
723+
zend_call_known_fcc(&ch->handlers.xferinfo, &retval, /* param_count */ sizeof(argv), argv, /* named_params */ NULL);
724+
ch->in_callback = false;
725+
726+
if (!Z_ISUNDEF(retval)) {
727+
_php_curl_verify_handlers(ch, /* reporterror */ true);
728+
/* TODO Check callback returns an int or something castable to in */
729+
if (0 != zval_get_long(&retval)) {
730+
rval = 1;
731+
}
732+
}
732733

733-
ch->in_callback = 1;
734-
error = zend_call_function(&fci, &t->fci_cache);
735-
ch->in_callback = 0;
736-
if (error == FAILURE) {
737-
php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_XFERINFOFUNCTION");
738-
} else if (!Z_ISUNDEF(retval)) {
739-
_php_curl_verify_handlers(ch, /* reporterror */ true);
740-
if (0 != zval_get_long(&retval)) {
741-
rval = 1;
742-
}
743-
}
744734
zval_ptr_dtor(&argv[0]);
745735
return rval;
746736
}
@@ -1034,7 +1024,7 @@ void init_curl_handle(php_curl *ch)
10341024
ch->handlers.write_header = ecalloc(1, sizeof(php_curl_write));
10351025
ch->handlers.read = ecalloc(1, sizeof(php_curl_read));
10361026
ch->handlers.progress = empty_fcall_info_cache;
1037-
ch->handlers.xferinfo = NULL;
1027+
ch->handlers.xferinfo = empty_fcall_info_cache;
10381028
ch->handlers.fnmatch = NULL;
10391029
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
10401030
ch->handlers.sshhostkey = empty_fcall_info_cache;
@@ -1218,7 +1208,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12181208
curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *) ch);
12191209

12201210
php_curl_copy_fcc_with_option(ch, CURLOPT_PROGRESSDATA, &ch->handlers.progress, &source->handlers.progress);
1221-
_php_copy_callback(ch, &ch->handlers.xferinfo, source->handlers.xferinfo, CURLOPT_XFERINFODATA);
1211+
php_curl_copy_fcc_with_option(ch, CURLOPT_XFERINFODATA, &ch->handlers.xferinfo, &source->handlers.xferinfo);
12221212
_php_copy_callback(ch, &ch->handlers.fnmatch, source->handlers.fnmatch, CURLOPT_FNMATCH_DATA);
12231213
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
12241214
php_curl_copy_fcc_with_option(ch, CURLOPT_SSH_HOSTKEYDATA, &ch->handlers.sshhostkey, &source->handlers.sshhostkey);
@@ -2137,17 +2127,17 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
21372127
ch->handlers.write->method = PHP_CURL_USER;
21382128
break;
21392129

2140-
case CURLOPT_XFERINFOFUNCTION:
2130+
case CURLOPT_XFERINFOFUNCTION: {
2131+
/* Check value is actually a callable and set it */
2132+
const char option_name[] = "CURLOPT_XFERINFOFUNCTION";
2133+
bool result = php_curl_set_callable_handler(&ch->handlers.xferinfo, zvalue, is_array_config, option_name);
2134+
if (!result) {
2135+
return FAILURE;
2136+
}
21412137
curl_easy_setopt(ch->cp, CURLOPT_XFERINFOFUNCTION, curl_xferinfo);
21422138
curl_easy_setopt(ch->cp, CURLOPT_XFERINFODATA, ch);
2143-
if (ch->handlers.xferinfo == NULL) {
2144-
ch->handlers.xferinfo = ecalloc(1, sizeof(php_curl_callback));
2145-
} else if (!Z_ISUNDEF(ch->handlers.xferinfo->func_name)) {
2146-
zval_ptr_dtor(&ch->handlers.xferinfo->func_name);
2147-
ch->handlers.xferinfo->fci_cache = empty_fcall_info_cache;
2148-
}
2149-
ZVAL_COPY(&ch->handlers.xferinfo->func_name, zvalue);
21502139
break;
2140+
}
21512141

21522142
/* Curl off_t options */
21532143
case CURLOPT_MAX_RECV_SPEED_LARGE:
@@ -2789,7 +2779,9 @@ static void curl_free_obj(zend_object *object)
27892779
if (ZEND_FCC_INITIALIZED(ch->handlers.progress)) {
27902780
zend_fcc_dtor(&ch->handlers.progress);
27912781
}
2792-
_php_curl_free_callback(ch->handlers.xferinfo);
2782+
if (ZEND_FCC_INITIALIZED(ch->handlers.xferinfo)) {
2783+
zend_fcc_dtor(&ch->handlers.xferinfo);
2784+
}
27932785
_php_curl_free_callback(ch->handlers.fnmatch);
27942786
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
27952787
if (ZEND_FCC_INITIALIZED(ch->handlers.sshhostkey)) {
@@ -2862,10 +2854,9 @@ static void _php_curl_reset_handlers(php_curl *ch)
28622854
zend_fcc_dtor(&ch->handlers.progress);
28632855
}
28642856

2865-
if (ch->handlers.xferinfo) {
2866-
zval_ptr_dtor(&ch->handlers.xferinfo->func_name);
2867-
efree(ch->handlers.xferinfo);
2868-
ch->handlers.xferinfo = NULL;
2857+
if (ZEND_FCC_INITIALIZED(ch->handlers.xferinfo)) {
2858+
zend_fcc_dtor(&ch->handlers.xferinfo);
2859+
ch->handlers.xferinfo.function_handler = NULL;
28692860
}
28702861

28712862
if (ch->handlers.fnmatch) {

ext/curl/tests/curl_copy_handle_xferinfo.phpt

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@ Test curl_copy_handle() with CURLOPT_XFERINFOFUNCTION
44
curl
55
--FILE--
66
<?php
7-
include 'server.inc';
8-
$host = curl_cli_server_start();
7+
include 'server.inc';
8+
$host = curl_cli_server_start();
99

10-
$url = "{$host}/get.inc";
11-
$ch = curl_init($url);
10+
$url = "{$host}/get.inc";
11+
$ch = curl_init($url);
1212

13-
curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
14-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
15-
curl_setopt($ch, CURLOPT_XFERINFOFUNCTION, function() { static $done = false; if (!$done) { echo "Download progress!\n"; $done = true; } });
16-
$ch2 = curl_copy_handle($ch);
17-
echo curl_exec($ch), PHP_EOL;
18-
unset($ch);
19-
echo curl_exec($ch2);
13+
function foo() {
14+
static $done = false; if (!$done) { echo "Download progress!\n"; $done = true; }
15+
}
16+
17+
curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
18+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
19+
curl_setopt($ch, CURLOPT_XFERINFOFUNCTION, 'foo');
20+
$ch2 = curl_copy_handle($ch);
21+
echo curl_exec($ch), PHP_EOL;
22+
unset($ch);
23+
echo curl_exec($ch2);
2024

2125
?>
2226
--EXPECT--

ext/curl/tests/curl_setopt_callables.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ $url = "{$host}/get.inc";
2525
$ch = curl_init($url);
2626
testOption($ch, CURLOPT_PROGRESSFUNCTION);
2727
testOption($ch, CURLOPT_SSH_HOSTKEYFUNCTION);
28+
testOption($ch, CURLOPT_XFERINFOFUNCTION);
2829

2930
?>
3031
--EXPECT--
3132
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_PROGRESSFUNCTION, function "undefined" not found or invalid function name
3233
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_PROGRESSFUNCTION, function "undefined" not found or invalid function name
3334
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_SSH_HOSTKEYFUNCTION, function "undefined" not found or invalid function name
3435
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
36+
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_XFERINFOFUNCTION, function "undefined" not found or invalid function name
37+
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_XFERINFOFUNCTION, function "undefined" not found or invalid function name

0 commit comments

Comments
 (0)