Check negative number from Integer::i() where it is not allowed

pull/230/merge
Tatsuhiro Tsujikawa 2014-05-01 11:34:27 +09:00
parent 4c2ad69a75
commit 84f1a15e10
6 changed files with 41 additions and 6 deletions

View File

@ -317,12 +317,12 @@ DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse,
minInterval_ = interval_; minInterval_ = interval_;
} }
const Integer* comp = downcast<Integer>(dict->get(BtAnnounce::COMPLETE)); const Integer* comp = downcast<Integer>(dict->get(BtAnnounce::COMPLETE));
if(comp) { if(comp && comp->i() >= 0) {
complete_ = comp->i(); complete_ = comp->i();
A2_LOG_DEBUG(fmt("Complete:%d", complete_)); A2_LOG_DEBUG(fmt("Complete:%d", complete_));
} }
const Integer* incomp = downcast<Integer>(dict->get(BtAnnounce::INCOMPLETE)); const Integer* incomp = downcast<Integer>(dict->get(BtAnnounce::INCOMPLETE));
if(incomp) { if(incomp && incomp->i() >= 0) {
incomplete_ = incomp->i(); incomplete_ = incomp->i();
A2_LOG_DEBUG(fmt("Incomplete:%d", incomplete_)); A2_LOG_DEBUG(fmt("Incomplete:%d", incomplete_));
} }

View File

@ -119,7 +119,7 @@ DefaultExtensionMessageFactory::createMessage
throw DL_ABORT_EX("Bad ut_metadata: msg_type not found"); throw DL_ABORT_EX("Bad ut_metadata: msg_type not found");
} }
const Integer* index = downcast<Integer>(dict->get("piece")); const Integer* index = downcast<Integer>(dict->get("piece"));
if(!index) { if(!index || index->i() < 0) {
throw DL_ABORT_EX("Bad ut_metadata: piece not found"); throw DL_ABORT_EX("Bad ut_metadata: piece not found");
} }
switch(msgType->i()) { switch(msgType->i()) {
@ -138,7 +138,7 @@ DefaultExtensionMessageFactory::createMessage
throw DL_ABORT_EX("Bad ut_metadata data: data not found"); throw DL_ABORT_EX("Bad ut_metadata data: data not found");
} }
const Integer* totalSize = downcast<Integer>(dict->get("total_size")); const Integer* totalSize = downcast<Integer>(dict->get("total_size"));
if(!totalSize) { if(!totalSize || totalSize->i() < 0) {
throw DL_ABORT_EX("Bad ut_metadata data: total_size not found"); throw DL_ABORT_EX("Bad ut_metadata data: total_size not found");
} }
auto m = make_unique<UTMetadataDataExtensionMessage> auto m = make_unique<UTMetadataDataExtensionMessage>
@ -161,8 +161,7 @@ DefaultExtensionMessageFactory::createMessage
} }
default: default:
throw DL_ABORT_EX throw DL_ABORT_EX
(fmt("Bad ut_metadata: unknown msg_type=%u", (fmt("Bad ut_metadata: unknown msg_type=%" PRId64, msgType->i()));
static_cast<unsigned int>(msgType->i())));
} }
} else { } else {
throw DL_ABORT_EX throw DL_ABORT_EX

View File

@ -188,6 +188,11 @@ HandshakeExtensionMessage::create(const unsigned char* data, size_t length)
for(auto & elem : *extDict) { for(auto & elem : *extDict) {
const Integer* extId = downcast<Integer>(elem.second); const Integer* extId = downcast<Integer>(elem.second);
if(extId) { if(extId) {
if(extId->i() < 0 || extId->i() > 255) {
A2_LOG_DEBUG(fmt("Extension ID=%" PRId64 " is invalid", extId->i()));
continue;
}
int key = keyBtExtension(elem.first.c_str()); int key = keyBtExtension(elem.first.c_str());
if(key == ExtensionMessageRegistry::MAX_EXTENSION) { if(key == ExtensionMessageRegistry::MAX_EXTENSION) {
A2_LOG_DEBUG(fmt("Unsupported BitTorrent extension %s=%" PRId64, A2_LOG_DEBUG(fmt("Unsupported BitTorrent extension %s=%" PRId64,
@ -203,6 +208,11 @@ HandshakeExtensionMessage::create(const unsigned char* data, size_t length)
if(metadataSize) { if(metadataSize) {
auto size = metadataSize->i(); auto size = metadataSize->i();
if(size < 0) {
throw DL_ABORT_EX(fmt("Negative metadataSize %" PRId64 " was received",
size));
}
// Only accept metadata smaller than 1MiB. Be aware that broken // Only accept metadata smaller than 1MiB. Be aware that broken
// clinet can send negative size! // clinet can send negative size!
if(size > 0 && size <= 1024*1024) { if(size > 0 && size <= 1024*1024) {

View File

@ -347,6 +347,10 @@ private:
getPaginationRange getPaginationRange
(int64_t offset, int64_t num, InputIterator first, InputIterator last) (int64_t offset, int64_t num, InputIterator first, InputIterator last)
{ {
if(num <= 0) {
return std::make_pair(last, last);
}
int64_t size = std::distance(first, last); int64_t size = std::distance(first, last);
if(offset < 0) { if(offset < 0) {
int64_t tempoffset = offset+size; int64_t tempoffset = offset+size;

View File

@ -227,6 +227,13 @@ void extractFileEntries
throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_LENGTH), throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_LENGTH),
error_code::BITTORRENT_PARSE_ERROR); error_code::BITTORRENT_PARSE_ERROR);
} }
if(fileLengthData->i() < 0) {
throw DL_ABORT_EX2
(fmt(MSG_NEGATIVE_LENGTH_BT_INFO, C_LENGTH, fileLengthData->i()),
error_code::BITTORRENT_PARSE_ERROR);
}
if(length > std::numeric_limits<int64_t>::max() - fileLengthData->i()) { if(length > std::numeric_limits<int64_t>::max() - fileLengthData->i()) {
throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, length)); throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, length));
} }
@ -289,6 +296,13 @@ void extractFileEntries
error_code::BITTORRENT_PARSE_ERROR); error_code::BITTORRENT_PARSE_ERROR);
} }
int64_t totalLength = lengthData->i(); int64_t totalLength = lengthData->i();
if(totalLength < 0) {
throw DL_ABORT_EX2
(fmt(MSG_NEGATIVE_LENGTH_BT_INFO, C_LENGTH, totalLength),
error_code::BITTORRENT_PARSE_ERROR);
}
if(totalLength > std::numeric_limits<a2_off_t>::max()) { if(totalLength > std::numeric_limits<a2_off_t>::max()) {
throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, totalLength)); throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, totalLength));
} }
@ -432,6 +446,13 @@ void processRootDictionary
throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_PIECE_LENGTH), throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_PIECE_LENGTH),
error_code::BITTORRENT_PARSE_ERROR); error_code::BITTORRENT_PARSE_ERROR);
} }
if(pieceLengthData->i() < 0) {
throw DL_ABORT_EX2
(fmt(MSG_NEGATIVE_LENGTH_BT_INFO, C_PIECE_LENGTH, pieceLengthData->i()),
error_code::BITTORRENT_PARSE_ERROR);
}
size_t pieceLength = pieceLengthData->i(); size_t pieceLength = pieceLengthData->i();
ctx->setPieceLength(pieceLength); ctx->setPieceLength(pieceLength);
// retrieve piece hashes // retrieve piece hashes

