Skip to content

Commit 0973ff8

Browse files
committed
ext/curl: Convert php_curl_read to just use FCC without a function name zval
1 parent b7f8a34 commit 0973ff8

File tree

3 files changed

+34
-44
lines changed

3 files changed

+34
-44
lines changed

ext/curl/curl_private.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,13 @@ typedef struct {
5353
} php_curl_write;
5454

5555
typedef struct {
56-
zval func_name;
57-
zend_fcall_info_cache fci_cache;
56+
zend_fcall_info_cache fcc;
5857
FILE *fp;
5958
zend_resource *res;
6059
int method;
6160
zval stream;
6261
} php_curl_read;
6362

64-
typedef struct {
65-
zval func_name;
66-
zend_fcall_info_cache fci_cache;
67-
} php_curl_callback;
68-
6963
typedef struct {
7064
php_curl_write *write;
7165
php_curl_write *write_header;

ext/curl/interface.c

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,9 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
474474

475475
zend_get_gc_buffer_add_zval(gc_buffer, &curl->postfields);
476476
if (curl->handlers.read) {
477-
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.read->func_name);
477+
if (ZEND_FCC_INITIALIZED(curl->handlers.read->fcc)) {
478+
zend_get_gc_buffer_add_fcc(gc_buffer, &curl->handlers.read->fcc);
479+
}
478480
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.read->stream);
479481
}
480482

