diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 8aec63ca501a..c031790968ea 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -813,6 +813,10 @@ static int curl_ssh_hostkeyfunction(void *clientp, int keytype, const char *key, php_curl *ch = (php_curl *)clientp; int rval = CURLKHMATCH_MISMATCH; /* cancel connection in case of an exception */ + if (!ZEND_FCC_INITIALIZED(ch->handlers.sshhostkey)) { + return rval; + } + #if PHP_CURL_DEBUG fprintf(stderr, "curl_ssh_hostkeyfunction() called\n"); fprintf(stderr, "clientp = %x, keytype = %d, key = %s, keylen = %zu\n", clientp, keytype, key, keylen); @@ -1284,8 +1288,11 @@ static void php_curl_copy_fcc_with_option(php_curl *ch, CURLoption option, zend_ { if (ZEND_FCC_INITIALIZED(*source_fcc)) { zend_fcc_dup(target_fcc, source_fcc); - curl_easy_setopt(ch->cp, option, (void *) ch); } + + /* The callback data (i.e. pointer to the curl handle) stays even if a user callback + * is reset to NULL. Ensure the data pointer always points to the new handle. */ + curl_easy_setopt(ch->cp, option, (void *) ch); } void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) @@ -1325,7 +1332,6 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); - curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *) ch); php_curl_copy_fcc_with_option(ch, CURLOPT_PROGRESSDATA, &ch->handlers.progress, &source->handlers.progress); php_curl_copy_fcc_with_option(ch, CURLOPT_XFERINFODATA, &ch->handlers.xferinfo, &source->handlers.xferinfo); diff --git a/ext/curl/tests/curl_copy_handle_progress_null_uaf.phpt b/ext/curl/tests/curl_copy_handle_progress_null_uaf.phpt new file mode 100644 index 000000000000..1f362f472f98 --- /dev/null +++ b/ext/curl/tests/curl_copy_handle_progress_null_uaf.phpt @@ -0,0 +1,27 @@ +--TEST-- +Cloning a curl handle whose CURLOPT_PROGRESSFUNCTION was reset to null must not reference the source handle +--EXTENSIONS-- +curl +--FILE-- + 0); +curl_setopt($ch1, CURLOPT_PROGRESSFUNCTION, null); + +$ch2 = clone $ch1; +unset($ch1); + +var_dump(curl_exec($ch2)); +?> +--CLEAN-- + +--EXPECT-- +string(5) "Test."