View File

@ -149,6 +149,7 @@
#define MSG_REMOVED_DEFUNCT_CONTROL_FILE _("Removed the defunct control file %s because the download file %s doesn't exist.") #define MSG_REMOVED_DEFUNCT_CONTROL_FILE _("Removed the defunct control file %s because the download file %s doesn't exist.")
#define MSG_SHARE_RATIO_REPORT _("Your share ratio was %.1f, uploaded/downloaded=%sB/%sB") #define MSG_SHARE_RATIO_REPORT _("Your share ratio was %.1f, uploaded/downloaded=%sB/%sB")
#define MSG_MISSING_BT_INFO _("Missing %s in torrent metainfo.") #define MSG_MISSING_BT_INFO _("Missing %s in torrent metainfo.")
#define MSG_NEGATIVE_LENGTH_BT_INFO _("%s does not allow negative integer %" PRId64 "")
#define MSG_NULL_TRACKER_RESPONSE _("Tracker returned null data.") #define MSG_NULL_TRACKER_RESPONSE _("Tracker returned null data.")
#define MSG_WINSOCK_INIT_FAILD _("Windows socket library initialization failed") #define MSG_WINSOCK_INIT_FAILD _("Windows socket library initialization failed")
#define MSG_TIME_HAS_PASSED _("%ld second(s) has passed. Stopping application.") #define MSG_TIME_HAS_PASSED _("%ld second(s) has passed. Stopping application.")