@@ -766,53 +768,41 @@ static int curl_ssh_hostkeyfunction(void *clientp, int keytype, const char *key,
766768
static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
767769
{
768770
php_curl *ch = (php_curl *)ctx;
769-
php_curl_read *t = ch->handlers.read;
771+
php_curl_read *read_handler = ch->handlers.read;
770772
int length = 0;
771773

772-
switch (t->method) {
774+
switch (read_handler->method) {
773775
case PHP_CURL_DIRECT:
774-
if (t->fp) {
775-
length = fread(data, size, nmemb, t->fp);
776+
if (read_handler->fp) {
777+
length = fread(data, size, nmemb, read_handler->fp);
776778
}
777779
break;
778780
case PHP_CURL_USER: {
779781
zval argv[3];
780782
zval retval;
781-
zend_result error;
782-
zend_fcall_info fci;
783783

784784
GC_ADDREF(&ch->std);
785785
ZVAL_OBJ(&argv[0], &ch->std);
786-
if (t->res) {
787-
GC_ADDREF(t->res);
788-
ZVAL_RES(&argv[1], t->res);
786+
if (read_handler->res) {
787+
GC_ADDREF(read_handler->res);
788+
ZVAL_RES(&argv[1], read_handler->res);
789789
} else {
790790
ZVAL_NULL(&argv[1]);
791791
}
792792
ZVAL_LONG(&argv[2], (int)size * nmemb);
793793

794-
fci.size = sizeof(fci);
795-
ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
796-
fci.object = NULL;
797-
fci.retval = &retval;
798-
fci.param_count = 3;
799-
fci.params = argv;
800-
fci.named_params = NULL;
801-
802-
ch->in_callback = 1;
803-
error = zend_call_function(&fci, &t->fci_cache);
804-
ch->in_callback = 0;
805-
if (error == FAILURE) {
806-
php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_READFUNCTION");
807-
length = CURL_READFUNC_ABORT;
808-
} else if (!Z_ISUNDEF(retval)) {
794+
ch->in_callback = true;
795+
zend_call_known_fcc(&read_handler->fcc, &retval, /* param_count */ 3, argv, /* named_params */ NULL);
796+
ch->in_callback = false;
797+
if (!Z_ISUNDEF(retval)) {
809798
_php_curl_verify_handlers(ch, /* reporterror */ true);
810799
if (Z_TYPE(retval) == IS_STRING) {
811800
length = MIN((int) (size * nmemb), Z_STRLEN(retval));
812801
memcpy(data, Z_STRVAL(retval), length);
813802
} else if (Z_TYPE(retval) == IS_LONG) {
814803
length = Z_LVAL_P(&retval);
815804
}
805+
// TODO Do type error if invalid type?
816806
zval_ptr_dtor(&retval);
817807
}
818808

@@ -1212,8 +1202,8 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12121202
ch->handlers.read->fp = source->handlers.read->fp;
12131203
ch->handlers.read->res = source->handlers.read->res;
12141204

1215-
if (!Z_ISUNDEF(source->handlers.read->func_name)) {
1216-
ZVAL_COPY(&ch->handlers.read->func_name, &source->handlers.read->func_name);
1205+
if (ZEND_FCC_INITIALIZED(source->handlers.read->fcc)) {
1206+
zend_fcc_dup(&source->handlers.read->fcc, &source->handlers.read->fcc);
12171207
}
12181208
if (ZEND_FCC_INITIALIZED(source->handlers.write->fcc)) {
12191209
zend_fcc_dup(&source->handlers.write->fcc, &source->handlers.write->fcc);
@@ -2111,6 +2101,16 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
21112101
break;
21122102
}
21132103

2104+
case CURLOPT_READFUNCTION:
2105+
/* Check value is actually a callable and set it */
2106+
const char option_name[] = "CURLOPT_READFUNCTION";
2107+
bool result = php_curl_set_callable_handler(&ch->handlers.read->fcc, zvalue, is_array_config, option_name);
2108+
if (!result) {
2109+
return FAILURE;
2110+
}
2111+
ch->handlers.read->method = PHP_CURL_USER;
2112+
break;
2113+
21142114
case CURLOPT_PROGRESSFUNCTION: {
21152115
/* Check value is actually a callable and set it */
21162116
const char option_name[] = "CURLOPT_PROGRESSFUNCTION";
@@ -2161,15 +2161,6 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
21612161
}
21622162
#endif
21632163

2164-
case CURLOPT_READFUNCTION:
2165-
if (!Z_ISUNDEF(ch->handlers.read->func_name)) {
2166-
zval_ptr_dtor(&ch->handlers.read->func_name);
2167-
ch->handlers.read->fci_cache = empty_fcall_info_cache;
2168-
}
2169-
ZVAL_COPY(&ch->handlers.read->func_name, zvalue);
2170-
ch->handlers.read->method = PHP_CURL_USER;
2171-
break;
2172-
21732164
case CURLOPT_RETURNTRANSFER:
21742165
if (zend_is_true(zvalue)) {
21752166
ch->handlers.write->method = PHP_CURL_RETURN;
@@ -2779,13 +2770,15 @@ static void curl_free_obj(zend_object *object)
27792770
}
27802771

27812772
smart_str_free(&ch->handlers.write->buf);
2782-
zval_ptr_dtor(&ch->handlers.read->func_name);
27832773
if (ZEND_FCC_INITIALIZED(ch->handlers.write->fcc)) {
27842774
zend_fcc_dtor(&ch->handlers.write->fcc);
27852775
}
27862776
if (ZEND_FCC_INITIALIZED(ch->handlers.write_header->fcc)) {
27872777
zend_fcc_dtor(&ch->handlers.write_header->fcc);
27882778
}
2779+
if (ZEND_FCC_INITIALIZED(ch->handlers.read->fcc)) {
2780+
zend_fcc_dtor(&ch->handlers.read->fcc);
2781+
}
27892782
zval_ptr_dtor(&ch->handlers.std_err);
27902783
if (ch->header.str) {
27912784
zend_string_release_ex(ch->header.str, 0);

ext/curl/tests/curl_setopt_callables.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ testOption($ch, CURLOPT_XFERINFOFUNCTION);
2929
testOption($ch, CURLOPT_FNMATCH_FUNCTION);
3030
testOption($ch, CURLOPT_WRITEFUNCTION);
3131
testOption($ch, CURLOPT_HEADERFUNCTION);
32+
testOption($ch, CURLOPT_READFUNCTION);
3233

3334
?>
3435
--EXPECT--
@@ -44,3 +45,5 @@ TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for opti
4445
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_WRITEFUNCTION, function "undefined" not found or invalid function name
4546
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_HEADERFUNCTION, function "undefined" not found or invalid function name
4647
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_HEADERFUNCTION, function "undefined" not found or invalid function name
48+
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_READFUNCTION, function "undefined" not found or invalid function name
49+
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_READFUNCTION, function "undefined" not found or invalid function name

0 commit comments

Comments
 (0)