From a3bf80a74119956a1ef4f68eda941ad2ab23934a Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 17 Aug 2026 10:43:43 +0000 Subject: [PATCH 01/11] ext/curl: test curl option CURLOPT_WRITEHEADER --- .../curl_setopt_CURLOPT_WRITEHEADER.phpt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt diff --git a/ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt b/ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt new file mode 100644 index 000000000000..06a80f86a3b1 --- /dev/null +++ b/ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt @@ -0,0 +1,36 @@ +--TEST-- +Curl option CURLOPT_WRITEHEADER +--DESCRIPTION-- +Test writing HTTP response headers to a file using CURLOPT_WRITEHEADER. +--EXTENSIONS-- +curl +--FILE-- + +--EXPECTF-- +HTTP/1.1 200 OK +Host: localhost:%d +Date: %s +Connection: close +X-Powered-By: PHP/%s +Content-Type: text/plain;charset=utf-8 From 7fd26e145f9c5c8f1accd2a155103bcf69f2f619 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 17 Aug 2026 11:50:42 +0000 Subject: [PATCH 02/11] ext/curl: add test for CURLOPT_MAXFILESIZE_LARGE --- ...curl_setopt_CURLOPT_MAXFILESIZE_LARGE.phpt | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 ext/curl/tests/curl_setopt_CURLOPT_MAXFILESIZE_LARGE.phpt diff --git a/ext/curl/tests/curl_setopt_CURLOPT_MAXFILESIZE_LARGE.phpt b/ext/curl/tests/curl_setopt_CURLOPT_MAXFILESIZE_LARGE.phpt new file mode 100644 index 000000000000..72064be824f0 --- /dev/null +++ b/ext/curl/tests/curl_setopt_CURLOPT_MAXFILESIZE_LARGE.phpt @@ -0,0 +1,54 @@ +--TEST-- +Curl option CURLOPT_MAXFILESIZE_LARGE +--DESCRIPTION-- +Test CURLOPT_MAXFILESIZE_LARGE with values that exceed, do not exceed, and +disable the limit, as well as a negative value that triggers an error. +--EXTENSIONS-- +curl +--FILE-- + +--EXPECTF-- +Body larger than CURLOPT_MAXFILESIZE_LARGE +bool(false) +bool(true) +Body smaller than CURLOPT_MAXFILESIZE_LARGE +int(25) +Limit disabled by setting CURLOPT_MAXFILESIZE_LARGE to 0 +int(25) +Negative value for CURLOPT_MAXFILESIZE_LARGE +bool(false) +bool(true) +Negative value not set, CURLOPT_MAXFILESIZE_LARGE is still 0 +int(25) From a1f182f6d4a1c3896dfa02b4d9a26a71d3665304 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 17 Aug 2026 12:45:02 +0000 Subject: [PATCH 03/11] Add test for CURLOPT_POSTREDIR --- .../tests/curl_setopt_CURLOPT_POSTREDIR.phpt | 91 +++++++++++++++++++ ext/curl/tests/responder/get.inc | 2 +- 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 ext/curl/tests/curl_setopt_CURLOPT_POSTREDIR.phpt diff --git a/ext/curl/tests/curl_setopt_CURLOPT_POSTREDIR.phpt b/ext/curl/tests/curl_setopt_CURLOPT_POSTREDIR.phpt new file mode 100644 index 000000000000..686eca698b17 --- /dev/null +++ b/ext/curl/tests/curl_setopt_CURLOPT_POSTREDIR.phpt @@ -0,0 +1,91 @@ +--TEST-- +Curl option CURLOPT_POSTREDIR +--DESCRIPTION-- +Verify that CURLOPT_POSTREDIR controls whether POST data is retained on +301, 302, and 303 redirects. By default libcurl turns POST into GET on +301, 302, and 303. Setting the appropriate bit in CURLOPT_POSTREDIR +keeps the POST method and body. +--EXTENSIONS-- +curl +--FILE-- + +--EXPECT-- +default 301: string(0) "" +default 302: string(0) "" +default 303: string(0) "" +301 on, code 301: string(7) "foo=bar" +301 on, code 302: string(0) "" +301 on, code 303: string(0) "" +302 on, code 301: string(0) "" +302 on, code 302: string(7) "foo=bar" +302 on, code 303: string(0) "" +303 on, code 301: string(0) "" +303 on, code 302: string(0) "" +303 on, code 303: string(7) "foo=bar" +ALL on, code 301: string(7) "foo=bar" +ALL on, code 302: string(7) "foo=bar" +ALL on, code 303: string(7) "foo=bar" diff --git a/ext/curl/tests/responder/get.inc b/ext/curl/tests/responder/get.inc index 2ef1e4a89dd3..a62b6f7f172e 100644 --- a/ext/curl/tests/responder/get.inc +++ b/ext/curl/tests/responder/get.inc @@ -49,7 +49,7 @@ case 'redirect': // A 307 preserves the method and body, so libcurl must rewind the upload // (via CURLOPT_SEEKFUNCTION) before resending it to the new location. - header('Location: /get.inc?test=input', true, 307); + header('Location: /get.inc?test=input', true, $_GET['code'] ?? 307); break; default: echo "Hello World!\n"; From bc61c3d416bd1e92aa779636b66cdfaf57516411 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 17 Aug 2026 14:05:13 +0000 Subject: [PATCH 04/11] ext/curl: test CURLOPT_SSH_HOSTKEYFUNCTION --- ...rl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 ext/curl/tests/curl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt diff --git a/ext/curl/tests/curl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt b/ext/curl/tests/curl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt new file mode 100644 index 000000000000..b2564162b635 --- /dev/null +++ b/ext/curl/tests/curl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt @@ -0,0 +1,26 @@ +--TEST-- +Curl option CURLOPT_SSH_HOSTKEYFUNCTION +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(false) +string(49) "SSL peer certificate or SSH remote key was not OK" From 52e7ed4a40417dda593aa7af3df3334a170628dd Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 17 Aug 2026 14:24:32 +0000 Subject: [PATCH 05/11] ext/curl: test CURLOPT_FNMATCH_FUNCTION --- .../curl_setopt_CURLOPT_FNMATCH_FUNCTION.phpt | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 ext/curl/tests/curl_setopt_CURLOPT_FNMATCH_FUNCTION.phpt diff --git a/ext/curl/tests/curl_setopt_CURLOPT_FNMATCH_FUNCTION.phpt b/ext/curl/tests/curl_setopt_CURLOPT_FNMATCH_FUNCTION.phpt new file mode 100644 index 000000000000..94196842160e --- /dev/null +++ b/ext/curl/tests/curl_setopt_CURLOPT_FNMATCH_FUNCTION.phpt @@ -0,0 +1,41 @@ +--TEST-- +Curl option CURLOPT_FNMATCH_FUNCTION +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- + +--EXPECT-- +The list of Debian mirror sites is available here: https://www.debian.org/mirror/list +bool(true) +bool(true) From afdeed93945de0c77047ef3704ed0c7c4881cf33 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 17 Aug 2026 17:22:27 +0000 Subject: [PATCH 06/11] ext/curl: test CURLINFO_HEADER_OUT --- .../curl_getinfo_CURLINFO_HEADER_OUT.phpt | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 ext/curl/tests/curl_getinfo_CURLINFO_HEADER_OUT.phpt diff --git a/ext/curl/tests/curl_getinfo_CURLINFO_HEADER_OUT.phpt b/ext/curl/tests/curl_getinfo_CURLINFO_HEADER_OUT.phpt new file mode 100644 index 000000000000..c50edc219e1d --- /dev/null +++ b/ext/curl/tests/curl_getinfo_CURLINFO_HEADER_OUT.phpt @@ -0,0 +1,43 @@ +--TEST-- +curl_getinfo CURLINFO_HEADER_OUT +--DESCRIPTION-- +Verify that CURLINFO_HEADER_OUT returns the request header sent on the +last request, and that toggling it back to 0 returns FALSE. +--EXTENSIONS-- +curl +--FILE-- + +--EXPECTF-- +With CURLINFO_HEADER_OUT=1: +GET /get.inc?test=method HTTP/1.1 +Host: localhost:%d +%s +Request-num: 1 +--- +With CURLINFO_HEADER_OUT=0: +bool(false) From a4014a026efaed5aee6b9384fd7470eb7b8e9264 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 17 Aug 2026 19:26:38 +0000 Subject: [PATCH 07/11] ext/curl: test read_cb by sending a CURLFile twice Allow setting target of redirect in test --- ext/curl/tests/curl_curlfile_seek.phpt | 22 ++++++++++++++++++++++ ext/curl/tests/responder/get.inc | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 ext/curl/tests/curl_curlfile_seek.phpt diff --git a/ext/curl/tests/curl_curlfile_seek.phpt b/ext/curl/tests/curl_curlfile_seek.phpt new file mode 100644 index 000000000000..8ebaab92bc43 --- /dev/null +++ b/ext/curl/tests/curl_curlfile_seek.phpt @@ -0,0 +1,22 @@ +--TEST-- +curl seek within uploaded file +--EXTENSIONS-- +curl +--FILE-- + new CURLFile(__DIR__ . '/curl_testdata1.txt') +]); +curl_exec($ch); + +?> +--EXPECT-- +curl_testdata1.txt|application/octet-stream|6 diff --git a/ext/curl/tests/responder/get.inc b/ext/curl/tests/responder/get.inc index a62b6f7f172e..a2ede2836cc5 100644 --- a/ext/curl/tests/responder/get.inc +++ b/ext/curl/tests/responder/get.inc @@ -49,7 +49,8 @@ case 'redirect': // A 307 preserves the method and body, so libcurl must rewind the upload // (via CURLOPT_SEEKFUNCTION) before resending it to the new location. - header('Location: /get.inc?test=input', true, $_GET['code'] ?? 307); + $target = $_GET['target'] ?? 'input'; + header('Location: /get.inc?test=' . $target, true, $_GET['code'] ?? 307); break; default: echo "Hello World!\n"; From f7f66c347a0f8114a02b9c56a94d3bba534cf762 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Mon, 17 Aug 2026 19:43:28 +0000 Subject: [PATCH 08/11] ext/curl: add test for CURLINFO_CERTINFO --- .../tests/curl_getinfo_CURLINFO_CERTINFO.phpt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 ext/curl/tests/curl_getinfo_CURLINFO_CERTINFO.phpt diff --git a/ext/curl/tests/curl_getinfo_CURLINFO_CERTINFO.phpt b/ext/curl/tests/curl_getinfo_CURLINFO_CERTINFO.phpt new file mode 100644 index 000000000000..7ce814717753 --- /dev/null +++ b/ext/curl/tests/curl_getinfo_CURLINFO_CERTINFO.phpt @@ -0,0 +1,26 @@ +--TEST-- +curl_getinfo - CURLINFO_CERTINFO +--EXTENSIONS-- +curl +--SKIPIF-- + +--FILE-- + +--EXPECT-- +pong +bool(false) +bool(true) From 2aa80efcacc776c87712a9beed9487c40be6cffc Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Tue, 18 Aug 2026 08:33:24 +0000 Subject: [PATCH 09/11] Minor fixes --- ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt | 2 +- ext/curl/tests/responder/get.inc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt b/ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt index 06a80f86a3b1..1a372c978548 100644 --- a/ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt +++ b/ext/curl/tests/curl_setopt_CURLOPT_WRITEHEADER.phpt @@ -10,7 +10,7 @@ include 'server.inc'; $host = curl_cli_server_start(); $header_file = tempnam(sys_get_temp_dir(), 'curl-writeheader'); -$fp = fopen($header_file, 'w'); +$fp = fopen($header_file, 'w') or die('failed to open header output file'); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "{$host}/get.inc?test=contenttype"); diff --git a/ext/curl/tests/responder/get.inc b/ext/curl/tests/responder/get.inc index a2ede2836cc5..f84d4b62858f 100644 --- a/ext/curl/tests/responder/get.inc +++ b/ext/curl/tests/responder/get.inc @@ -50,7 +50,8 @@ // A 307 preserves the method and body, so libcurl must rewind the upload // (via CURLOPT_SEEKFUNCTION) before resending it to the new location. $target = $_GET['target'] ?? 'input'; - header('Location: /get.inc?test=' . $target, true, $_GET['code'] ?? 307); + $code = $_GET['code'] ?? 307; + header('Location: /get.inc?test=' . $target, true, $code); break; default: echo "Hello World!\n"; From 035e0b896b165b6b2612fd34d79d53846ccb735f Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Tue, 18 Aug 2026 11:31:21 +0000 Subject: [PATCH 10/11] ext/curl: test CURLE_ error constants --- ext/curl/tests/curl_errors.phpt | 110 ++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 ext/curl/tests/curl_errors.phpt diff --git a/ext/curl/tests/curl_errors.phpt b/ext/curl/tests/curl_errors.phpt new file mode 100644 index 000000000000..aada11b3f60f --- /dev/null +++ b/ext/curl/tests/curl_errors.phpt @@ -0,0 +1,110 @@ +--TEST-- +curl error constants +--EXTENSIONS-- +curl +--FILE-- + Date: Tue, 18 Aug 2026 11:57:07 +0000 Subject: [PATCH 11/11] Improve tests after review comments --- ext/curl/tests/curl_errors.phpt | 2 +- .../curl_getinfo_CURLINFO_HEADER_OUT.phpt | 3 +- .../tests/curl_setopt_CURLOPT_POSTREDIR.phpt | 86 ++++++------------- ...rl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt | 4 + .../curl_setopt_CURLOPT_WRITEHEADER.phpt | 11 +-- 5 files changed, 39 insertions(+), 67 deletions(-) diff --git a/ext/curl/tests/curl_errors.phpt b/ext/curl/tests/curl_errors.phpt index aada11b3f60f..cf3d8c60770a 100644 --- a/ext/curl/tests/curl_errors.phpt +++ b/ext/curl/tests/curl_errors.phpt @@ -57,7 +57,7 @@ $errors = [ foreach ($errors as $error) { $value = defined($error) ? constant($error) : 'undefined'; - echo $error, '=', $value, PHP_EOL; + echo $error, '=', $value, "\n"; } --EXPECT-- diff --git a/ext/curl/tests/curl_getinfo_CURLINFO_HEADER_OUT.phpt b/ext/curl/tests/curl_getinfo_CURLINFO_HEADER_OUT.phpt index c50edc219e1d..c03bd3bc6033 100644 --- a/ext/curl/tests/curl_getinfo_CURLINFO_HEADER_OUT.phpt +++ b/ext/curl/tests/curl_getinfo_CURLINFO_HEADER_OUT.phpt @@ -19,8 +19,7 @@ curl_exec($ch); // The header string contains the full request header line(s). $headers = rtrim(curl_getinfo($ch, CURLINFO_HEADER_OUT)); echo "With CURLINFO_HEADER_OUT=1:\n"; -echo $headers; -echo "\n---\n"; +echo $headers, "\n---\n"; // Toggling back to 0 should clear the buffer; next getinfo returns false. curl_setopt($ch, CURLOPT_HTTPHEADER, ['Request-num: 2']); diff --git a/ext/curl/tests/curl_setopt_CURLOPT_POSTREDIR.phpt b/ext/curl/tests/curl_setopt_CURLOPT_POSTREDIR.phpt index 686eca698b17..ff7cebdb4c15 100644 --- a/ext/curl/tests/curl_setopt_CURLOPT_POSTREDIR.phpt +++ b/ext/curl/tests/curl_setopt_CURLOPT_POSTREDIR.phpt @@ -18,7 +18,7 @@ function do_redirect($code, $postredir_value = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "{$host}/get.inc?test=redirect&code={$code}"); curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, 'foo=bar'); + curl_setopt($ch, CURLOPT_POSTFIELDS, 'postdata was kept in redirect'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); if ($postredir_value !== null) { @@ -27,65 +27,33 @@ function do_redirect($code, $postredir_value = null) { return trim(curl_exec($ch)); } -echo "default 301: "; -echo do_redirect(301), PHP_EOL; +$options = [null, CURL_REDIR_POST_301, CURL_REDIR_POST_302, CURL_REDIR_POST_303, CURL_REDIR_POST_ALL, 0]; +$codes = [301, 302, 303]; -echo "default 302: "; -echo do_redirect(302), PHP_EOL; - -echo "default 303: "; -echo do_redirect(303), PHP_EOL; - -echo "301 on, code 301: "; -echo do_redirect(301, CURL_REDIR_POST_301), PHP_EOL; - -echo "301 on, code 302: "; -echo do_redirect(302, CURL_REDIR_POST_301), PHP_EOL; - -echo "301 on, code 303: "; -echo do_redirect(303, CURL_REDIR_POST_301), PHP_EOL; - -echo "302 on, code 301: "; -echo do_redirect(301, CURL_REDIR_POST_302), PHP_EOL; - -echo "302 on, code 302: "; -echo do_redirect(302, CURL_REDIR_POST_302), PHP_EOL; - -echo "302 on, code 303: "; -echo do_redirect(303, CURL_REDIR_POST_302), PHP_EOL; - -echo "303 on, code 301: "; -echo do_redirect(301, CURL_REDIR_POST_303), PHP_EOL; - -echo "303 on, code 302: "; -echo do_redirect(302, CURL_REDIR_POST_303), PHP_EOL; - -echo "303 on, code 303: "; -echo do_redirect(303, CURL_REDIR_POST_303), PHP_EOL; - -echo "ALL on, code 301: "; -echo do_redirect(301, CURL_REDIR_POST_ALL), PHP_EOL; - -echo "ALL on, code 302: "; -echo do_redirect(302, CURL_REDIR_POST_ALL), PHP_EOL; - -echo "ALL on, code 303: "; -echo do_redirect(303, CURL_REDIR_POST_ALL), PHP_EOL; +foreach ($options as $option) { + foreach ($codes as $code) { + echo "code: $code; option ", var_export($option, true), ': '; + echo do_redirect($code, $option), "\n"; + } +} ?> --EXPECT-- -default 301: string(0) "" -default 302: string(0) "" -default 303: string(0) "" -301 on, code 301: string(7) "foo=bar" -301 on, code 302: string(0) "" -301 on, code 303: string(0) "" -302 on, code 301: string(0) "" -302 on, code 302: string(7) "foo=bar" -302 on, code 303: string(0) "" -303 on, code 301: string(0) "" -303 on, code 302: string(0) "" -303 on, code 303: string(7) "foo=bar" -ALL on, code 301: string(7) "foo=bar" -ALL on, code 302: string(7) "foo=bar" -ALL on, code 303: string(7) "foo=bar" +code: 301; option NULL: string(0) "" +code: 302; option NULL: string(0) "" +code: 303; option NULL: string(0) "" +code: 301; option 1: string(29) "postdata was kept in redirect" +code: 302; option 1: string(0) "" +code: 303; option 1: string(0) "" +code: 301; option 2: string(0) "" +code: 302; option 2: string(29) "postdata was kept in redirect" +code: 303; option 2: string(0) "" +code: 301; option 4: string(0) "" +code: 302; option 4: string(0) "" +code: 303; option 4: string(29) "postdata was kept in redirect" +code: 301; option 7: string(29) "postdata was kept in redirect" +code: 302; option 7: string(29) "postdata was kept in redirect" +code: 303; option 7: string(29) "postdata was kept in redirect" +code: 301; option 0: string(0) "" +code: 302; option 0: string(0) "" +code: 303; option 0: string(0) "" diff --git a/ext/curl/tests/curl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt b/ext/curl/tests/curl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt index b2564162b635..9bb6f0104cdf 100644 --- a/ext/curl/tests/curl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt +++ b/ext/curl/tests/curl_setopt_CURLOPT_SSH_HOSTKEYFUNCTION.phpt @@ -5,6 +5,10 @@ curl --SKIPIF-- = 7.84.0"); +} ?> --FILE-- +--CLEAN-- + --EXPECTF-- HTTP/1.1 200 OK