[php-src] PR #24340: Fix out-of-bounds reads parsing ftp:// wrapper server replies

From: Date: Thu, 15 Oct 2026 02:50:31 +0000
Subject: [php-src] PR #24340: Fix out-of-bounds reads parsing ftp:// wrapper server replies
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-39454@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/24340 Author: alepacheco The ftp:// wrapper reads server replies into a 512-byte tmp_line and then parses them at fixed offsets and sizes that are not tied to the line actually received: - get_ftp_result() returns the code of whatever line it read last when the stream ends, even if that line is not a complete ddd status line. The callers then parse from tmp_line + 4 (PASV/EPSV, SIZE, MDTM), which for a short line such as 213 is past its terminating NUL. - php_fopen_do_pasv() copies a fixed ip_size bytes from the dotted address inside tmp_line, so an address near the end of the buffer is read past tmp_line, and an over-long one is silently truncated to a different address. - The MDTM handler in php_stream_ftp_url_stat() skips non-digits without stopping at the NUL, and its bound check uses > instead of >=, so sscanf() can start at tmp_line + sizeof(tmp_line). This change makes get_ftp_result() return a code only for a complete status line (and 0 otherwise), which keeps every tmp_line + 4 reader inside the received line; php_fopen_do_pasv() now copies exactly the parsed address and rejects one that does not fit; and the MDTM scan stops at the end of the line. Every caller already treats 0 as a failure (it is what get_ftp_result() returned when nothing could be read at all). The only visible change is for a server that ends the connection after a reply without the space after the code, such as a bare 226, which RFC 959 does not allow; that reply used to be accepted from the stale buffer after the read timed out. #13717 enlarges the ip buffers; this change bounds the copy itself, so it is independent of the buffer size. The tests add server.inc replies for two cases: a PASV reply whose address ends at the buffer limit, which fopen() now rejects (the old read past the buffer shows under ASan); and an MDTM reply without digits following a longer SIZE reply, for which stat() now reports an unknown mtime instead of the timestamp left in the buffer by the previous reply. Targeting PHP-8.4 as the oldest branch with the bug in active support.

« previous php.git-pulls (#39454) next »