Skip to content

ext/ftp: abort a pending transfer in ftp_nb_put() - #24477

Open
kubakozub wants to merge 2 commits into
php:PHP-8.4from
kubakozub:fix/ftp-nb-put-pending-transfer-guard
Open

kubakozub wants to merge 2 commits into
php:PHP-8.4from
kubakozub:fix/ftp-nb-put-pending-transfer-guard

Conversation

@kubakozub

Copy link
Copy Markdown

What

ftp_nb_get() aborts a pending non-blocking transfer before starting a new one.
ftp_nb_put() does not. ftp_getdata() assigns ftp->data unconditionally, so each
ftp_nb_put() / ftp_nb_fput() issued while a transfer is pending replaces the pointer to the
previous databuf_t, leaking it with its socket, and reads the pending transfer's response as
the answer to its own command.

The guard was added to the GET path by c962a96 (GH-10562, "Memory leak and invalid state
with consecutive ftp_nb_fget") and never applied to the PUT path. It is absent there on every
branch from PHP-8.2 to master.

Measured

Starting one non-blocking download and then five non-blocking uploads, counting the process's
own sockets through /proc/self/fd:

before:  nb_fput #0..#4   sockets 3,4,5,6,7   (delta +1 +2 +3 +4 +5)
after:   nb_fput #0..#4   sockets 1,2,1,2,1   (delta -1 +0 -1 +0 -1)

The second line is what the guarded sibling ftp_nb_fget() already does with the same server
and the same loop.

Test

ext/ftp/tests/ftp_nb_put_during_nb_transfer.phpt leaves a transfer pending with
ftp_nb_fget() and then uploads. It fails without the change and passes with it. The full
ext/ftp suite is unaffected: 62 passed, 0 failed, 4 skipped.

🤖 Generated with Claude Code

ftp_nb_get() aborts a pending non-blocking transfer before it starts a new
one; ftp_nb_put() did not. ftp_getdata() assigns ftp->data unconditionally,
so every ftp_nb_put()/ftp_nb_fput() issued while a transfer was still pending
replaced the pointer to the previous databuf_t, leaking it together with its
socket, and read the pending transfer's response as the answer to its own
command.

The guard was added to the GET path by c962a96 (phpGH-10562, "Memory leak
and invalid state with consecutive ftp_nb_fget") and was never applied to the
PUT path. It is missing there on every branch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant