Repository navigation
Filesystem API: Remove the temporary file when FTPext put_contents() fails - #14891
bluefairydevelopment wants to merge 2 commits into
Conversation
…fails. WP_Filesystem_FTPext::put_contents() wrote a temporary file before uploading it. Without an FTP connection, or on a closed one, ftp_fput() throws, so the temporary file was never removed and accumulated in the temp directory. Return early without a connection, as get_contents() already does, and remove the temporary file in a finally block. Props lucianwpwhite. See #64519.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. Props Bot commandsYou can trigger Props Bot actions by commenting on this PR:
|
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Before PHP 8.1 an FTP connection is a resource, and using a closed one only raises a warning instead of throwing an Error, so the test failed on PHP 7.4. See #64519.
|
The closed-connection test failed on PHP 7.4: before PHP 8.1 an FTP connection is a resource, and using a closed one raises a warning rather than throwing an |
WP_Filesystem_FTPext::put_contents()writes the contents to a temporary file fromwp_tempnam()and then uploads it withftp_fput(). When there is no FTP connection ($this->linkisnullorfalse), or the connection has been closed,ftp_fput()throws on PHP 8, so thefclose()/unlink()cleanup never runs. As the reporter describes, busy sites can accumulate very large numbers of*.tmpfiles in the temp directory.This change:
falseearly when there is no connection, matchingget_contents(), which already has this check, so no temporary file is created at all;finallyblock aroundftp_fput(), so the temporary file is removed even if the upload throws, for example on a closed connection. The exception still propagates as before.Tests: new
tests/phpunit/tests/filesystem/wpFilesystemFtpext/putContents.php.test_put_contents_without_connection_leaves_no_temp_file(null and false links): returnsfalseand leaves no temporary file.test_put_contents_on_closed_connection_leaves_no_temp_file: opens a real connection to a minimal local FTP responder, closes it, then callsput_contents(). It requires theftpextension and does not need a real FTP server.Each part of the fix was checked separately:
--group filesystemshows no new failures. Its 20 warnings are the same PHPUnit 10 deprecation notices trunk already has.Not in this PR:
WP_Filesystem_FTPexthas other methods that use$this->linkwithout a connection check, and the reporter's point that the temporary file name doesn't match the target file comes fromwp_tempnam(), which is shared by every filesystem method. Both are left for follow-up to keep this change focused.Props lucianwpwhite.
Trac ticket: https://core.trac.wordpress.org/ticket/64519
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: reading the ticket and the code, the fix, and the tests, including confirming that each test fails without the corresponding part of the fix. Submitted by Blue Fairy Development, who are responsible for the change.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.