From 7a37d079d5909d5ae504f6df44e22971a35cab32 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Thu, 27 Jul 2017 21:43:13 -0700 Subject: [PATCH] [tlvs] add additional length validation when reading tlvs (#2035) --- src/core/common/tlvs.cpp | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/core/common/tlvs.cpp b/src/core/common/tlvs.cpp index a4d5b014b..f6936ef69 100644 --- a/src/core/common/tlvs.cpp +++ b/src/core/common/tlvs.cpp @@ -66,28 +66,32 @@ otError Tlv::GetOffset(const Message &aMessage, uint8_t aType, uint16_t &aOffset uint16_t end = aMessage.GetLength(); Tlv tlv; - while (offset < end) + while (offset + sizeof(tlv) <= end) { - aMessage.Read(offset, sizeof(Tlv), &tlv); + uint16_t length; - // skip extended TLV - if (tlv.GetLength() == kExtendedLength) + aMessage.Read(offset, sizeof(tlv), &tlv); + + if (tlv.GetLength() != kExtendedLength) { - uint16_t length = 0; - - offset += sizeof(tlv); - aMessage.Read(offset, sizeof(length), &length); - offset += sizeof(length) + HostSwap16(length); + length = sizeof(tlv) + tlv.GetLength(); } - else if (tlv.GetType() == aType && (offset + sizeof(tlv) + tlv.GetLength()) <= end) + else + { + VerifyOrExit(offset + sizeof(tlv) + sizeof(length) <= end); + aMessage.Read(offset + sizeof(tlv), sizeof(length), &length); + length = sizeof(tlv) + sizeof(length) + HostSwap16(length); + } + + VerifyOrExit(length <= end - offset); + + if (tlv.GetType() == aType) { aOffset = offset; ExitNow(error = OT_ERROR_NONE); } - else - { - offset += sizeof(tlv) + tlv.GetLength(); - } + + offset += length; } exit: @@ -99,24 +103,26 @@ otError Tlv::GetValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aO otError error = OT_ERROR_NOT_FOUND; uint16_t offset = aMessage.GetOffset(); uint16_t end = aMessage.GetLength(); + Tlv tlv; - while (offset < end) + while (offset + sizeof(tlv) <= end) { - Tlv tlv; uint16_t length; aMessage.Read(offset, sizeof(tlv), &tlv); offset += sizeof(tlv); - length = tlv.GetLength(); if (length == kExtendedLength) { + VerifyOrExit(offset + sizeof(length) <= end); aMessage.Read(offset, sizeof(length), &length); offset += sizeof(length); length = HostSwap16(length); } + VerifyOrExit(length <= end - offset); + if (tlv.GetType() == aType) { aOffset = offset;