Skip to content

Commit 3014182

Browse files
committed
Fix phpGH-10521: ftp_get/ftp_nb_get resumepos offset is maximum 10GB
The char arrays were too small for a long on 64-bit systems, which resulted in cutting off the string at the end with a NUL byte. Use a size of MAX_LENGTH_OF_LONG to fix this issue instead of a fixed size of 11 chars. Closes phpGH-10525.
1 parent c407243 commit 3014182

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ PHP NEWS
2424

2525
- FTP:
2626
. Propagate success status of ftp_close(). (nielsdos)
27+
. Fixed bug GH-10521 (ftp_get/ftp_nb_get resumepos offset is maximum 10GB).
28+
(nielsdos)
2729

2830
- Opcache:
2931
. Fixed build for macOS to cater with pkg-config settings. (David Carlier)

ext/ftp/ftp.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,7 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t pat
867867
{
868868
databuf_t *data = NULL;
869869
size_t rcvd;
870-
char arg[11];
870+
char arg[MAX_LENGTH_OF_LONG];
871871

872872
if (ftp == NULL) {
873873
return 0;
@@ -964,7 +964,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *inst
964964
zend_long size;
965965
char *ptr;
966966
int ch;
967-
char arg[11];
967+
char arg[MAX_LENGTH_OF_LONG];
968968

969969
if (ftp == NULL) {
970970
return 0;
@@ -2057,7 +2057,7 @@ int
20572057
ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t path_len, ftptype_t type, zend_long resumepos)
20582058
{
20592059
databuf_t *data = NULL;
2060-
char arg[11];
2060+
char arg[MAX_LENGTH_OF_LONG];
20612061

20622062
if (ftp == NULL) {
20632063
return PHP_FTP_FAILED;
@@ -2176,7 +2176,7 @@ int
21762176
ftp_nb_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos)
21772177
{
21782178
databuf_t *data = NULL;
2179-
char arg[11];
2179+
char arg[MAX_LENGTH_OF_LONG];
21802180

21812181
if (ftp == NULL) {
21822182
return 0;

ext/ftp/tests/gh10521.phpt

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
GH-10521 (ftp_get/ftp_nb_get resumepos offset is maximum 10GB)
3+
--EXTENSIONS--
4+
ftp
5+
pcntl
6+
--SKIPIF--
7+
<?php
8+
if (PHP_INT_SIZE != 8) die("skip: 64-bit only");
9+
?>
10+
--FILE--
11+
<?php
12+
require 'server.inc';
13+
14+
$ftp = ftp_connect('127.0.0.1', $port);
15+
if (!$ftp) die("Couldn't connect to the server");
16+
17+
var_dump(ftp_login($ftp, 'anonymous', 'IEUser@'));
18+
19+
$local_file = __DIR__ . DIRECTORY_SEPARATOR . "gh10521.txt";
20+
21+
foreach ([12345678910, 9223372036854775807] as $size) {
22+
$handle = fopen($local_file, 'w');
23+
// Doesn't actually succeed in transferring a file. The file transfer gets aborted by our fake server.
24+
// We just want to see if the offset was correctly received.
25+
ftp_fget($ftp, $handle, 'gh10521', FTP_ASCII, $size);
26+
fclose($handle);
27+
}
28+
29+
?>
30+
--CLEAN--
31+
<?php
32+
@unlink(__DIR__ . DIRECTORY_SEPARATOR . "gh10521.txt");
33+
?>
34+
--EXPECTF--
35+
bool(true)
36+
37+
%s: ftp_fget(): Can't open data connection (12345678910). in %s on line %d
38+
39+
%s: ftp_fget(): Can't open data connection (9223372036854775807). in %s on line %d

ext/ftp/tests/server.inc

+4
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,10 @@ if ($pid) {
387387
case "/bug73457":
388388
fputs($s, "150 File status okay; about to open data connection.\r\n");
389389
break;
390+
case "gh10521":
391+
// Just a side channel for getting the received file size.
392+
fputs($s, "425 Can't open data connection (".$GLOBALS['rest_pos'].").\r\n");
393+
break;
390394

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

0 commit comments

Comments
 (0)