diff --git a/ext/curl/interface.c b/ext/curl/interface.c index d5d20d825652..f740a9feac10 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -554,6 +554,8 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) _php_curl_verify_handlers(ch, /* reporterror */ true); /* TODO Check callback returns an int or something castable to int */ length = php_curl_get_long(&retval); + } else if (EG(exception)) { + length = -1; } zval_ptr_dtor(&argv[0]); @@ -603,14 +605,14 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string) static int curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { php_curl *ch = (php_curl *)clientp; - int rval = 0; + int rval = 1; // error #if PHP_CURL_DEBUG fprintf(stderr, "curl_progress() called\n"); fprintf(stderr, "clientp = %p, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); #endif if (!ZEND_FCC_INITIALIZED(ch->handlers.progress)) { - return rval; + return 0; // ok } zval args[5]; @@ -630,8 +632,8 @@ static int curl_progress(void *clientp, double dltotal, double dlnow, double ult if (!Z_ISUNDEF(retval)) { _php_curl_verify_handlers(ch, /* reporterror */ true); /* TODO Check callback returns an int or something castable to int */ - if (0 != php_curl_get_long(&retval)) { - rval = 1; + if (0 == php_curl_get_long(&retval)) { + rval = 0; // ok } } @@ -644,14 +646,14 @@ static int curl_progress(void *clientp, double dltotal, double dlnow, double ult static int curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { php_curl *ch = (php_curl *)clientp; - int rval = 0; + int rval = 1; // error #if PHP_CURL_DEBUG fprintf(stderr, "curl_xferinfo() called\n"); fprintf(stderr, "clientp = %p, dltotal = %ld, dlnow = %ld, ultotal = %ld, ulnow = %ld\n", clientp, dltotal, dlnow, ultotal, ulnow); #endif - if (!ZEND_FCC_INITIALIZED(ch->handlers.xferinfo)) { - return rval; + if (UNEXPECTED(!ZEND_FCC_INITIALIZED(ch->handlers.xferinfo))) { + return 0; // ok } zval argv[5]; @@ -671,8 +673,8 @@ static int curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, cu if (!Z_ISUNDEF(retval)) { _php_curl_verify_handlers(ch, /* reporterror */ true); /* TODO Check callback returns an int or something castable to int */ - if (0 != php_curl_get_long(&retval)) { - rval = 1; + if (0 == php_curl_get_long(&retval)) { + rval = 0; // ok } } @@ -685,13 +687,13 @@ static int curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, cu static int curl_prereqfunction(void *clientp, char *conn_primary_ip, char *conn_local_ip, int conn_primary_port, int conn_local_port) { php_curl *ch = (php_curl *)clientp; - int rval = CURL_PREREQFUNC_OK; + int rval = CURL_PREREQFUNC_ABORT; // when CURLOPT_PREREQFUNCTION is set to null, curl_prereqfunction still // gets called. Return CURL_PREREQFUNC_OK immediately in this case to avoid // zend_call_known_fcc() with an uninitialized FCC. - if (!ZEND_FCC_INITIALIZED(ch->handlers.prereq)) { - return rval; + if (UNEXPECTED(!ZEND_FCC_INITIALIZED(ch->handlers.prereq))) { + return CURL_PREREQFUNC_OK; } #if PHP_CURL_DEBUG @@ -822,6 +824,8 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) } // TODO Do type error if invalid type? zval_ptr_dtor(&retval); + } else if (EG(exception)) { + length = CURL_READFUNC_ABORT; } zval_ptr_dtor(&argv[0]); @@ -916,6 +920,8 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx // TODO: Check for valid int type for return value _php_curl_verify_handlers(ch, /* reporterror */ true); length = php_curl_get_long(&retval); + } else if (EG(exception)) { + length = -1; } zval_ptr_dtor(&argv[0]); zval_ptr_dtor(&argv[1]); diff --git a/ext/curl/tests/curl_headerfunction_throws_abort.phpt b/ext/curl/tests/curl_headerfunction_throws_abort.phpt new file mode 100644 index 000000000000..9a69c966f144 --- /dev/null +++ b/ext/curl/tests/curl_headerfunction_throws_abort.phpt @@ -0,0 +1,45 @@ +--TEST-- +CURLOPT_HEADERFUNCTION aborts transfer when callback throws +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +var_dump(curl_errno($ch) === CURLE_WRITE_ERROR); + +echo "Test: header function is null\n"; +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_HEADERFUNCTION, null); +curl_exec($ch); +var_dump(curl_errno($ch) === CURLE_OK); + +?> +--EXPECTF-- +Test: header function throws exception +header exception +bool(true) +Test: header function is null +bool(true) diff --git a/ext/curl/tests/curl_prereqfunction_throws_abort.phpt b/ext/curl/tests/curl_prereqfunction_throws_abort.phpt new file mode 100644 index 000000000000..7e8ccbf94f53 --- /dev/null +++ b/ext/curl/tests/curl_prereqfunction_throws_abort.phpt @@ -0,0 +1,35 @@ +--TEST-- +CURLOPT_PREREQFUNCTION aborts transfer when callback throws +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +var_dump(curl_errno($ch) === CURLE_ABORTED_BY_CALLBACK); + +?> +--EXPECTF-- +prereq exception +bool(true) diff --git a/ext/curl/tests/curl_progressfunction_throws_abort.phpt b/ext/curl/tests/curl_progressfunction_throws_abort.phpt new file mode 100644 index 000000000000..55e0f76cb61f --- /dev/null +++ b/ext/curl/tests/curl_progressfunction_throws_abort.phpt @@ -0,0 +1,46 @@ +--TEST-- +CURLOPT_PROGRESSFUNCTION aborts transfer when callback throws +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +var_dump(curl_errno($ch) === CURLE_ABORTED_BY_CALLBACK); + +echo "Test: progress function is null\n"; +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, null); +curl_exec($ch); +var_dump(curl_errno($ch) === CURLE_OK); + +?> +--EXPECTF-- +Test: progress function throws exception +info exception +bool(true) +Test: progress function is null +bool(true) diff --git a/ext/curl/tests/curl_readfunction_throws_abort.phpt b/ext/curl/tests/curl_readfunction_throws_abort.phpt new file mode 100644 index 000000000000..a030f8c4f41e --- /dev/null +++ b/ext/curl/tests/curl_readfunction_throws_abort.phpt @@ -0,0 +1,48 @@ +--TEST-- +CURLOPT_READFUNCTION aborts transfer when callback throws +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +var_dump(curl_errno($ch) === CURLE_ABORTED_BY_CALLBACK); + +echo "Test: read function is null\n"; +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_READFUNCTION, null); +curl_exec($ch); +var_dump(curl_errno($ch) === CURLE_OK); + +?> +--EXPECTF-- +Test: read function throws exception +read exception +bool(true) +Test: read function is null +bool(true) diff --git a/ext/curl/tests/curl_writefunction_throws_abort.phpt b/ext/curl/tests/curl_writefunction_throws_abort.phpt new file mode 100644 index 000000000000..3da2fe8107b4 --- /dev/null +++ b/ext/curl/tests/curl_writefunction_throws_abort.phpt @@ -0,0 +1,45 @@ +--TEST-- +CURLOPT_WRITEFUNCTION aborts transfer when callback throws +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +var_dump(curl_errno($ch) === CURLE_WRITE_ERROR); + +echo "Test: write function is null\n"; +curl_setopt($ch, CURLOPT_WRITEFUNCTION, null); +curl_exec($ch); +var_dump(curl_errno($ch) === CURLE_OK); + +?> +--EXPECTF-- +Test: write function throws exception +write exception +bool(true) +Test: write function is null +Hello World! +Hello World!bool(true) diff --git a/ext/curl/tests/curl_xferinfofunction_throws_abort.phpt b/ext/curl/tests/curl_xferinfofunction_throws_abort.phpt new file mode 100644 index 000000000000..fbc28f07ee96 --- /dev/null +++ b/ext/curl/tests/curl_xferinfofunction_throws_abort.phpt @@ -0,0 +1,46 @@ +--TEST-- +CURLOPT_XFERINFOFUNCTION aborts transfer when callback throws +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +var_dump(curl_errno($ch) === CURLE_ABORTED_BY_CALLBACK); + +echo "Test: xfer info function is null\n"; +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_XFERINFOFUNCTION, null); +curl_exec($ch); +var_dump(curl_errno($ch) === CURLE_OK); + +?> +--EXPECTF-- +Test: xfer info function throws exception +info exception +bool(true) +Test: xfer info function is null +bool(true)