From 9c291f0fa0c8b8c6994f521f5863c407494eb1dc Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 3 Aug 2016 22:59:01 -0700 Subject: Fix bug #72716 - initialize buffer before read --- ext/standard/ftp_fopen_wrapper.c | 81 ++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index b7eeb5649e..0d5384e3a5 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -82,6 +82,7 @@ typedef struct _php_ftp_dirstream_data { */ static inline int get_ftp_result(php_stream *stream, char *buffer, size_t buffer_size TSRMLS_DC) { + buffer[0] = '\0'; /* in case read fails to read anything */ while (php_stream_gets(stream, buffer, buffer_size-1) && !(isdigit((int) buffer[0]) && isdigit((int) buffer[1]) && isdigit((int) buffer[2]) && buffer[3] == ' ')); @@ -105,7 +106,7 @@ static int php_stream_ftp_stream_close(php_stream_wrapper *wrapper, php_stream * { php_stream *controlstream = stream->wrapperthis; int ret = 0; - + if (controlstream) { if (strpbrk(stream->mode, "wa+")) { char tmp_line[512]; @@ -154,7 +155,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char /* use port 21 if one wasn't specified */ if (resource->port == 0) resource->port = 21; - + transport_len = spprintf(&transport, 0, "tcp://%s:%d", resource->host, resource->port); stream = php_stream_xport_create(transport, transport_len, REPORT_ERRORS, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, NULL, context, NULL, NULL); efree(transport); @@ -174,7 +175,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char } if (use_ssl) { - + /* send the AUTH TLS request name */ php_stream_write_string(stream, "AUTH TLS\r\n"); @@ -183,7 +184,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char if (result != 234) { /* AUTH TLS not supported try AUTH SSL */ php_stream_write_string(stream, "AUTH SSL\r\n"); - + /* get the response */ result = GET_FTP_RESULT(stream); if (result != 334) { @@ -200,7 +201,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char } } - + if (use_ssl) { if (php_stream_xport_crypto_setup(stream, STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 @@ -210,13 +211,13 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char stream = NULL; goto connect_errexit; } - + /* set PBSZ to 0 */ php_stream_write_string(stream, "PBSZ 0\r\n"); /* ignore the response */ result = GET_FTP_RESULT(stream); - + /* set data connection protection level */ #if FTPS_ENCRYPT_DATA php_stream_write_string(stream, "PROT P\r\n"); @@ -241,7 +242,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char } \ s++; \ } \ -} +} /* send the user name */ if (resource->user != NULL) { @@ -253,10 +254,10 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char } else { php_stream_write_string(stream, "USER anonymous\r\n"); } - + /* get the response */ result = GET_FTP_RESULT(stream); - + /* if a password is required, send it */ if (result >= 300 && result <= 399) { php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, tmp_line, 0); @@ -307,7 +308,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char connect_errexit: if (resource) { - php_url_free(resource); + php_url_free(resource); } if (stream) { @@ -338,7 +339,7 @@ static unsigned short php_fopen_do_pasv(php_stream *stream, char *ip, size_t ip_ /* EPSV failed, let's try PASV */ php_stream_write_string(stream, "PASV\r\n"); result = GET_FTP_RESULT(stream); - + /* make sure we got a 227 response */ if (result != 227) { return 0; @@ -358,14 +359,14 @@ static unsigned short php_fopen_do_pasv(php_stream *stream, char *ip, size_t ip_ if (*tpath != ',') { return 0; } - *tpath='.'; + *tpath='.'; tpath++; } tpath[-1] = '\0'; memcpy(ip, hoststart, ip_size); ip[ip_size-1] = '\0'; hoststart = ip; - + /* pull out the MSB of the port */ portno = (unsigned short) strtoul(tpath, &ttpath, 10) * 256; if (ttpath == NULL) { @@ -395,7 +396,7 @@ static unsigned short php_fopen_do_pasv(php_stream *stream, char *ip, size_t ip_ /* pull out the port */ portno = (unsigned short) strtoul(tpath + 1, &ttpath, 10); } -#endif +#endif if (ttpath == NULL) { /* didn't get correct response from EPSV/PASV */ return 0; @@ -403,7 +404,7 @@ static unsigned short php_fopen_do_pasv(php_stream *stream, char *ip, size_t ip_ if (phoststart) { *phoststart = hoststart; - } + } return portno; } @@ -473,28 +474,28 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa result = GET_FTP_RESULT(stream); if (result > 299 || result < 200) goto errexit; - + /* find out the size of the file (verifying it exists) */ php_stream_printf(stream TSRMLS_CC, "SIZE %s\r\n", resource->path); - + /* read the response */ result = GET_FTP_RESULT(stream); if (read_write == 1) { /* Read Mode */ char *sizestr; - + /* when reading file, it must exist */ if (result > 299 || result < 200) { errno = ENOENT; goto errexit; } - + sizestr = strchr(tmp_line, ' '); if (sizestr) { sizestr++; file_size = atoi(sizestr); php_stream_notify_file_size(context, file_size, tmp_line, result); - } + } } else if (read_write == 2) { /* when writing file (but not appending), it must NOT exist, unless a context option exists which allows it */ if (context && php_stream_context_get_option(context, "ftp", "overwrite", &tmpzval) == SUCCESS) { @@ -502,7 +503,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa } if (result <= 299 && result >= 200) { if (allow_overwrite) { - /* Context permits overwriting file, + /* Context permits overwriting file, so we just delete whatever's there in preparation */ php_stream_printf(stream TSRMLS_CC, "DELE %s\r\n", resource->path); result = GET_FTP_RESULT(stream); @@ -533,7 +534,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa Z_LVAL_PP(tmpzval) > 0) { php_stream_printf(stream TSRMLS_CC, "REST %ld\r\n", Z_LVAL_PP(tmpzval)); result = GET_FTP_RESULT(stream); - if (result < 300 || result > 399) { + if (result < 300 || result > 399) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to resume from offset %ld", Z_LVAL_PP(tmpzval)); goto errexit; } @@ -547,9 +548,9 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa } else { /* Append */ memcpy(tmp_line, "APPE", sizeof("APPE")); - } + } php_stream_printf(stream TSRMLS_CC, "%s %s\r\n", tmp_line, (resource->path != NULL ? resource->path : "/")); - + /* open the data channel */ if (hoststart == NULL) { hoststart = resource->host; @@ -563,14 +564,14 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa result = GET_FTP_RESULT(stream); if (result != 150 && result != 125) { - /* Could not retrieve or send the file + /* Could not retrieve or send the file * this data will only be sent to us after connection on the data port was initiated. */ php_stream_close(datastream); datastream = NULL; - goto errexit; + goto errexit; } - + php_stream_context_set(datastream, context); php_stream_notify_progress_init(context, 0, file_size); @@ -584,7 +585,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa goto errexit; } - /* remember control stream */ + /* remember control stream */ datastream->wrapperthis = stream; php_url_free(resource); @@ -668,7 +669,7 @@ static int php_ftp_dirstream_close(php_stream *stream, int close_handle TSRMLS_D /* close data connection */ php_stream_close(data->datastream); data->datastream = NULL; - + efree(data); stream->abstract = NULL; @@ -707,7 +708,7 @@ php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const char *pat stream = php_ftp_fopen_connect(wrapper, path, mode, options, opened_path, context, &reuseid, &resource, &use_ssl, &use_ssl_on_data TSRMLS_CC); if (!stream) { - goto opendir_errexit; + goto opendir_errexit; } /* set the connection to be ascii */ @@ -716,7 +717,7 @@ php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const char *pat if (result > 299 || result < 200) goto opendir_errexit; - // tmp_line isn't relevant after the php_fopen_do_pasv(). + // tmp_line isn't relevant after the php_fopen_do_pasv(). tmp_line[0] = '\0'; /* set up the passive connection */ @@ -744,7 +745,7 @@ php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const char *pat php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode"); php_stream_close(datastream); datastream = NULL; - goto opendir_errexit; + goto opendir_errexit; } @@ -811,17 +812,17 @@ static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url, } php_stream_write_string(stream, "TYPE I\r\n"); /* we need this since some servers refuse to accept SIZE command in ASCII mode */ - + result = GET_FTP_RESULT(stream); if(result < 200 || result > 299) { goto stat_errexit; } - + php_stream_printf(stream TSRMLS_CC, "SIZE %s\r\n", (resource->path != NULL ? resource->path : "/")); result = GET_FTP_RESULT(stream); if (result < 200 || result > 299) { - /* Failure either means it doesn't exist + /* Failure either means it doesn't exist or it's a directory and this server fails on listing directory sizes */ if (ssb->sb.st_mode & S_IFDIR) { @@ -968,8 +969,8 @@ static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_fr resource_from = php_url_parse(url_from); resource_to = php_url_parse(url_to); - /* Must be same scheme (ftp/ftp or ftps/ftps), same host, and same port - (or a 21/0 0/21 combination which is also "same") + /* Must be same scheme (ftp/ftp or ftps/ftps), same host, and same port + (or a 21/0 0/21 combination which is also "same") Also require paths to/from */ if (!resource_from || !resource_to || @@ -979,8 +980,8 @@ static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_fr !resource_from->host || !resource_to->host || strcmp(resource_from->host, resource_to->host) || - (resource_from->port != resource_to->port && - resource_from->port * resource_to->port != 0 && + (resource_from->port != resource_to->port && + resource_from->port * resource_to->port != 0 && resource_from->port + resource_to->port != 21) || !resource_from->path || !resource_to->path) { -- cgit v1.2.1