From 1318d7942ed6256665b5d83b62ce51ec8893f5c7 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Fri, 2 Feb 2018 17:03:36 +0000 Subject: [PATCH] [network-data] add length validation to Service TLV (#2527) Credit to OSS-Fuzz. --- src/core/thread/network_data_leader_ftd.cpp | 1 + src/core/thread/network_data_tlvs.hpp | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index 5ba4297e7..b6422dfe1 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -528,6 +528,7 @@ otError Leader::RlocLookup(uint16_t aRloc16, bool &aIn, bool &aStable, uint8_t * case NetworkDataTlv::kTypeService: { service = static_cast(cur); + VerifyOrExit(service->IsValid(), error = OT_ERROR_PARSE); subCur = service->GetSubTlvs(); subEnd = service->GetNext(); diff --git a/src/core/thread/network_data_tlvs.hpp b/src/core/thread/network_data_tlvs.hpp index 50efb65b5..94ad90eb3 100644 --- a/src/core/thread/network_data_tlvs.hpp +++ b/src/core/thread/network_data_tlvs.hpp @@ -297,8 +297,8 @@ public: * */ bool IsValid(void) const { - return ((GetLength() >= sizeof(*this) - sizeof(Tlv)) && - (GetLength() >= BitVectorBytes(mPrefixLength) + sizeof(*this) - sizeof(Tlv))); + return ((GetLength() >= sizeof(*this) - sizeof(NetworkDataTlv)) && + (GetLength() >= BitVectorBytes(mPrefixLength) + sizeof(*this) - sizeof(NetworkDataTlv))); } /** @@ -712,6 +712,23 @@ public: */ void Init(void) { NetworkDataTlv::Init(); SetType(kTypeService); SetLength(2); mTResSId = kTMask; SetServiceDataLength(0); } + /** + * This method indicates whether or not the TLV appears to be well-formed. + * + * @retval TRUE If the TLV appears to be well-formed. + * @retval FALSE If the TLV does not appear to be well-formed. + * + */ + bool IsValid(void) { + uint8_t length = GetLength(); + return ((length >= (sizeof(*this) - sizeof(NetworkDataTlv))) && + (length >= ((sizeof(*this) - sizeof(NetworkDataTlv)) + + (IsThreadEnterprise() ? 0 : sizeof(uint32_t)) + sizeof(uint8_t))) && + (length >= ((sizeof(*this) - sizeof(NetworkDataTlv)) + + (IsThreadEnterprise() ? 0 : sizeof(uint32_t)) + sizeof(uint8_t) + + GetServiceDataLength()))); + } + /** * This method gets Service Data length. *