Skip to content

Fix use-after-free on re-entrant ftp_close() during a transfer#22400

Open
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:ftp-reentrant-close-uaf
Open

Fix use-after-free on re-entrant ftp_close() during a transfer#22400
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:ftp-reentrant-close-uaf

Conversation

@iliaal

@iliaal iliaal commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

A user stream wrapper's stream_read/stream_write handler can call ftp_close() mid-transfer (during ftp_get/ftp_put/ftp_append or the ftp_nb_* variants), freeing the ftpbuf_t the engine still holds on the C stack, so the transfer resumes on freed memory (valgrind: invalid reads in the ftp_get receive loop). The fix guards each engine transfer with an in_use flag and makes ftp_close() throw while a transfer is in progress. Reported privately as GHSA-vr2x-x6ff-4586, rejected per the security policy because the trigger is PHP code, not the FTP server.

A user stream wrapper passed to ftp_get(), ftp_put(), ftp_append() or
the ftp_nb_* variants can call ftp_close() from its stream_read or
stream_write handler while the engine still holds the freed ftpbuf_t and
databuf_t on the C stack, so the transfer resumes on freed memory. Guard
each engine transfer with an in_use flag and make ftp_close() throw while
it is set.

Closes phpGH-22400
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