@@ -487,8 +487,8 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
487
487
zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .write_header -> stream );
488
488
}
489
489
490
- if (curl -> handlers .progress ) {
491
- zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .progress -> func_name );
490
+ if (ZEND_FCC_INITIALIZED ( curl -> handlers .progress ) ) {
491
+ zend_get_gc_buffer_add_fcc (gc_buffer , & curl -> handlers .progress );
492
492
}
493
493
494
494
if (curl -> handlers .xferinfo ) {
@@ -664,46 +664,36 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string)
664
664
static size_t curl_progress (void * clientp , double dltotal , double dlnow , double ultotal , double ulnow )
665
665
{
666
666
php_curl * ch = (php_curl * )clientp ;
667
- php_curl_callback * t = ch -> handlers .progress ;
668
667
size_t rval = 0 ;
669
668
670
669
#if PHP_CURL_DEBUG
671
670
fprintf (stderr , "curl_progress() called\n" );
672
671
fprintf (stderr , "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n" , clientp , dltotal , dlnow , ultotal , ulnow );
673
672
#endif
674
673
675
- zval argv [5 ];
674
+ zval args [5 ];
676
675
zval retval ;
677
- zend_result error ;
678
- zend_fcall_info fci ;
679
676
680
677
GC_ADDREF (& ch -> std );
681
- ZVAL_OBJ (& argv [0 ], & ch -> std );
682
- ZVAL_LONG (& argv [1 ], (zend_long )dltotal );
683
- ZVAL_LONG (& argv [2 ], (zend_long )dlnow );
684
- ZVAL_LONG (& argv [3 ], (zend_long )ultotal );
685
- ZVAL_LONG (& argv [4 ], (zend_long )ulnow );
686
-
687
- fci .size = sizeof (fci );
688
- ZVAL_COPY_VALUE (& fci .function_name , & t -> func_name );
689
- fci .object = NULL ;
690
- fci .retval = & retval ;
691
- fci .param_count = 5 ;
692
- fci .params = argv ;
693
- fci .named_params = NULL ;
694
-
695
- ch -> in_callback = 1 ;
696
- error = zend_call_function (& fci , & t -> fci_cache );
697
- ch -> in_callback = 0 ;
698
- if (error == FAILURE ) {
699
- php_error_docref (NULL , E_WARNING , "Cannot call the CURLOPT_PROGRESSFUNCTION" );
700
- } else if (!Z_ISUNDEF (retval )) {
701
- _php_curl_verify_handlers (ch , /* reporterror */ true);
702
- if (0 != zval_get_long (& retval )) {
703
- rval = 1 ;
704
- }
705
- }
706
- zval_ptr_dtor (& argv [0 ]);
678
+ ZVAL_OBJ (& args [0 ], & ch -> std );
679
+ ZVAL_LONG (& args [1 ], (zend_long )dltotal );
680
+ ZVAL_LONG (& args [2 ], (zend_long )dlnow );
681
+ ZVAL_LONG (& args [3 ], (zend_long )ultotal );
682
+ ZVAL_LONG (& args [4 ], (zend_long )ulnow );
683
+
684
+ ch -> in_callback = true;
685
+ zend_call_known_fcc (& ch -> handlers .progress , & retval , /* param_count */ 5 , args , /* named_params */ NULL );
686
+ ch -> in_callback = false;
687
+
688
+ if (!Z_ISUNDEF (retval )) {
689
+ _php_curl_verify_handlers (ch , /* reporterror */ true);
690
+ /* TODO Check callback returns an int or something castable to in */
691
+ if (0 != zval_get_long (& retval )) {
692
+ rval = 1 ;
693
+ }
694
+ }
695
+
696
+ zval_ptr_dtor (& args [0 ]);
707
697
return rval ;
708
698
}
709
699
/* }}} */
@@ -1054,7 +1044,7 @@ void init_curl_handle(php_curl *ch)
1054
1044
ch -> handlers .write = ecalloc (1 , sizeof (php_curl_write ));
1055
1045
ch -> handlers .write_header = ecalloc (1 , sizeof (php_curl_write ));
1056
1046
ch -> handlers .read = ecalloc (1 , sizeof (php_curl_read ));
1057
- ch -> handlers .progress = NULL ;
1047
+ ch -> handlers .progress = empty_fcall_info_cache ;
1058
1048
ch -> handlers .xferinfo = NULL ;
1059
1049
ch -> handlers .fnmatch = NULL ;
1060
1050
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
@@ -1191,6 +1181,14 @@ static void _php_copy_callback(php_curl *ch, php_curl_callback **new_callback, p
1191
1181
}
1192
1182
}
1193
1183
1184
+ 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 )
1185
+ {
1186
+ if (ZEND_FCC_INITIALIZED (* source_fcc )) {
1187
+ zend_fcc_dup (target_fcc , source_fcc );
1188
+ curl_easy_setopt (ch -> cp , option , (void * ) ch );
1189
+ }
1190
+ }
1191
+
1194
1192
void _php_setup_easy_copy_handlers (php_curl * ch , php_curl * source )
1195
1193
{
1196
1194
if (!Z_ISUNDEF (source -> handlers .write -> stream )) {
@@ -1230,7 +1228,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
1230
1228
curl_easy_setopt (ch -> cp , CURLOPT_WRITEHEADER , (void * ) ch );
1231
1229
curl_easy_setopt (ch -> cp , CURLOPT_DEBUGDATA , (void * ) ch );
1232
1230
1233
- _php_copy_callback (ch , & ch -> handlers .progress , source -> handlers .progress , CURLOPT_PROGRESSDATA );
1231
+ php_curl_copy_fcc_with_option (ch , CURLOPT_PROGRESSDATA , & ch -> handlers .progress , & source -> handlers .progress );
1234
1232
_php_copy_callback (ch , & ch -> handlers .xferinfo , source -> handlers .xferinfo , CURLOPT_XFERINFODATA );
1235
1233
_php_copy_callback (ch , & ch -> handlers .fnmatch , source -> handlers .fnmatch , CURLOPT_FNMATCH_DATA );
1236
1234
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
@@ -1535,6 +1533,25 @@ PHP_FUNCTION(curl_copy_handle)
1535
1533
}
1536
1534
/* }}} */
1537
1535
1536
+ static bool php_curl_set_callable_handler (zend_fcall_info_cache * const handler_fcc , zval * callable , bool is_array_config , const char * option_name )
1537
+ {
1538
+ if (ZEND_FCC_INITIALIZED (* handler_fcc )) {
1539
+ zend_fcc_dtor (handler_fcc );
1540
+ handler_fcc -> function_handler = NULL ;
1541
+ }
1542
+
1543
+ char * error = NULL ;
1544
+ if (UNEXPECTED (!zend_is_callable_ex (callable , /* object */ NULL , /* check_flags */ 0 , /* callable_name */ NULL , handler_fcc , /* error */ & error ))) {
1545
+ if (!EG (exception )) {
1546
+ zend_argument_type_error (2 + !is_array_config , "must be a valid callback for option %s, %s" , option_name , error );
1547
+ }
1548
+ efree (error );
1549
+ return false;
1550
+ }
1551
+ zend_fcc_addref (handler_fcc );
1552
+ return true;
1553
+ }
1554
+
1538
1555
static zend_result _php_curl_setopt (php_curl * ch , zend_long option , zval * zvalue , bool is_array_config ) /* {{{ */
1539
1556
{
1540
1557
CURLcode error = CURLE_OK ;
@@ -2079,17 +2096,17 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
2079
2096
}
2080
2097
break ;
2081
2098
2082
- case CURLOPT_PROGRESSFUNCTION :
2099
+ case CURLOPT_PROGRESSFUNCTION : {
2100
+ /* Check value is actually a callable and set it */
2101
+ const char option_name [] = "CURLOPT_PROGRESSFUNCTION" ;
2102
+ bool result = php_curl_set_callable_handler (& ch -> handlers .progress , zvalue , is_array_config , option_name );
2103
+ if (!result ) {
2104
+ return FAILURE ;
2105
+ }
2083
2106
curl_easy_setopt (ch -> cp , CURLOPT_PROGRESSFUNCTION , curl_progress );
2084
2107
curl_easy_setopt (ch -> cp , CURLOPT_PROGRESSDATA , ch );
2085
- if (ch -> handlers .progress == NULL ) {
2086
- ch -> handlers .progress = ecalloc (1 , sizeof (php_curl_callback ));
2087
- } else if (!Z_ISUNDEF (ch -> handlers .progress -> func_name )) {
2088
- zval_ptr_dtor (& ch -> handlers .progress -> func_name );
2089
- ch -> handlers .progress -> fci_cache = empty_fcall_info_cache ;
2090
- }
2091
- ZVAL_COPY (& ch -> handlers .progress -> func_name , zvalue );
2092
2108
break ;
2109
+ }
2093
2110
2094
2111
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2095
2112
case CURLOPT_SSH_HOSTKEYFUNCTION :
@@ -2780,7 +2797,9 @@ static void curl_free_obj(zend_object *object)
2780
2797
efree (ch -> handlers .write_header );
2781
2798
efree (ch -> handlers .read );
2782
2799
2783
- _php_curl_free_callback (ch -> handlers .progress );
2800
+ if (ZEND_FCC_INITIALIZED (ch -> handlers .progress )) {
2801
+ zend_fcc_dtor (& ch -> handlers .progress );
2802
+ }
2784
2803
_php_curl_free_callback (ch -> handlers .xferinfo );
2785
2804
_php_curl_free_callback (ch -> handlers .fnmatch );
2786
2805
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
@@ -2848,10 +2867,8 @@ static void _php_curl_reset_handlers(php_curl *ch)
2848
2867
ZVAL_UNDEF (& ch -> handlers .std_err );
2849
2868
}
2850
2869
2851
- if (ch -> handlers .progress ) {
2852
- zval_ptr_dtor (& ch -> handlers .progress -> func_name );
2853
- efree (ch -> handlers .progress );
2854
- ch -> handlers .progress = NULL ;
2870
+ if (ZEND_FCC_INITIALIZED (ch -> handlers .progress )) {
2871
+ zend_fcc_dtor (& ch -> handlers .progress );
2855
2872
}
2856
2873
2857
2874
if (ch -> handlers .xferinfo ) {
0 commit comments