]> granicus.if.org Git - php/commitdiff
MFH: fix bug #33222 (segfault when CURL handle is closed in a callback).
authorAntony Dovgal <tony2001@php.net>
Thu, 2 Jun 2005 21:04:43 +0000 (21:04 +0000)
committerAntony Dovgal <tony2001@php.net>
Thu, 2 Jun 2005 21:04:43 +0000 (21:04 +0000)
fix segfaults when CURL callback functions throw exception.

NEWS
ext/curl/interface.c
ext/curl/php_curl.h

diff --git a/NEWS b/NEWS
index 7b68487337ba70f3f7bfe2c089d344be35454455..d090098934fafa35f4bf78801584fee8d78eea7c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ PHP                                                                        NEWS
   of type (MEDIUM|LONG)BLOB/(MEDIUM|LONG)TEXT. (Andrey)
 - Fixed memory corruption in ImageTTFText() with 64bit systems. (Andrey)
 - Fixed memory corruption in stristr(). (Derick)
+- Fixed segfaults when CURL callback functions throw exception. (Tony)
+- Fixed bug #33222 (segfault when CURL handle is closed in a callback). (Tony)
 - Fixed bug #33214 (odbc_next_result does not signal SQL errors with 
   2-statement SQL batches). (rich at kastle dot com, Tony)
 - Fixed bug #33210 (relax jpeg recursive loop protection). (Ilia)
index 7d9b1cc9f1b509a6d1e8855bfe68443833ea9853..f678e9436411c3b6a215f48c1fa7dceb54867f22 100644 (file)
@@ -484,20 +484,22 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
                        fci.no_separation = 0;
                        fci.symbol_table = NULL;
 
+                       ch->in_callback = 1;
                        error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
+                       ch->in_callback = 0;
                        if (error == FAILURE) {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION");
                                length = -1;
-                       } else {
+                       } else if (retval_ptr) {
                                if (Z_TYPE_P(retval_ptr) != IS_LONG) {
                                        convert_to_long_ex(&retval_ptr);
                                }
                                length = Z_LVAL_P(retval_ptr);
+                               zval_ptr_dtor(&retval_ptr);
                        }
 
                        zval_ptr_dtor(argv[0]);
                        zval_ptr_dtor(argv[1]);
-                       zval_ptr_dtor(&retval_ptr);
                        break;
                }
        }
@@ -554,20 +556,22 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
                        fci.no_separation = 0;
                        fci.symbol_table = NULL;
 
+                       ch->in_callback = 1;
                        error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
+                       ch->in_callback = 0;
                        if (error == FAILURE) {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_READFUNCTION"); 
-                       } else {
+                       } else if (retval_ptr) {
                                if (Z_TYPE_P(retval_ptr) == IS_STRING) {
                                        length = MIN(size * nmemb, Z_STRLEN_P(retval_ptr));
                                        memcpy(data, Z_STRVAL_P(retval_ptr), length);
                                }
+                               zval_ptr_dtor(&retval_ptr);
                        }
 
                        zval_ptr_dtor(argv[0]);
                        zval_ptr_dtor(argv[1]);
                        zval_ptr_dtor(argv[2]);
-                       zval_ptr_dtor(&retval_ptr);
                        break;
                }
        }
@@ -625,19 +629,21 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx
                        fci.params = argv;
                        fci.no_separation = 0;
 
+                       ch->in_callback = 1;
                        error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
+                       ch->in_callback = 0;
                        if (error == FAILURE) {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION");
                                length = -1;
-                       } else {
+                       } else if (retval_ptr) {
                                if (Z_TYPE_P(retval_ptr) != IS_LONG) {
                                        convert_to_long_ex(&retval_ptr);
                                }
                                length = Z_LVAL_P(retval_ptr);
+                               zval_ptr_dtor(&retval_ptr);
                        }
                        zval_ptr_dtor(argv[0]);
                        zval_ptr_dtor(argv[1]);
-                       zval_ptr_dtor(&retval_ptr);
                        break;
                }
 
@@ -773,6 +779,8 @@ static void alloc_curl_handle(php_curl **ch)
        (*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
        (*ch)->handlers->read         = ecalloc(1, sizeof(php_curl_read));
 
+       (*ch)->in_callback = 0;
+       
        memset(&(*ch)->err, 0, sizeof((*ch)->err));
        
        zend_llist_init(&(*ch)->to_free.str,   sizeof(char *),            (void(*)(void *)) curl_free_string, 0);
@@ -1468,6 +1476,12 @@ PHP_FUNCTION(curl_close)
        }
 
        ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
+
+       if (ch->in_callback) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to close CURL handle from a callback");
+               return;
+       }
+       
        if (ch->uses) { 
                ch->uses--;
        } else {
index d2a14c43b7ec629f763748a817241d3c1187989b..2f8ba6111f893350798a995e823e4e8c5c89ab0e 100644 (file)
@@ -121,6 +121,7 @@ typedef struct {
        php_curl_handlers       *handlers;
        long                     id;
        unsigned int             uses;
+       zend_bool                in_callback;
 } php_curl;
 
 typedef struct {