From 31163c6785364cea045ed07fefa541f6f414c1d1 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 9 Dec 2011 01:12:54 +0900 Subject: [PATCH] Check totalLength of file is less than std::numeric_limits::max() If totalLength is larger than std::numeric_limits::max(), throw DownloadFailureException. --- src/FtpNegotiationCommand.cc | 5 ++--- src/HttpHeader.cc | 27 +++++++++++++++++++++------ src/MetalinkParserStateV3Impl.cc | 5 +++-- src/MetalinkParserStateV4Impl.cc | 3 ++- src/bittorrent_helper.cc | 15 +++++++++++---- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index 70e29468..e5deafe8 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -464,14 +464,13 @@ bool FtpNegotiationCommand::onFileSizeDetermined(off_t totalLength) } bool FtpNegotiationCommand::recvSize() { - off_t size = 0; + int64_t size = 0; int status = ftp_->receiveSizeResponse(size); if(status == 0) { return false; } if(status == 213) { - - if(size > INT64_MAX) { + if(size > std::numeric_limits::max()) { throw DL_ABORT_EX2 (fmt(EX_TOO_LARGE_FILE, static_cast(size)), error_code::FTP_PROTOCOL_ERROR); diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index ff6aa8d9..8513cb56 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -36,6 +36,7 @@ #include "Range.h" #include "util.h" #include "A2STR.h" +#include "DownloadFailureException.h" namespace aria2 { @@ -136,11 +137,13 @@ RangeHandle HttpHeader::getRange() const if(clenStr.empty()) { return SharedHandle(new Range()); } else { - off_t contentLength = util::parseLLInt(clenStr); + int64_t contentLength = util::parseLLInt(clenStr); if(contentLength < 0) { throw DL_ABORT_EX("Content-Length must be positive"); - } - if(contentLength == 0) { + } else if(contentLength > std::numeric_limits::max()) { + throw DOWNLOAD_FAILURE_EXCEPTION + (fmt(EX_TOO_LARGE_FILE, static_cast(contentLength))); + } else if(contentLength == 0) { return SharedHandle(new Range()); } else { return SharedHandle @@ -176,13 +179,25 @@ RangeHandle HttpHeader::getRange() const if(minus == slash) { return SharedHandle(new Range()); } - off_t startByte = util::parseLLInt(std::string(byteRangeSpec, minus)); - off_t endByte = util::parseLLInt(std::string(minus+1, slash)); - off_t entityLength = + int64_t startByte = util::parseLLInt(std::string(byteRangeSpec, minus)); + int64_t endByte = util::parseLLInt(std::string(minus+1, slash)); + int64_t entityLength = util::parseLLInt(std::string(slash+1, rangeStr.end())); if(startByte < 0 || endByte < 0 || entityLength < 0) { throw DL_ABORT_EX("byte-range-spec must be positive"); } + if(startByte > std::numeric_limits::max()) { + throw DOWNLOAD_FAILURE_EXCEPTION + (fmt(EX_TOO_LARGE_FILE, static_cast(startByte))); + } + if(endByte > std::numeric_limits::max()) { + throw DOWNLOAD_FAILURE_EXCEPTION + (fmt(EX_TOO_LARGE_FILE, static_cast(endByte))); + } + if(entityLength > std::numeric_limits::max()) { + throw DOWNLOAD_FAILURE_EXCEPTION + (fmt(EX_TOO_LARGE_FILE, static_cast(entityLength))); + } return SharedHandle(new Range(startByte, endByte, entityLength)); } diff --git a/src/MetalinkParserStateV3Impl.cc b/src/MetalinkParserStateV3Impl.cc index fd85270f..a695b267 100644 --- a/src/MetalinkParserStateV3Impl.cc +++ b/src/MetalinkParserStateV3Impl.cc @@ -148,8 +148,9 @@ void SizeMetalinkParserState::endElement const std::string& characters) { // current metalink specification doesn't require size element. - off_t size; - if(util::parseLLIntNoThrow(size, characters) && size >= 0) { + int64_t size; + if(util::parseLLIntNoThrow(size, characters) && size >= 0 && + size <= std::numeric_limits::max()) { psm->setFileLengthOfEntry(size); } } diff --git a/src/MetalinkParserStateV4Impl.cc b/src/MetalinkParserStateV4Impl.cc index 31573139..0a488040 100644 --- a/src/MetalinkParserStateV4Impl.cc +++ b/src/MetalinkParserStateV4Impl.cc @@ -254,7 +254,8 @@ void SizeMetalinkParserStateV4::endElement const std::string& characters) { off_t size; - if(util::parseLLIntNoThrow(size, characters) && size >= 0) { + if(util::parseLLIntNoThrow(size, characters) && size >= 0 && + size <= std::numeric_limits::max()) { psm->setFileLengthOfEntry(size); } else { psm->cancelEntryTransaction(); diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index 7a2e6041..d877c45c 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -60,6 +60,7 @@ #include "FileEntry.h" #include "error_code.h" #include "array_fun.h" +#include "DownloadFailureException.h" namespace aria2 { @@ -232,7 +233,7 @@ void extractFileEntries const List* filesList = downcast(infoDict->get(C_FILES)); if(filesList) { fileEntries.reserve(filesList->size()); - off_t length = 0; + int64_t length = 0; off_t offset = 0; // multi-file mode torrent->mode = MULTI; @@ -248,7 +249,10 @@ void extractFileEntries error_code::BITTORRENT_PARSE_ERROR); } length += fileLengthData->i(); - + if(length > std::numeric_limits::max()) { + throw DOWNLOAD_FAILURE_EXCEPTION + (fmt(EX_TOO_LARGE_FILE, static_cast(length))); + } std::string pathKey; if(fileDict->containsKey(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()), error_code::BITTORRENT_PARSE_ERROR); } - off_t totalLength = lengthData->i(); - + int64_t totalLength = lengthData->i(); + if(totalLength > std::numeric_limits::max()) { + throw DOWNLOAD_FAILURE_EXCEPTION + (fmt(EX_TOO_LARGE_FILE, static_cast(totalLength))); + } // For each uri in urlList, if it ends with '/', then // concatenate name to it. Specification just says so. std::vector uris;