[PHP-CVS] [php-src] master: Balance stream error ops on file_put_contents LOCK_EX URL reject (#23186)
[email protected] (Ilia Alshanetsky via GitHub)
| Newsgroups | php.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: Ilia Alshanetsky (iliaal)
Committer: GitHub (web-flow)
Pusher: iliaal
Date: 2026-08-09T19:44:21-04:00
Commit: https://github.com/php/php-src/commit/0b7f50ad2e48161c3d4e8b3ddd6d547ea72ed691
Raw diff: https://github.com/php/php-src/commit/0b7f50ad2e48161c3d4e8b3ddd6d547ea72ed691.diff
Balance stream error ops on file_put_contents LOCK_EX URL reject (#23186)
file_put_contents begins a stream error operation then returns early
when LOCK_EX is used with a non-file URL, without ending the operation.
After ~1000 such failures the depth limit is exhausted and later stream
ops fail. Call php_stream_error_operation_end before that RETURN_FALSE.
Closes GH-23186
Changed paths:
A ext/standard/tests/file/file_put_contents_lock_ex_url.phpt
M NEWS
M ext/standard/file.c
Diff:
diff --git a/NEWS b/NEWS
index 39d5a948e26f..b091ea276142 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.6.0beta1
+- Streams:
+ . Fixed file_put_contents() LOCK_EX early return leaking stream error
+ operation depth. (iliaal)
+
- Core:
. Changed run-tests.php to run test subprocesses without a shell where
possible. (NickSdot)
diff --git a/ext/standard/file.c b/ext/standard/file.c
index fd6f578e4ef0..d6a8b9f1d0ea 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -474,6 +474,7 @@ PHP_FUNCTION(file_put_contents)
if (php_memnstr(filename, "://", sizeof("://") - 1, filename + filename_len)) {
if (strncasecmp(filename, "file://", sizeof("file://") - 1)) {
php_error_docref(NULL, E_WARNING, "Exclusive locks may only be set for regular files");
+ php_stream_error_operation_end(context);
RETURN_FALSE;
}
}
diff --git a/ext/standard/tests/file/file_put_contents_lock_ex_url.phpt b/ext/standard/tests/file/file_put_contents_lock_ex_url.phpt
new file mode 100644
index 000000000000..6bd346f39f46
--- /dev/null
+++ b/ext/standard/tests/file/file_put_contents_lock_ex_url.phpt
@@ -0,0 +1,20 @@
+--TEST--
+file_put_contents LOCK_EX on non-file URL balances stream error operation
+--INI--
+allow_url_fopen=1
+--FILE--
+<?php
+for ($i = 0; $i < 1005; $i++) {
+ @file_put_contents('http://127.0.0.1/x', 'data', LOCK_EX);
+}
+set_error_handler(function (int $errno, string $errstr): bool {
+ if (str_contains($errstr, 'Stream error operation depth exceeded')) {
+ echo "depth_exceeded\n";
+ }
+ return true;
+});
+file_put_contents('http://127.0.0.1/x', 'data', LOCK_EX);
+echo "done\n";
+?>
+--EXPECT--
+done