[php-src] Issue #14915: curl_error() is missing a fallback as expected and documented in curl manual
| From: | arekm | Date: | Thu, 11 Jul 2024 08:57:42 +0000 |
| Subject: | [php-src] Issue #14915: curl_error() is missing a fallback as expected and documented in curl manual | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-247272@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/14915
Author: arekm
### Description
The following code:
```php
$session = curl_init();
curl_setopt($session, CURLOPT_URL, "https://someserver/cmd.php");
curl_setopt($session, CURLOPT_USERPWD, "user:pass");
curl_setopt($session, CURLOPT_SSL_VERIFYHOST, 1);
curl_setopt($session, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($session, CURLOPT_TIMEOUT, 70);
curl_setopt($session, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($session, CURLOPT_HTTPHEADER, array('Content-type: application/json',
'Expect:'));
curl_setopt($session, CURLOPT_FAILONERROR, 1);
curl_setopt($session, CURLOPT_POST, 1);
curl_setopt($session, CURLOPT_POSTFIELDS,
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
$response = curl_exec($session);
echo "curl_error: " . curl_error($session) . ", curl_errno: " .
curl_errno($session) . "\n";
```
Resulted in this output:
```
$ php83 --version
PHP 8.3.9 (cli) (built: Jul 7 2024 09:48:02) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.9, Copyright (c) Zend Technologies
$ php83 test.php
curl_error: , curl_errno: 16
```
But I expected this output instead:
```
curl_error: Error in the HTTP2 framing layer, curl_errno: 16
```
since that's what curl cmdline returns
```
$ sh test.sh
curl: (16) Error in the HTTP2 framing layer
```
Server is some old lighttpd 1.4.73 which most likely mishandles HTTP/2 and allows me to reproduce
such error but unfortunately it's not reachable over internet.
But I have an explanation on what's wrong.
php is currently doing
```
PHP_FUNCTION(curl_error)
{
[...]
if (ch->err.no) {
ch->err.str[CURL_ERROR_SIZE] = 0;
RETURN_STRING(ch->err.str);
} else {
RETURN_EMPTY_STRING();
}
}
```
and err.str is set
```
curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str);
```
**The problem**
curl documentation says that errobuffer sometimes can be not filled with error and then you are
expected to fallback to curl_easy_strerror(). See example C code in manual: https://curl.se/libcurl/c/CURLOPT_ERRORBUFFER.html
That's what curl cmdline does:
https://github.com/curl/curl/blob/curl-8_8_0/src/tool_operate.c#L402-L403
(msg is their CURLOPT_ERRORBUFFER buffer)
Similar bug existed in pycurl until got fixed in latest release:
https://github.com/pycurl/pycurl/commit/88d2bfff565bf62504a812beb7d07f7f553bdcfa
**Solution**
Solution is to return curl_easy_strerror() information instead of RETURN_EMPTY_STRING()
### PHP Version
PHP 8.3.9 (all existing php versions including git master)
### Operating System
_No response_