From c643aab206ad871bd4477b4c08d6d221ea9d812f Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Wed, 20 Sep 2017 15:45:14 -0700 Subject: [PATCH] [network-data] add length checks to Prefix TLV parsing (#2207) Credit to OSS-Fuzz. --- src/core/thread/network_data_leader_ftd.cpp | 10 ++++++++-- src/core/thread/network_data_tlvs.hpp | 12 ++++++++++++ 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 82e334801..179e677fa 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -451,6 +451,8 @@ otError Leader::RlocLookup(uint16_t aRloc16, bool &aIn, bool &aStable, uint8_t * if (cur->GetType() == NetworkDataTlv::kTypePrefix) { prefix = static_cast(cur); + VerifyOrExit(prefix->IsValid(), error = OT_ERROR_PARSE); + subCur = prefix->GetSubTlvs(); subEnd = prefix->GetNext(); @@ -657,8 +659,12 @@ exit: otError Leader::AddPrefix(PrefixTlv &aPrefix) { otError error = OT_ERROR_NONE; - NetworkDataTlv *cur = aPrefix.GetSubTlvs(); - NetworkDataTlv *end = aPrefix.GetNext(); + NetworkDataTlv *cur; + NetworkDataTlv *end; + + VerifyOrExit(aPrefix.IsValid(), error = OT_ERROR_PARSE); + cur = aPrefix.GetSubTlvs(); + end = aPrefix.GetNext(); while (cur < end) { diff --git a/src/core/thread/network_data_tlvs.hpp b/src/core/thread/network_data_tlvs.hpp index 8639e0577..8a3d51c59 100644 --- a/src/core/thread/network_data_tlvs.hpp +++ b/src/core/thread/network_data_tlvs.hpp @@ -283,6 +283,18 @@ public: SetSubTlvsLength(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) const { + return ((GetLength() >= sizeof(*this) - sizeof(Tlv)) && + (GetLength() >= BitVectorBytes(mPrefixLength) + sizeof(*this) - sizeof(Tlv))); + } + /** * This method returns the Domain ID value. *