Commit 5e5839904f5 for php.net

commit 5e5839904f57f5dabaad28d447b74aea798d79e9
Author: Sjoerd Langkemper <sjoerd-github@linuxonly.nl>
Date:   Sun Aug 16 20:51:14 2026 +0200

    ext/curl: set curl post size using CURLOPT_POSTFIELDSIZE_LARGE (#22842)

    This is a 64-bit number on all platforms. This improves support of
    posting files larger than 2GB.

    - https://curl.se/libcurl/c/CURLOPT_POSTFIELDSIZE.html
    - https://curl.se/libcurl/c/CURLOPT_POSTFIELDSIZE_LARGE.html

diff --git a/NEWS b/NEWS
index 9977ea3b340..a75d304276f 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,11 @@ PHP                                                                        NEWS
     class constants via OBJ->prop = $val). (Khaled Alam)
   . Reverted GH-22833, which attempted to fix bug GH-18985. (ilutov)

+- Curl:
+  . Set content length using CURLOPT_POSTFIELDSIZE_LARGE instead of
+    CURLOPT_POSTFIELDSIZE. This makes it possible to post strings larger than
+    2GB on some platforms, e.g. Windows. (Sjoerd Langkemper)
+
 - DOM:
   . Fixed bug GH-22624 (use-after-free via DOMNameSpaceNode after
     DOMDocument::xinclude()). (David Carlier)
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index e198b0bb7d7..db3dd01b550 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -2178,7 +2178,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
 					/* no need to build the mime structure for empty hashtables;
 					   also works around https://github.com/curl/curl/issues/6455 */
 					curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, "");
-					error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, 0L);
+					error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t) 0);
 				} else {
 					return build_mime_structure_from_hash(ch, zvalue);
 				}
@@ -2186,7 +2186,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
 				zend_string *tmp_str;
 				zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
 				/* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */
-				error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str));
+				error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t) ZSTR_LEN(str));
 				error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, ZSTR_VAL(str));
 				zend_tmp_string_release(tmp_str);
 			}
diff --git a/ext/curl/tests/curl_post_large_string.phpt b/ext/curl/tests/curl_post_large_string.phpt
new file mode 100644
index 00000000000..b6bc6782542
--- /dev/null
+++ b/ext/curl/tests/curl_post_large_string.phpt
@@ -0,0 +1,30 @@
+--TEST--
+CURL post data larger than 2GB (to test CURLOPT_POSTFIELDSIZE_LARGE)
+--INI--
+memory_limit=3G
+--SKIPIF--
+<?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
+if (PHP_INT_SIZE < 8) die('skip 64-bit only');
+include 'skipif-nocaddy.inc';
+?>
+--EXTENSIONS--
+curl
+--FILE--
+<?php
+$size = 2 ** 31 + 100; // a little bit more than a signed 32-bit int
+$data = str_repeat('a', $size);
+
+$ch = curl_init("https://localhost/show_upload_size");
+curl_setopt_array($ch, [
+    CURLOPT_RETURNTRANSFER => true,
+    CURLOPT_POST => true,
+    CURLOPT_POSTFIELDS => $data,
+]);
+
+$response = curl_exec($ch);
+var_dump($response);
+
+?>
+--EXPECT--
+string(28) "Content-length: =2147483748="