Skip to content

Commit f05e439

Browse files
committed
Fix GH-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.
1 parent fe2dc2b commit f05e439

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

ext/ftp/ftp.c

Lines changed: 4 additions & 4 deletions
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

Lines changed: 39 additions & 0 deletions
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+
@unlink($local_file);
23+
$handle = fopen($local_file, 'a');
24+
var_dump(ftp_fget($ftp, $handle, 'fget_large.txt', FTP_ASCII, $size));
25+
fclose($handle);
26+
var_dump(file_get_contents($local_file));
27+
}
28+
29+
?>
30+
--CLEAN--
31+
<?php
32+
@unlink(__DIR__ . DIRECTORY_SEPARATOR . "gh10521.txt");
33+
?>
34+
--EXPECT--
35+
bool(true)
36+
bool(true)
37+
string(11) "12345678910"
38+
bool(true)
39+
string(19) "9223372036854775807"

ext/ftp/tests/server.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,10 @@ if ($pid) {
371371
$transfer_type = $ascii? 'ASCII' : 'BINARY' ;
372372
if ($GLOBALS['rest_pos'] == '5368709119') {
373373
fputs($fs, "X");
374+
} elseif ($GLOBALS['rest_pos'] == '12345678910') {
375+
fputs($fs, "12345678910");
376+
} elseif ($GLOBALS['rest_pos'] == '9223372036854775807') {
377+
fputs($fs, "9223372036854775807");
374378
} else {
375379
fputs($fs, "Y");
376380
}

0 commit comments

Comments
 (0)