From 1a733ccbdda682fe9899957f43e411e215639e63 Mon Sep 17 00:00:00 2001 From: Antony Dovgal Date: Thu, 2 Jun 2005 21:05:06 +0000 Subject: [PATCH] MFH: fix bug #33222 (segfault when CURL handle is closed in a callback). --- NEWS | 1 + ext/curl/curl.c | 18 ++++++++++++++++-- ext/curl/php_curl.h | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 00976483c3..1e7763d9cb 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP 4 NEWS - Changed sha1_file() and md5_file() functions to use streams instead of low level IO. (Uwe) - Fixed memory corruption in stristr(). (Derick) +- 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) diff --git a/ext/curl/curl.c b/ext/curl/curl.c index 9a2c39aacc..27192695f7 100644 --- a/ext/curl/curl.c +++ b/ext/curl/curl.c @@ -436,10 +436,12 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) zend_list_addref(ch->id); ZVAL_STRINGL(argv[1], data, length, 1); + ch->in_callback = 1; error = call_user_function(EG(function_table), NULL, t->func, retval, 2, argv TSRMLS_CC); + ch->in_callback = 0; if (error == FAILURE) { php_error(E_WARNING, "%s(): Couldn't call the CURLOPT_WRITEFUNCTION", get_active_function_name(TSRMLS_C)); @@ -495,10 +497,12 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) zend_list_addref(t->fd); ZVAL_LONG(argv[2], (int) size * nmemb); + ch->in_callback = 1; error = call_user_function(EG(function_table), NULL, t->func, retval, 3, argv TSRMLS_CC); + ch->in_callback = 0; if (error == FAILURE) { php_error(E_WARNING, "%s(): Cannot call the CURLOPT_READFUNCTION", get_active_function_name(TSRMLS_C)); @@ -553,10 +557,12 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx zend_list_addref(ch->id); ZVAL_STRINGL(argv[1], data, length, 1); + ch->in_callback = 1; error = call_user_function(EG(function_table), NULL, t->func, retval, 2, argv TSRMLS_CC); + ch->in_callback = 0; if (error == FAILURE) { php_error(E_WARNING, "%s(): Couldn't call the CURLOPT_HEADERFUNCTION", get_active_function_name(TSRMLS_C)); @@ -606,10 +612,12 @@ static size_t curl_passwd(void *ctx, char *prompt, char *buf, int buflen) ZVAL_STRING(argv[1], prompt, 1); ZVAL_LONG(argv[2], buflen); + ch->in_callback = 1; error = call_user_function(EG(function_table), NULL, func, retval, 2, argv TSRMLS_CC); + ch->in_callback = 0; if (error == FAILURE) { php_error(E_WARNING, "%s(): Couldn't call the CURLOPT_PASSWDFUNCTION", get_active_function_name(TSRMLS_C)); } else if (Z_TYPE_P(retval) == IS_STRING) { @@ -680,7 +688,9 @@ 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)); memset(&(*ch)->err, 0, sizeof((*ch)->err)); - + + (*ch)->in_callback = 0; + zend_llist_init(&(*ch)->to_free.str, sizeof(char *), (void(*)(void *)) curl_free_string, 0); zend_llist_init(&(*ch)->to_free.slist, sizeof(struct curl_slist), @@ -1337,7 +1347,11 @@ PHP_FUNCTION(curl_close) WRONG_PARAM_COUNT; } 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; + } zend_list_delete(Z_LVAL_PP(zid)); } /* }}} */ diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h index a78f643333..be49f24c6b 100644 --- a/ext/curl/php_curl.h +++ b/ext/curl/php_curl.h @@ -93,6 +93,7 @@ typedef struct { struct _php_curl_free to_free; long id; unsigned int uses; + zend_bool in_callback; } php_curl; /* streams support */ -- 2.40.0