Description
Description
The following code:
$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:
pycurl/pycurl@88d2bff
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