Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ PHP NEWS

- FTP:
. Fix double free in ext/ftp data_accept() on accept failure. (alepacheco)
. Fixed crash in ftp_nb_continue() after ftp_nb_get() failed to abort a
pending transfer. (Jakub Kozub)

- MBString:
. Fixed bug GH-23958 (truncated encoding names resolving to full names). (Kamil Tekiela)
Expand Down
1 change: 1 addition & 0 deletions ext/ftp/ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2239,6 +2239,7 @@ ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t
return (ftp_nb_continue_read(ftp));

bail:
ftp->nb = 0;
data_close(ftp);
return PHP_FTP_FAILED;
}
Expand Down
39 changes: 39 additions & 0 deletions ext/ftp/tests/ftp_nb_get_rejected_abort.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--TEST--
ftp_nb_get() must clear ftp->nb when aborting a pending transfer fails
--EXTENSIONS--
ftp
pcntl
--FILE--
<?php
require 'server.inc';

$ftp = ftp_connect('127.0.0.1', $port);
if (!$ftp) die("Couldn't connect to the server");
var_dump(ftp_login($ftp, 'user', 'pass'));

$local_file = __DIR__ . DIRECTORY_SEPARATOR . "ftp_nb_get_rejected_abort.txt";

/* Leaves a transfer pending. The server answers this one with 451, not 226. */
var_dump(ftp_nb_get($ftp, $local_file, "abort_rejected", FTP_BINARY) === FTP_MOREDATA);

/* Aborts the pending transfer; the server's 451 sends ftp_nb_get() to bail. */
var_dump(@ftp_nb_get($ftp, $local_file, "a story", FTP_BINARY) === FTP_FAILED);

/* There is no transfer to continue any more. Before the fix ftp->nb was still
* set here, so this reached php_stream_close() on an already cleared
* ftp->stream and crashed. */
var_dump(@ftp_nb_continue($ftp) === FTP_FAILED);

ftp_close($ftp);
echo "closed\n";
?>
--CLEAN--
<?php
@unlink(__DIR__ . DIRECTORY_SEPARATOR . "ftp_nb_get_rejected_abort.txt");
?>
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
closed
9 changes: 9 additions & 0 deletions ext/ftp/tests/server.inc
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,15 @@ if ($pid) {
fputs($s, "226 Closing data Connection.\r\n");
break;

case "abort_rejected":
// Opens the data connection, then answers the transfer with
// something other than 226/250, so that a client aborting it
// from ftp_nb_get() takes the error path.
fputs($s, "150 File status okay; about to open data connection.\r\n");
fputs($fs, "partial");
fputs($s, "451 Requested action aborted: local error in processing.\r\n");
break;

default:
fputs($s, "550 {$matches[1]}: No such file or directory \r\n");
break;
Expand Down
Loading