From 84f1a15e10e7d6a916cc872cb84d0a4384d61c47 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 1 May 2014 11:34:27 +0900 Subject: [PATCH] Check negative number from Integer::i() where it is not allowed --- src/DefaultBtAnnounce.cc | 4 ++-- src/DefaultExtensionMessageFactory.cc | 7 +++---- src/HandshakeExtensionMessage.cc | 10 ++++++++++ src/RpcMethodImpl.h | 4 ++++ src/bittorrent_helper.cc | 21 +++++++++++++++++++++ src/message.h | 1 + 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/DefaultBtAnnounce.cc b/src/DefaultBtAnnounce.cc index b2eeef39..74e2c2ed 100644 --- a/src/DefaultBtAnnounce.cc +++ b/src/DefaultBtAnnounce.cc @@ -317,12 +317,12 @@ DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse, minInterval_ = interval_; } const Integer* comp = downcast(dict->get(BtAnnounce::COMPLETE)); - if(comp) { + if(comp && comp->i() >= 0) { complete_ = comp->i(); A2_LOG_DEBUG(fmt("Complete:%d", complete_)); } const Integer* incomp = downcast(dict->get(BtAnnounce::INCOMPLETE)); - if(incomp) { + if(incomp && incomp->i() >= 0) { incomplete_ = incomp->i(); A2_LOG_DEBUG(fmt("Incomplete:%d", incomplete_)); } diff --git a/src/DefaultExtensionMessageFactory.cc b/src/DefaultExtensionMessageFactory.cc index abf52dea..60f70462 100644 --- a/src/DefaultExtensionMessageFactory.cc +++ b/src/DefaultExtensionMessageFactory.cc @@ -119,7 +119,7 @@ DefaultExtensionMessageFactory::createMessage throw DL_ABORT_EX("Bad ut_metadata: msg_type not found"); } const Integer* index = downcast(dict->get("piece")); - if(!index) { + if(!index || index->i() < 0) { throw DL_ABORT_EX("Bad ut_metadata: piece not found"); } switch(msgType->i()) { @@ -138,7 +138,7 @@ DefaultExtensionMessageFactory::createMessage throw DL_ABORT_EX("Bad ut_metadata data: data not found"); } const Integer* totalSize = downcast(dict->get("total_size")); - if(!totalSize) { + if(!totalSize || totalSize->i() < 0) { throw DL_ABORT_EX("Bad ut_metadata data: total_size not found"); } auto m = make_unique @@ -161,8 +161,7 @@ DefaultExtensionMessageFactory::createMessage } default: throw DL_ABORT_EX - (fmt("Bad ut_metadata: unknown msg_type=%u", - static_cast(msgType->i()))); + (fmt("Bad ut_metadata: unknown msg_type=%" PRId64, msgType->i())); } } else { throw DL_ABORT_EX diff --git a/src/HandshakeExtensionMessage.cc b/src/HandshakeExtensionMessage.cc index b94669ba..37ae1019 100644 --- a/src/HandshakeExtensionMessage.cc +++ b/src/HandshakeExtensionMessage.cc @@ -188,6 +188,11 @@ HandshakeExtensionMessage::create(const unsigned char* data, size_t length) for(auto & elem : *extDict) { const Integer* extId = downcast(elem.second); 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()); if(key == ExtensionMessageRegistry::MAX_EXTENSION) { A2_LOG_DEBUG(fmt("Unsupported BitTorrent extension %s=%" PRId64, @@ -203,6 +208,11 @@ HandshakeExtensionMessage::create(const unsigned char* data, size_t length) if(metadataSize) { 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 // clinet can send negative size! if(size > 0 && size <= 1024*1024) { diff --git a/src/RpcMethodImpl.h b/src/RpcMethodImpl.h index ac349896..6d691611 100644 --- a/src/RpcMethodImpl.h +++ b/src/RpcMethodImpl.h @@ -347,6 +347,10 @@ private: getPaginationRange (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); if(offset < 0) { int64_t tempoffset = offset+size; diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index b25e1dff..4f2309f8 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -227,6 +227,13 @@ void extractFileEntries throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_LENGTH), 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::max() - fileLengthData->i()) { throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, length)); } @@ -289,6 +296,13 @@ void extractFileEntries error_code::BITTORRENT_PARSE_ERROR); } 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::max()) { 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), 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(); ctx->setPieceLength(pieceLength); // retrieve piece hashes diff --git a/src/message.h b/src/message.h index fd6ee70a..89365a6e 100644 --- a/src/message.h +++ b/src/message.h @@ -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_SHARE_RATIO_REPORT _("Your share ratio was %.1f, uploaded/downloaded=%sB/%sB") #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_WINSOCK_INIT_FAILD _("Windows socket library initialization failed") #define MSG_TIME_HAS_PASSED _("%ld second(s) has passed. Stopping application.")