summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2015-04-04 15:58:27 -0700
committerStanislav Malyshev <stas@php.net>2015-04-11 16:53:21 -0700
commit0ea75af9be8a40836951fc89f723dd5390b8b46f (patch)
tree9ad6e95477f81fa16840819876f381223a5770d1
parent809610f5ea38a83b284e1125d1fff129bdd615e7 (diff)
downloadphp-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.c4
-rw-r--r--ext/curl/tests/bug69316.phpt41
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===