@@ -488,8 +488,8 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
488
488
zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .write_header -> stream );
489
489
}
490
490
491
- if (curl -> handlers .progress ) {
492
- zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .progress -> func_name );
491
+ if (ZEND_FCC_INITIALIZED ( curl -> handlers .progress ) ) {
492
+ zend_get_gc_buffer_add_fcc (gc_buffer , & curl -> handlers .progress );
493
493
}
494
494
495
495
if (curl -> handlers .xferinfo ) {
@@ -665,46 +665,36 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string)
665
665
static size_t curl_progress (void * clientp , double dltotal , double dlnow , double ultotal , double ulnow )
666
666
{
667
667
php_curl * ch = (php_curl * )clientp ;
668
- php_curl_callback * t = ch -> handlers .progress ;
669
668
size_t rval = 0 ;
670
669
671
670
#if PHP_CURL_DEBUG
672
671
fprintf (stderr , "curl_progress() called\n" );
673
672
fprintf (stderr , "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n" , clientp , dltotal , dlnow , ultotal , ulnow );
674
673
#endif
675
674
676
- zval argv [5 ];
675
+ zval args [5 ];
677
676
zval retval ;
678
- zend_result error ;
679
- zend_fcall_info fci ;
680
677
681
678
GC_ADDREF (& ch -> std );
682
- ZVAL_OBJ (& argv [0 ], & ch -> std );
683
- ZVAL_LONG (& argv [1 ], (zend_long )dltotal );
684
- ZVAL_LONG (& argv [2 ], (zend_long )dlnow );
685
- ZVAL_LONG (& argv [3 ], (zend_long )ultotal );
686
- ZVAL_LONG (& argv [4 ], (zend_long )ulnow );
687
-
688
- fci .size = sizeof (fci );
689
- ZVAL_COPY_VALUE (& fci .function_name , & t -> func_name );
690
- fci .object = NULL ;
691
- fci .retval = & retval ;
692
- fci .param_count = 5 ;
693
- fci .params = argv ;
694
- fci .named_params = NULL ;
695
-
696
- ch -> in_callback = 1 ;
697
- error = zend_call_function (& fci , & t -> fci_cache );
698
- ch -> in_callback = 0 ;
699
- if (error == FAILURE ) {
700
- php_error_docref (NULL , E_WARNING , "Cannot call the CURLOPT_PROGRESSFUNCTION" );
701
- } else if (!Z_ISUNDEF (retval )) {
702
- _php_curl_verify_handlers (ch , /* reporterror */ true);
703
- if (0 != zval_get_long (& retval )) {
704
- rval = 1 ;
705
- }
706
- }
707
- zval_ptr_dtor (& argv [0 ]);
679
+ ZVAL_OBJ (& args [0 ], & ch -> std );
680
+ ZVAL_LONG (& args [1 ], (zend_long )dltotal );
681
+ ZVAL_LONG (& args [2 ], (zend_long )dlnow );
682
+ ZVAL_LONG (& args [3 ], (zend_long )ultotal );
683
+ ZVAL_LONG (& args [4 ], (zend_long )ulnow );
684
+
685
+ ch -> in_callback = true;
686
+ zend_call_known_fcc (& ch -> handlers .progress , & retval , /* param_count */ 5 , args , /* named_params */ NULL );
687
+ ch -> in_callback = false;
688
+
689
+ if (!Z_ISUNDEF (retval )) {
690
+ _php_curl_verify_handlers (ch , /* reporterror */ true);
691
+ /* TODO Check callback returns an int or something castable to int */
692
+ if (0 != zval_get_long (& retval )) {
693
+ rval = 1 ;
694
+ }
695
+ }
696
+
697
+ zval_ptr_dtor (& args [0 ]);
708
698
return rval ;
709
699
}
710
700
/* }}} */
@@ -1117,7 +1107,7 @@ void init_curl_handle(php_curl *ch)
1117
1107
ch -> handlers .write = ecalloc (1 , sizeof (php_curl_write ));
1118
1108
ch -> handlers .write_header = ecalloc (1 , sizeof (php_curl_write ));
1119
1109
ch -> handlers .read = ecalloc (1 , sizeof (php_curl_read ));
1120
- ch -> handlers .progress = NULL ;
1110
+ ch -> handlers .progress = empty_fcall_info_cache ;
1121
1111
ch -> handlers .xferinfo = NULL ;
1122
1112
ch -> handlers .fnmatch = NULL ;
1123
1113
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
@@ -1254,6 +1244,14 @@ static void _php_copy_callback(php_curl *ch, php_curl_callback **new_callback, p
1254
1244
}
1255
1245
}
1256
1246
1247
+ static void php_curl_copy_fcc_with_option (php_curl * ch , CURLoption option , zend_fcall_info_cache * target_fcc , zend_fcall_info_cache * source_fcc )
1248
+ {
1249
+ if (ZEND_FCC_INITIALIZED (* source_fcc )) {
1250
+ zend_fcc_dup (target_fcc , source_fcc );
1251
+ curl_easy_setopt (ch -> cp , option , (void * ) ch );
1252
+ }
1253
+ }
1254
+
1257
1255
void _php_setup_easy_copy_handlers (php_curl * ch , php_curl * source )
1258
1256
{
1259
1257
if (!Z_ISUNDEF (source -> handlers .write -> stream )) {
@@ -1293,7 +1291,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
1293
1291
curl_easy_setopt (ch -> cp , CURLOPT_WRITEHEADER , (void * ) ch );
1294
1292
curl_easy_setopt (ch -> cp , CURLOPT_DEBUGDATA , (void * ) ch );
1295
1293
1296
- _php_copy_callback (ch , & ch -> handlers .progress , source -> handlers .progress , CURLOPT_PROGRESSDATA );
1294
+ php_curl_copy_fcc_with_option (ch , CURLOPT_PROGRESSDATA , & ch -> handlers .progress , & source -> handlers .progress );
1297
1295
_php_copy_callback (ch , & ch -> handlers .xferinfo , source -> handlers .xferinfo , CURLOPT_XFERINFODATA );
1298
1296
_php_copy_callback (ch , & ch -> handlers .fnmatch , source -> handlers .fnmatch , CURLOPT_FNMATCH_DATA );
1299
1297
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
@@ -1598,6 +1596,25 @@ PHP_FUNCTION(curl_copy_handle)
1598
1596
}
1599
1597
/* }}} */
1600
1598
1599
+ static bool php_curl_set_callable_handler (zend_fcall_info_cache * const handler_fcc , zval * callable , bool is_array_config , const char * option_name )
1600
+ {
1601
+ if (ZEND_FCC_INITIALIZED (* handler_fcc )) {
1602
+ zend_fcc_dtor (handler_fcc );
1603
+ handler_fcc -> function_handler = NULL ;
1604
+ }
1605
+
1606
+ char * error = NULL ;
1607
+ if (UNEXPECTED (!zend_is_callable_ex (callable , /* object */ NULL , /* check_flags */ 0 , /* callable_name */ NULL , handler_fcc , /* error */ & error ))) {
1608
+ if (!EG (exception )) {
1609
+ zend_argument_type_error (2 + !is_array_config , "must be a valid callback for option %s, %s" , option_name , error );
1610
+ }
1611
+ efree (error );
1612
+ return false;
1613
+ }
1614
+ zend_fcc_addref (handler_fcc );
1615
+ return true;
1616
+ }
1617
+
1601
1618
static zend_result _php_curl_setopt (php_curl * ch , zend_long option , zval * zvalue , bool is_array_config ) /* {{{ */
1602
1619
{
1603
1620
CURLcode error = CURLE_OK ;
@@ -2142,17 +2159,17 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
2142
2159
}
2143
2160
break ;
2144
2161
2145
- case CURLOPT_PROGRESSFUNCTION :
2162
+ case CURLOPT_PROGRESSFUNCTION : {
2163
+ /* Check value is actually a callable and set it */
2164
+ const char option_name [] = "CURLOPT_PROGRESSFUNCTION" ;
2165
+ bool result = php_curl_set_callable_handler (& ch -> handlers .progress , zvalue , is_array_config , option_name );
2166
+ if (!result ) {
2167
+ return FAILURE ;
2168
+ }
2146
2169
curl_easy_setopt (ch -> cp , CURLOPT_PROGRESSFUNCTION , curl_progress );
2147
2170
curl_easy_setopt (ch -> cp , CURLOPT_PROGRESSDATA , ch );
2148
- if (ch -> handlers .progress == NULL ) {
2149
- ch -> handlers .progress = ecalloc (1 , sizeof (php_curl_callback ));
2150
- } else if (!Z_ISUNDEF (ch -> handlers .progress -> func_name )) {
2151
- zval_ptr_dtor (& ch -> handlers .progress -> func_name );
2152
- ch -> handlers .progress -> fci_cache = empty_fcall_info_cache ;
2153
- }
2154
- ZVAL_COPY (& ch -> handlers .progress -> func_name , zvalue );
2155
2171
break ;
2172
+ }
2156
2173
2157
2174
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2158
2175
case CURLOPT_SSH_HOSTKEYFUNCTION :
@@ -2843,7 +2860,9 @@ static void curl_free_obj(zend_object *object)
2843
2860
efree (ch -> handlers .write_header );
2844
2861
efree (ch -> handlers .read );
2845
2862
2846
- _php_curl_free_callback (ch -> handlers .progress );
2863
+ if (ZEND_FCC_INITIALIZED (ch -> handlers .progress )) {
2864
+ zend_fcc_dtor (& ch -> handlers .progress );
2865
+ }
2847
2866
_php_curl_free_callback (ch -> handlers .xferinfo );
2848
2867
_php_curl_free_callback (ch -> handlers .fnmatch );
2849
2868
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
@@ -2911,10 +2930,8 @@ static void _php_curl_reset_handlers(php_curl *ch)
2911
2930
ZVAL_UNDEF (& ch -> handlers .std_err );
2912
2931
}
2913
2932
2914
- if (ch -> handlers .progress ) {
2915
- zval_ptr_dtor (& ch -> handlers .progress -> func_name );
2916
- efree (ch -> handlers .progress );
2917
- ch -> handlers .progress = NULL ;
2933
+ if (ZEND_FCC_INITIALIZED (ch -> handlers .progress )) {
2934
+ zend_fcc_dtor (& ch -> handlers .progress );
2918
2935
}
2919
2936
2920
2937
if (ch -> handlers .xferinfo ) {
0 commit comments