Skip to content

Commit 11bf042

Browse files
committed
ext/curl: Convert php_curl_read to just use FCC without a function name zval
1 parent e746ee3 commit 11bf042

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
@@ -473,7 +473,9 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
473473

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

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

771-
switch (t->method) {
773+
switch (read_handler->method) {
772774
case PHP_CURL_DIRECT:
773-
if (t->fp) {
774-
length = fread(data, size, nmemb, t->fp);
775+
if (read_handler->fp) {
776+
length = fread(data, size, nmemb, read_handler->fp);
775777
}
776778
break;
777779
case PHP_CURL_USER: {
778780
zval argv[3];
779781
zval retval;
780-
zend_result error;
781-
zend_fcall_info fci;
782782

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

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

@@ -1149,8 +1139,8 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
11491139
ch->handlers.read->fp = source->handlers.read->fp;
11501140
ch->handlers.read->res = source->handlers.read->res;
11511141

1152-
if (!Z_ISUNDEF(source->handlers.read->func_name)) {
1153-
ZVAL_COPY(&ch->handlers.read->func_name, &source->handlers.read->func_name);
1142+
if (ZEND_FCC_INITIALIZED(source->handlers.read->fcc)) {
1143+
zend_fcc_dup(&source->handlers.read->fcc, &source->handlers.read->fcc);
11541144
}
11551145
if (ZEND_FCC_INITIALIZED(source->handlers.write->fcc)) {
11561146
zend_fcc_dup(&source->handlers.write->fcc, &source->handlers.write->fcc);
@@ -2048,6 +2038,16 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
20482038
break;
20492039
}
20502040

2041+
case CURLOPT_READFUNCTION:
2042+
/* Check value is actually a callable and set it */
2043+
const char option_name[] = "CURLOPT_READFUNCTION";
2044+
bool result = php_curl_set_callable_handler(&ch->handlers.read->fcc, zvalue, is_array_config, option_name);
2045+
if (!result) {
2046+
return FAILURE;
2047+
}
2048+
ch->handlers.read->method = PHP_CURL_USER;
2049+
break;
2050+
20512051
case CURLOPT_PROGRESSFUNCTION: {
20522052
/* Check value is actually a callable and set it */
20532053
const char option_name[] = "CURLOPT_PROGRESSFUNCTION";
@@ -2098,15 +2098,6 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
20982098
}
20992099
#endif
21002100

2101-
case CURLOPT_READFUNCTION:
2102-
if (!Z_ISUNDEF(ch->handlers.read->func_name)) {
2103-
zval_ptr_dtor(&ch->handlers.read->func_name);
2104-
ch->handlers.read->fci_cache = empty_fcall_info_cache;
2105-
}
2106-
ZVAL_COPY(&ch->handlers.read->func_name, zvalue);
2107-
ch->handlers.read->method = PHP_CURL_USER;
2108-
break;
2109-
21102101
case CURLOPT_RETURNTRANSFER:
21112102
if (zend_is_true(zvalue)) {
21122103
ch->handlers.write->method = PHP_CURL_RETURN;
@@ -2716,13 +2707,15 @@ static void curl_free_obj(zend_object *object)
27162707
}
27172708

27182709
smart_str_free(&ch->handlers.write->buf);
2719-
zval_ptr_dtor(&ch->handlers.read->func_name);
27202710
if (ZEND_FCC_INITIALIZED(ch->handlers.write->fcc)) {
27212711
zend_fcc_dtor(&ch->handlers.write->fcc);
27222712
}
27232713
if (ZEND_FCC_INITIALIZED(ch->handlers.write_header->fcc)) {
27242714
zend_fcc_dtor(&ch->handlers.write_header->fcc);
27252715
}
2716+
if (ZEND_FCC_INITIALIZED(ch->handlers.read->fcc)) {
2717+
zend_fcc_dtor(&ch->handlers.read->fcc);
2718+
}
27262719
zval_ptr_dtor(&ch->handlers.std_err);
27272720
if (ch->header.str) {
27282721
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)