diff options
author | Stanislav Malyshev <stas@php.net> | 2015-04-04 15:58:27 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2015-04-11 16:53:21 -0700 |
commit | 0ea75af9be8a40836951fc89f723dd5390b8b46f (patch) | |
tree | 9ad6e95477f81fa16840819876f381223a5770d1 | |
parent | 809610f5ea38a83b284e1125d1fff129bdd615e7 (diff) | |
download | php-git-0ea75af9be8a40836951fc89f723dd5390b8b46f.tar.gz |
Fixed bug #69316 (Use-after-free in php_curl related to CURLOPT_FILE/_INFILE/_WRITEHEADER)
-rw-r--r-- | ext/curl/interface.c | 4 | ||||
-rw-r--r-- | ext/curl/tests/bug69316.phpt | 41 |
2 files changed, 45 insertions, 0 deletions
diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 0423f71f9a..7f8f276791 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1051,6 +1051,7 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION"); length = -1; } else if (retval_ptr) { + _php_curl_verify_handlers(ch, 1 TSRMLS_CC); if (Z_TYPE_P(retval_ptr) != IS_LONG) { convert_to_long_ex(&retval_ptr); } @@ -1124,6 +1125,7 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double if (error == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION"); } else if (retval_ptr) { + _php_curl_verify_handlers(ch, 1 TSRMLS_CC); if (Z_TYPE_P(retval_ptr) != IS_LONG) { convert_to_long_ex(&retval_ptr); } @@ -1200,6 +1202,7 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) length = CURL_READFUNC_ABORT; #endif } else if (retval_ptr) { + _php_curl_verify_handlers(ch, 1 TSRMLS_CC); if (Z_TYPE_P(retval_ptr) == IS_STRING) { length = MIN((int) (size * nmemb), Z_STRLEN_P(retval_ptr)); memcpy(data, Z_STRVAL_P(retval_ptr), length); @@ -1274,6 +1277,7 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION"); length = -1; } else if (retval_ptr) { + _php_curl_verify_handlers(ch, 1 TSRMLS_CC); if (Z_TYPE_P(retval_ptr) != IS_LONG) { convert_to_long_ex(&retval_ptr); } diff --git a/ext/curl/tests/bug69316.phpt b/ext/curl/tests/bug69316.phpt new file mode 100644 index 0000000000..2a88eb2bc9 --- /dev/null +++ b/ext/curl/tests/bug69316.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug #69316: Use-after-free in php_curl related to CURLOPT_FILE/_INFILE/_WRITEHEADER +--SKIPIF-- +<?php +if (!extension_loaded("curl")) exit("skip curl extension not loaded"); +if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined"); +?> +--FILE-- +<?php + function hdr_callback($ch, $data) { + // close the stream, causing the FILE structure to be free()'d + if($GLOBALS['f_file']) { + fclose($GLOBALS['f_file']); $GLOBALS['f_file'] = 0; + + // cause an allocation of approx the same size as a FILE structure, size varies a bit depending on platform/libc + $FILE_size = (PHP_INT_SIZE == 4 ? 0x160 : 0x238); + curl_setopt($ch, CURLOPT_COOKIE, str_repeat("a", $FILE_size - 1)); + } + return strlen($data); + } + $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER'); + + $temp_file = dirname(__FILE__) . '/body.tmp'; + $url = "{$host}/get.php?test=getpost"; + $ch = curl_init(); + $f_file = fopen($temp_file, "w") or die("failed to open file\n"); + curl_setopt($ch, CURLOPT_BUFFERSIZE, 10); + curl_setopt($ch, CURLOPT_HEADERFUNCTION, "hdr_callback"); + curl_setopt($ch, CURLOPT_FILE, $f_file); + curl_setopt($ch, CURLOPT_URL, $url); + curl_exec($ch); + curl_close($ch); +?> +===DONE=== +--CLEAN-- +<?php +unlink(dirname(__FILE__) . '/body.tmp'); +?> +--EXPECTF-- +Warning: curl_exec(): CURLOPT_FILE resource has gone away, resetting to default in %s on line %d +===DONE=== |