Check totalLength of file is less than std::numeric_limits<off_t>::max()

If totalLength is larger than std::numeric_limits<off_t>::max(), throw
DownloadFailureException.
pull/4/head
Tatsuhiro Tsujikawa 2011-12-09 01:12:54 +09:00
parent 7989cd898d
commit 31163c6785
5 changed files with 39 additions and 16 deletions

View File

@ -464,14 +464,13 @@ bool FtpNegotiationCommand::onFileSizeDetermined(off_t totalLength)
} }
bool FtpNegotiationCommand::recvSize() { bool FtpNegotiationCommand::recvSize() {
off_t size = 0; int64_t size = 0;
int status = ftp_->receiveSizeResponse(size); int status = ftp_->receiveSizeResponse(size);
if(status == 0) { if(status == 0) {
return false; return false;
} }
if(status == 213) { if(status == 213) {
if(size > std::numeric_limits<off_t>::max()) {
if(size > INT64_MAX) {
throw DL_ABORT_EX2 throw DL_ABORT_EX2
(fmt(EX_TOO_LARGE_FILE, static_cast<long long int>(size)), (fmt(EX_TOO_LARGE_FILE, static_cast<long long int>(size)),
error_code::FTP_PROTOCOL_ERROR); error_code::FTP_PROTOCOL_ERROR);

View File

@ -36,6 +36,7 @@
#include "Range.h" #include "Range.h"
#include "util.h" #include "util.h"
#include "A2STR.h" #include "A2STR.h"
#include "DownloadFailureException.h"
namespace aria2 { namespace aria2 {
@ -136,11 +137,13 @@ RangeHandle HttpHeader::getRange() const
if(clenStr.empty()) { if(clenStr.empty()) {
return SharedHandle<Range>(new Range()); return SharedHandle<Range>(new Range());
} else { } else {
off_t contentLength = util::parseLLInt(clenStr); int64_t contentLength = util::parseLLInt(clenStr);
if(contentLength < 0) { if(contentLength < 0) {
throw DL_ABORT_EX("Content-Length must be positive"); throw DL_ABORT_EX("Content-Length must be positive");
} } else if(contentLength > std::numeric_limits<off_t>::max()) {
if(contentLength == 0) { throw DOWNLOAD_FAILURE_EXCEPTION
(fmt(EX_TOO_LARGE_FILE, static_cast<long long int>(contentLength)));
} else if(contentLength == 0) {
return SharedHandle<Range>(new Range()); return SharedHandle<Range>(new Range());
} else { } else {
return SharedHandle<Range> return SharedHandle<Range>
@ -176,13 +179,25 @@ RangeHandle HttpHeader::getRange() const
if(minus == slash) { if(minus == slash) {
return SharedHandle<Range>(new Range()); return SharedHandle<Range>(new Range());
} }
off_t startByte = util::parseLLInt(std::string(byteRangeSpec, minus)); int64_t startByte = util::parseLLInt(std::string(byteRangeSpec, minus));
off_t endByte = util::parseLLInt(std::string(minus+1, slash)); int64_t endByte = util::parseLLInt(std::string(minus+1, slash));
off_t entityLength = int64_t entityLength =
util::parseLLInt(std::string(slash+1, rangeStr.end())); util::parseLLInt(std::string(slash+1, rangeStr.end()));
if(startByte < 0 || endByte < 0 || entityLength < 0) { if(startByte < 0 || endByte < 0 || entityLength < 0) {
throw DL_ABORT_EX("byte-range-spec must be positive"); throw DL_ABORT_EX("byte-range-spec must be positive");
} }
if(startByte > std::numeric_limits<off_t>::max()) {
throw DOWNLOAD_FAILURE_EXCEPTION
(fmt(EX_TOO_LARGE_FILE, static_cast<long long int>(startByte)));
}
if(endByte > std::numeric_limits<off_t>::max()) {
throw DOWNLOAD_FAILURE_EXCEPTION
(fmt(EX_TOO_LARGE_FILE, static_cast<long long int>(endByte)));
}
if(entityLength > std::numeric_limits<off_t>::max()) {
throw DOWNLOAD_FAILURE_EXCEPTION
(fmt(EX_TOO_LARGE_FILE, static_cast<long long int>(entityLength)));
}
return SharedHandle<Range>(new Range(startByte, endByte, entityLength)); return SharedHandle<Range>(new Range(startByte, endByte, entityLength));
} }

View File

@ -148,8 +148,9 @@ void SizeMetalinkParserState::endElement
const std::string& characters) const std::string& characters)
{ {
// current metalink specification doesn't require size element. // current metalink specification doesn't require size element.
off_t size; int64_t size;
if(util::parseLLIntNoThrow(size, characters) && size >= 0) { if(util::parseLLIntNoThrow(size, characters) && size >= 0 &&
size <= std::numeric_limits<off_t>::max()) {
psm->setFileLengthOfEntry(size); psm->setFileLengthOfEntry(size);
} }
} }

View File

@ -254,7 +254,8 @@ void SizeMetalinkParserStateV4::endElement
const std::string& characters) const std::string& characters)
{ {
off_t size; off_t size;
if(util::parseLLIntNoThrow(size, characters) && size >= 0) { if(util::parseLLIntNoThrow(size, characters) && size >= 0 &&
size <= std::numeric_limits<off_t>::max()) {
psm->setFileLengthOfEntry(size); psm->setFileLengthOfEntry(size);
} else { } else {
psm->cancelEntryTransaction(); psm->cancelEntryTransaction();

View File

@ -60,6 +60,7 @@
#include "FileEntry.h" #include "FileEntry.h"
#include "error_code.h" #include "error_code.h"
#include "array_fun.h" #include "array_fun.h"
#include "DownloadFailureException.h"
namespace aria2 { namespace aria2 {
@ -232,7 +233,7 @@ void extractFileEntries
const List* filesList = downcast<List>(infoDict->get(C_FILES)); const List* filesList = downcast<List>(infoDict->get(C_FILES));
if(filesList) { if(filesList) {
fileEntries.reserve(filesList->size()); fileEntries.reserve(filesList->size());
off_t length = 0; int64_t length = 0;
off_t offset = 0; off_t offset = 0;
// multi-file mode // multi-file mode
torrent->mode = MULTI; torrent->mode = MULTI;
@ -248,7 +249,10 @@ void extractFileEntries
error_code::BITTORRENT_PARSE_ERROR); error_code::BITTORRENT_PARSE_ERROR);
} }
length += fileLengthData->i(); length += fileLengthData->i();
if(length > std::numeric_limits<off_t>::max()) {
throw DOWNLOAD_FAILURE_EXCEPTION
(fmt(EX_TOO_LARGE_FILE, static_cast<long long int>(length)));
}
std::string pathKey; std::string pathKey;
if(fileDict->containsKey(C_PATH_UTF8)) { if(fileDict->containsKey(C_PATH_UTF8)) {
pathKey = C_PATH_UTF8; pathKey = C_PATH_UTF8;
@ -304,8 +308,11 @@ void extractFileEntries
throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_LENGTH.c_str()), throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_LENGTH.c_str()),
error_code::BITTORRENT_PARSE_ERROR); error_code::BITTORRENT_PARSE_ERROR);
} }
off_t totalLength = lengthData->i(); int64_t totalLength = lengthData->i();
if(totalLength > std::numeric_limits<off_t>::max()) {
throw DOWNLOAD_FAILURE_EXCEPTION
(fmt(EX_TOO_LARGE_FILE, static_cast<long long int>(totalLength)));
}
// For each uri in urlList, if it ends with '/', then // For each uri in urlList, if it ends with '/', then
// concatenate name to it. Specification just says so. // concatenate name to it. Specification just says so.
std::vector<std::string> uris; std::vector<std::string> uris;