ThreadOperationalDataset: various bug fixes (#34331)

* ThreadOperationalDataset: various bug fixes

- Ensure TLVs read have the correct length
- Default construct as empty (mLength == 0)
- Change MakeRoom() size argument to size_t to avoid chance of truncation
- Check for null in SetNetworkName
- Use Encoding::BigEndian instead of hand-rolled math
- Use ReturnErrorOnFailure / VerifyOrReturnError consistently
- Make tests independent from each other (non-static dataset member)
- Add more tests

* Fix includes
diff --git a/src/lib/support/ThreadOperationalDataset.cpp b/src/lib/support/ThreadOperationalDataset.cpp
index 70db620..9f2ae6a 100644
--- a/src/lib/support/ThreadOperationalDataset.cpp
+++ b/src/lib/support/ThreadOperationalDataset.cpp
@@ -15,11 +15,13 @@
  *    limitations under the License.
  */
 
-#include <assert.h>
-#include <string.h>
-
 #include <lib/support/ThreadOperationalDataset.h>
 
+#include <lib/core/CHIPEncoding.h>
+
+#include <cassert>
+#include <cstring>
+
 namespace chip {
 namespace Thread {
 
@@ -70,7 +72,7 @@
         mLength = aLength;
     }
 
-    const void * GetValue() const
+    const uint8_t * GetValue() const
     {
         assert(mLength != kLengthEscape);
 
@@ -79,75 +81,44 @@
         return reinterpret_cast<const uint8_t *>(this) + sizeof(*this);
     }
 
-    void * GetValue() { return const_cast<void *>(const_cast<const ThreadTLV *>(this)->GetValue()); }
+    uint8_t * GetValue() { return const_cast<uint8_t *>(const_cast<const ThreadTLV *>(this)->GetValue()); }
+
+    ByteSpan GetValueAsSpan() const { return ByteSpan(static_cast<const uint8_t *>(GetValue()), GetLength()); }
 
     void Get64(uint64_t & aValue) const
     {
         assert(GetLength() >= sizeof(aValue));
+        aValue = Encoding::BigEndian::Get64(GetValue());
+    }
 
-        const uint8_t * p = reinterpret_cast<const uint8_t *>(GetValue());
-        aValue            =                       //
-            (static_cast<uint64_t>(p[0]) << 56) | //
-            (static_cast<uint64_t>(p[1]) << 48) | //
-            (static_cast<uint64_t>(p[2]) << 40) | //
-            (static_cast<uint64_t>(p[3]) << 32) | //
-            (static_cast<uint64_t>(p[4]) << 24) | //
-            (static_cast<uint64_t>(p[5]) << 16) | //
-            (static_cast<uint64_t>(p[6]) << 8) |  //
-            (static_cast<uint64_t>(p[7]));
+    void Get32(uint32_t & aValue) const
+    {
+        assert(GetLength() >= sizeof(aValue));
+        aValue = Encoding::BigEndian::Get32(GetValue());
     }
 
     void Get16(uint16_t & aValue) const
     {
         assert(GetLength() >= sizeof(aValue));
-
-        const uint8_t * p = static_cast<const uint8_t *>(GetValue());
-
-        aValue = static_cast<uint16_t>(p[0] << 8 | p[1]);
-    }
-
-    void Get8(uint8_t & aValue) const
-    {
-        assert(GetLength() >= sizeof(aValue));
-        aValue = *static_cast<const uint8_t *>(GetValue());
+        aValue = Encoding::BigEndian::Get16(GetValue());
     }
 
     void Set64(uint64_t aValue)
     {
-        uint8_t * value = static_cast<uint8_t *>(GetValue());
-
         SetLength(sizeof(aValue));
+        Encoding::BigEndian::Put64(GetValue(), aValue);
+    }
 
-        value[0] = static_cast<uint8_t>((aValue >> 56) & 0xff);
-        value[1] = static_cast<uint8_t>((aValue >> 48) & 0xff);
-        value[2] = static_cast<uint8_t>((aValue >> 40) & 0xff);
-        value[3] = static_cast<uint8_t>((aValue >> 32) & 0xff);
-        value[4] = static_cast<uint8_t>((aValue >> 24) & 0xff);
-        value[5] = static_cast<uint8_t>((aValue >> 16) & 0xff);
-        value[6] = static_cast<uint8_t>((aValue >> 8) & 0xff);
-        value[7] = static_cast<uint8_t>(aValue & 0xff);
+    void Set32(uint32_t aValue)
+    {
+        SetLength(sizeof(aValue));
+        Encoding::BigEndian::Put32(GetValue(), aValue);
     }
 
     void Set16(uint16_t aValue)
     {
-        uint8_t * value = static_cast<uint8_t *>(GetValue());
-
         SetLength(sizeof(aValue));
-
-        value[0] = static_cast<uint8_t>(aValue >> 8);
-        value[1] = static_cast<uint8_t>(aValue & 0xff);
-    }
-
-    void Set8(uint8_t aValue)
-    {
-        SetLength(sizeof(aValue));
-        *static_cast<uint8_t *>(GetValue()) = aValue;
-    }
-
-    void Set8(int8_t aValue)
-    {
-        SetLength(sizeof(aValue));
-        *static_cast<int8_t *>(GetValue()) = aValue;
+        Encoding::BigEndian::Put16(GetValue(), aValue);
     }
 
     void SetValue(const void * aValue, uint8_t aLength)
@@ -218,24 +189,16 @@
 CHIP_ERROR OperationalDataset::GetActiveTimestamp(uint64_t & aActiveTimestamp) const
 {
     const ThreadTLV * tlv = Locate(ThreadTLV::kActiveTimestamp);
-
-    if (tlv != nullptr)
-    {
-        tlv->Get64(aActiveTimestamp);
-        return CHIP_NO_ERROR;
-    }
-
-    return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    VerifyOrReturnError(tlv->GetLength() == sizeof(aActiveTimestamp), CHIP_ERROR_INVALID_TLV_ELEMENT);
+    tlv->Get64(aActiveTimestamp);
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR OperationalDataset::SetActiveTimestamp(uint64_t aActiveTimestamp)
 {
     ThreadTLV * tlv = MakeRoom(ThreadTLV::kActiveTimestamp, sizeof(*tlv) + sizeof(aActiveTimestamp));
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_NO_MEMORY;
-    }
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
 
     tlv->Set64(aActiveTimestamp);
 
@@ -247,26 +210,19 @@
 CHIP_ERROR OperationalDataset::GetChannel(uint16_t & aChannel) const
 {
     const ThreadTLV * tlv = Locate(ThreadTLV::kChannel);
-
-    if (tlv != nullptr)
-    {
-        const uint8_t * value = reinterpret_cast<const uint8_t *>(tlv->GetValue());
-        aChannel              = static_cast<uint16_t>((value[1] << 8) | value[2]);
-        return CHIP_NO_ERROR;
-    }
-
-    return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    VerifyOrReturnError(tlv->GetLength() == 3, CHIP_ERROR_INVALID_TLV_ELEMENT);
+    // Note: The channel page (byte 0) is not returned
+    const uint8_t * value = tlv->GetValue();
+    aChannel              = static_cast<uint16_t>((value[1] << 8) | value[2]);
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR OperationalDataset::SetChannel(uint16_t aChannel)
 {
     uint8_t value[] = { 0, static_cast<uint8_t>(aChannel >> 8), static_cast<uint8_t>(aChannel & 0xff) };
     ThreadTLV * tlv = MakeRoom(ThreadTLV::kChannel, sizeof(*tlv) + sizeof(value));
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_NO_MEMORY;
-    }
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
 
     tlv->SetValue(value, sizeof(value));
 
@@ -278,13 +234,7 @@
 CHIP_ERROR OperationalDataset::GetExtendedPanId(uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) const
 {
     ByteSpan extPanIdSpan;
-    CHIP_ERROR error = GetExtendedPanIdAsByteSpan(extPanIdSpan);
-
-    if (error != CHIP_NO_ERROR)
-    {
-        return error;
-    }
-
+    ReturnErrorOnFailure(GetExtendedPanIdAsByteSpan(extPanIdSpan));
     memcpy(aExtendedPanId, extPanIdSpan.data(), extPanIdSpan.size());
     return CHIP_NO_ERROR;
 }
@@ -292,17 +242,8 @@
 CHIP_ERROR OperationalDataset::GetExtendedPanIdAsByteSpan(ByteSpan & span) const
 {
     const ThreadTLV * tlv = Locate(ThreadTLV::kExtendedPanId);
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_TLV_TAG_NOT_FOUND;
-    }
-
-    if (tlv->GetLength() != kSizeExtendedPanId)
-    {
-        return CHIP_ERROR_INVALID_TLV_ELEMENT;
-    }
-
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    VerifyOrReturnError(tlv->GetLength() == kSizeExtendedPanId, CHIP_ERROR_INVALID_TLV_ELEMENT);
     span = ByteSpan(static_cast<const uint8_t *>(tlv->GetValue()), tlv->GetLength());
     return CHIP_NO_ERROR;
 }
@@ -310,11 +251,7 @@
 CHIP_ERROR OperationalDataset::SetExtendedPanId(const uint8_t (&aExtendedPanId)[kSizeExtendedPanId])
 {
     ThreadTLV * tlv = MakeRoom(ThreadTLV::kExtendedPanId, sizeof(*tlv) + sizeof(aExtendedPanId));
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_NO_MEMORY;
-    }
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
 
     tlv->SetValue(aExtendedPanId, sizeof(aExtendedPanId));
 
@@ -328,24 +265,16 @@
 CHIP_ERROR OperationalDataset::GetMasterKey(uint8_t (&aMasterKey)[kSizeMasterKey]) const
 {
     const ThreadTLV * tlv = Locate(ThreadTLV::kMasterKey);
-
-    if (tlv != nullptr)
-    {
-        memcpy(aMasterKey, tlv->GetValue(), sizeof(aMasterKey));
-        return CHIP_NO_ERROR;
-    }
-
-    return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    VerifyOrReturnError(tlv->GetLength() == sizeof(aMasterKey), CHIP_ERROR_INVALID_TLV_ELEMENT);
+    memcpy(aMasterKey, tlv->GetValue(), sizeof(aMasterKey));
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR OperationalDataset::SetMasterKey(const uint8_t (&aMasterKey)[kSizeMasterKey])
 {
     ThreadTLV * tlv = MakeRoom(ThreadTLV::kMasterKey, sizeof(*tlv) + sizeof(aMasterKey));
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_NO_MEMORY;
-    }
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
 
     tlv->SetValue(aMasterKey, sizeof(aMasterKey));
 
@@ -359,24 +288,16 @@
 CHIP_ERROR OperationalDataset::GetMeshLocalPrefix(uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) const
 {
     const ThreadTLV * tlv = Locate(ThreadTLV::kMeshLocalPrefix);
-
-    if (tlv != nullptr)
-    {
-        memcpy(aMeshLocalPrefix, tlv->GetValue(), sizeof(aMeshLocalPrefix));
-        return CHIP_NO_ERROR;
-    }
-
-    return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    VerifyOrReturnError(tlv->GetLength() == sizeof(aMeshLocalPrefix), CHIP_ERROR_INVALID_TLV_ELEMENT);
+    memcpy(aMeshLocalPrefix, tlv->GetValue(), sizeof(aMeshLocalPrefix));
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR OperationalDataset::SetMeshLocalPrefix(const uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix])
 {
     ThreadTLV * tlv = MakeRoom(ThreadTLV::kMeshLocalPrefix, sizeof(*tlv) + sizeof(aMeshLocalPrefix));
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_NO_MEMORY;
-    }
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
 
     tlv->SetValue(aMeshLocalPrefix, sizeof(aMeshLocalPrefix));
 
@@ -388,32 +309,21 @@
 CHIP_ERROR OperationalDataset::GetNetworkName(char (&aNetworkName)[kSizeNetworkName + 1]) const
 {
     const ThreadTLV * tlv = Locate(ThreadTLV::kNetworkName);
-
-    if (tlv != nullptr)
-    {
-        memcpy(aNetworkName, tlv->GetValue(), tlv->GetLength());
-        aNetworkName[tlv->GetLength()] = '\0';
-        return CHIP_NO_ERROR;
-    }
-
-    return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    VerifyOrReturnError(tlv->GetLength() <= kSizeNetworkName, CHIP_ERROR_INVALID_TLV_ELEMENT);
+    memcpy(aNetworkName, tlv->GetValue(), tlv->GetLength());
+    aNetworkName[tlv->GetLength()] = '\0';
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR OperationalDataset::SetNetworkName(const char * aNetworkName)
 {
+    VerifyOrReturnError(aNetworkName != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     size_t len = strlen(aNetworkName);
+    VerifyOrReturnError(0 < len && len <= kSizeNetworkName, CHIP_ERROR_INVALID_STRING_LENGTH);
 
-    if (len > kSizeNetworkName || len == 0)
-    {
-        return CHIP_ERROR_INVALID_STRING_LENGTH;
-    }
-
-    ThreadTLV * tlv = MakeRoom(ThreadTLV::kNetworkName, static_cast<uint8_t>(sizeof(*tlv) + static_cast<uint8_t>(len)));
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_NO_MEMORY;
-    }
+    ThreadTLV * tlv = MakeRoom(ThreadTLV::kNetworkName, sizeof(*tlv) + len);
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
 
     tlv->SetValue(aNetworkName, static_cast<uint8_t>(len));
 
@@ -425,24 +335,16 @@
 CHIP_ERROR OperationalDataset::GetPanId(uint16_t & aPanId) const
 {
     const ThreadTLV * tlv = Locate(ThreadTLV::kPanId);
-
-    if (tlv != nullptr)
-    {
-        tlv->Get16(aPanId);
-        return CHIP_NO_ERROR;
-    }
-
-    return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    VerifyOrReturnError(tlv->GetLength() == sizeof(aPanId), CHIP_ERROR_INVALID_TLV_ELEMENT);
+    tlv->Get16(aPanId);
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR OperationalDataset::SetPanId(uint16_t aPanId)
 {
     ThreadTLV * tlv = MakeRoom(ThreadTLV::kPanId, sizeof(*tlv) + sizeof(aPanId));
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_NO_MEMORY;
-    }
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
 
     tlv->Set16(aPanId);
 
@@ -454,24 +356,16 @@
 CHIP_ERROR OperationalDataset::GetPSKc(uint8_t (&aPSKc)[kSizePSKc]) const
 {
     const ThreadTLV * tlv = Locate(ThreadTLV::kPSKc);
-
-    if (tlv != nullptr)
-    {
-        memcpy(aPSKc, tlv->GetValue(), sizeof(aPSKc));
-        return CHIP_NO_ERROR;
-    }
-
-    return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    VerifyOrReturnError(tlv->GetLength() == sizeof(aPSKc), CHIP_ERROR_INVALID_TLV_ELEMENT);
+    memcpy(aPSKc, tlv->GetValue(), sizeof(aPSKc));
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR OperationalDataset::SetPSKc(const uint8_t (&aPSKc)[kSizePSKc])
 {
     ThreadTLV * tlv = MakeRoom(ThreadTLV::kPSKc, sizeof(*tlv) + sizeof(aPSKc));
-
-    if (tlv == nullptr)
-    {
-        return CHIP_ERROR_NO_MEMORY;
-    }
+    VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
 
     tlv->SetValue(aPSKc, sizeof(aPSKc));
 
@@ -533,7 +427,7 @@
     }
 }
 
-ThreadTLV * OperationalDataset::MakeRoom(uint8_t aType, uint8_t aSize)
+ThreadTLV * OperationalDataset::MakeRoom(uint8_t aType, size_t aSize)
 {
     ThreadTLV * tlv = Locate(aType);
 
diff --git a/src/lib/support/ThreadOperationalDataset.h b/src/lib/support/ThreadOperationalDataset.h
index e4de3dd..7bb528d 100644
--- a/src/lib/support/ThreadOperationalDataset.h
+++ b/src/lib/support/ThreadOperationalDataset.h
@@ -54,7 +54,6 @@
      *
      * @retval CHIP_NO_ERROR                Successfully initialized the dataset.
      * @retval CHIP_ERROR_INVALID_ARGUMENT  The dataset length @p aLength is too long or @p data is corrupted.
-     *
      */
     CHIP_ERROR Init(ByteSpan aData);
 
@@ -65,7 +64,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the active timestamp.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread active timestamp is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetActiveTimestamp(uint64_t & aActiveTimestamp) const;
 
@@ -76,7 +75,6 @@
      *
      * @retval CHIP_NO_ERROR           Successfully set the active timestamp.
      * @retval CHIP_ERROR_NO_MEMORY    Insufficient memory in the dataset for setting Thread active timestamp.
-     *
      */
     CHIP_ERROR SetActiveTimestamp(uint64_t aActiveTimestamp);
 
@@ -87,7 +85,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the channel.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread channel is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetChannel(uint16_t & aChannel) const;
 
@@ -98,7 +96,6 @@
      *
      * @retval CHIP_NO_ERROR           Successfully set the channel.
      * @retval CHIP_ERROR_NO_MEMORY    Insufficient memory in the dataset for setting Thread channel.
-     *
      */
     CHIP_ERROR SetChannel(uint16_t aChannel);
 
@@ -109,7 +106,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the extended PAN ID.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread extended PAN ID is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetExtendedPanId(uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) const;
 
@@ -121,7 +118,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the extended PAN ID.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread extended PAN ID is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetExtendedPanIdAsByteSpan(ByteSpan & span) const;
 
@@ -132,7 +129,6 @@
      *
      * @retval CHIP_NO_ERROR           Successfully set the extended PAN ID.
      * @retval CHIP_ERROR_NO_MEMORY    Insufficient memory in the dataset for setting Thread extended PAN ID.
-     *
      */
     CHIP_ERROR SetExtendedPanId(const uint8_t (&aExtendedPanId)[kSizeExtendedPanId]);
 
@@ -143,7 +139,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the master key.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread master key is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetMasterKey(uint8_t (&aMasterKey)[kSizeMasterKey]) const;
 
@@ -154,13 +150,11 @@
      *
      * @retval CHIP_NO_ERROR           Successfully set the master key.
      * @retval CHIP_ERROR_NO_MEMORY    Insufficient memory in the dataset for setting Thread master key.
-     *
      */
     CHIP_ERROR SetMasterKey(const uint8_t (&aMasterKey)[kSizeMasterKey]);
 
     /**
      * This method unsets Thread master key to the dataset.
-     *
      */
     void UnsetMasterKey(void);
 
@@ -171,7 +165,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the mesh local prefix.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread mesh local prefix is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetMeshLocalPrefix(uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) const;
 
@@ -182,7 +176,6 @@
      *
      * @retval CHIP_NO_ERROR           Successfully set the Thread mesh local prefix.
      * @retval CHIP_ERROR_NO_MEMORY    Insufficient memory in the dataset for setting Thread mesh local prefix.
-     *
      */
     CHIP_ERROR SetMeshLocalPrefix(const uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]);
 
@@ -193,7 +186,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the network name.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread network name is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetNetworkName(char (&aNetworkName)[kSizeNetworkName + 1]) const;
 
@@ -204,7 +197,6 @@
      *
      * @retval CHIP_NO_ERROR           Successfully set the network name.
      * @retval CHIP_ERROR_NO_MEMORY    Insufficient memory in the dataset for setting Thread network name.
-     *
      */
     CHIP_ERROR SetNetworkName(const char * aNetworkName);
 
@@ -215,7 +207,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the PAN ID.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread PAN ID is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetPanId(uint16_t & aPanId) const;
 
@@ -226,7 +218,6 @@
      *
      * @retval CHIP_NO_ERROR           Successfully set the PAN ID.
      * @retval CHIP_ERROR_NO_MEMORY    Insufficient memory in the dataset for setting Thread PAN ID.
-     *
      */
     CHIP_ERROR SetPanId(uint16_t aPanId);
 
@@ -237,7 +228,7 @@
      *
      * @retval CHIP_NO_ERROR                    Successfully retrieved the PSKc.
      * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND     Thread PSKc is not present in the dataset.
-     *
+     * @retval CHIP_ERROR_INVALID_TLV_ELEMENT   If the TLV element is invalid.
      */
     CHIP_ERROR GetPSKc(uint8_t (&aPSKc)[kSizePSKc]) const;
 
@@ -248,13 +239,11 @@
      *
      * @retval CHIP_NO_ERROR           Successfully set the PSKc.
      * @retval CHIP_ERROR_NO_MEMORY    Insufficient memory in the dataset for setting Thread PSKc.
-     *
      */
     CHIP_ERROR SetPSKc(const uint8_t (&aPSKc)[kSizePSKc]);
 
     /**
      * This method unsets Thread PSKc to the dataset.
-     *
      */
     void UnsetPSKc(void);
 
@@ -296,12 +285,12 @@
     ThreadTLV & End(void) { return const_cast<ThreadTLV &>(const_cast<const OperationalDataset *>(this)->End()); }
     void Remove(uint8_t aType);
     void Remove(ThreadTLV & aTlv);
-    ThreadTLV * MakeRoom(uint8_t aType, uint8_t aSize);
+    ThreadTLV * MakeRoom(uint8_t aType, size_t aSize);
     bool Has(uint8_t aType) const { return Locate(aType) != nullptr; }
 
     uint8_t mData[kSizeOperationalDataset];
-    uint8_t mLength;
+    uint8_t mLength = 0;
 };
 
 } // namespace Thread
-}; // namespace chip
+} // namespace chip
diff --git a/src/lib/support/tests/TestThreadOperationalDataset.cpp b/src/lib/support/tests/TestThreadOperationalDataset.cpp
index d9e13c8..b37cde4 100644
--- a/src/lib/support/tests/TestThreadOperationalDataset.cpp
+++ b/src/lib/support/tests/TestThreadOperationalDataset.cpp
@@ -30,11 +30,9 @@
     static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); }
     static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); }
 
-    static Thread::OperationalDataset dataset;
+    Thread::OperationalDataset dataset;
 };
 
-Thread::OperationalDataset TestThreadOperationalDataset::dataset;
-
 TEST_F(TestThreadOperationalDataset, TestInit)
 {
 
@@ -103,6 +101,10 @@
     EXPECT_EQ(dataset.SetMasterKey(kMasterKey), CHIP_NO_ERROR);
     EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_NO_ERROR);
     EXPECT_EQ(memcmp(masterKey, kMasterKey, sizeof(kMasterKey)), 0);
+
+    dataset.UnsetMasterKey();
+    EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_ERROR_TLV_TAG_NOT_FOUND);
+    EXPECT_EQ(dataset.SetMasterKey(masterKey), CHIP_NO_ERROR);
 }
 
 TEST_F(TestThreadOperationalDataset, TestMeshLocalPrefix)
@@ -129,6 +131,7 @@
     EXPECT_EQ(dataset.SetNetworkName("0123456789abcdef"), CHIP_NO_ERROR);
     EXPECT_EQ(dataset.SetNetworkName("0123456789abcdefg"), CHIP_ERROR_INVALID_STRING_LENGTH);
     EXPECT_EQ(dataset.SetNetworkName(""), CHIP_ERROR_INVALID_STRING_LENGTH);
+    EXPECT_EQ(dataset.SetNetworkName(nullptr), CHIP_ERROR_INVALID_ARGUMENT);
 }
 
 TEST_F(TestThreadOperationalDataset, TestPanId)
@@ -152,25 +155,7 @@
     EXPECT_EQ(dataset.SetPSKc(kPSKc), CHIP_NO_ERROR);
     EXPECT_EQ(dataset.GetPSKc(pskc), CHIP_NO_ERROR);
     EXPECT_FALSE(memcmp(pskc, kPSKc, sizeof(kPSKc)));
-}
 
-TEST_F(TestThreadOperationalDataset, TestUnsetMasterKey)
-{
-
-    uint8_t masterKey[Thread::kSizeMasterKey] = { 0 };
-
-    EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_NO_ERROR);
-    dataset.UnsetMasterKey();
-    EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_ERROR_TLV_TAG_NOT_FOUND);
-    EXPECT_EQ(dataset.SetMasterKey(masterKey), CHIP_NO_ERROR);
-}
-
-TEST_F(TestThreadOperationalDataset, TestUnsetPSKc)
-{
-
-    uint8_t pskc[Thread::kSizePSKc] = { 0 };
-
-    EXPECT_EQ(dataset.GetPSKc(pskc), CHIP_NO_ERROR);
     dataset.UnsetPSKc();
     EXPECT_EQ(dataset.GetPSKc(pskc), CHIP_ERROR_TLV_TAG_NOT_FOUND);
     EXPECT_EQ(dataset.SetPSKc(pskc), CHIP_NO_ERROR);
@@ -178,45 +163,19 @@
 
 TEST_F(TestThreadOperationalDataset, TestClear)
 {
-
     {
-        uint64_t activeTimestamp;
-        EXPECT_EQ(dataset.GetActiveTimestamp(activeTimestamp), CHIP_NO_ERROR);
-    }
-
-    {
-        uint16_t channel;
-        EXPECT_EQ(dataset.GetChannel(channel), CHIP_NO_ERROR);
-    }
-
-    {
-        uint8_t extendedPanId[Thread::kSizeExtendedPanId] = { 0 };
-        EXPECT_EQ(dataset.GetExtendedPanId(extendedPanId), CHIP_NO_ERROR);
-    }
-
-    {
+        EXPECT_EQ(dataset.SetActiveTimestamp(123), CHIP_NO_ERROR);
+        EXPECT_EQ(dataset.SetChannel(5), CHIP_NO_ERROR);
+        uint8_t extendedPanId[Thread::kSizeExtendedPanId] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+        EXPECT_EQ(dataset.SetExtendedPanId(extendedPanId), CHIP_NO_ERROR);
         uint8_t masterKey[Thread::kSizeMasterKey] = { 0 };
-        EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_NO_ERROR);
-    }
-
-    {
+        EXPECT_EQ(dataset.SetMasterKey(masterKey), CHIP_NO_ERROR);
         uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix] = { 0 };
-        EXPECT_EQ(dataset.GetMeshLocalPrefix(meshLocalPrefix), CHIP_NO_ERROR);
-    }
-
-    {
-        char networkName[Thread::kSizeNetworkName + 1] = { 0 };
-        EXPECT_EQ(dataset.GetNetworkName(networkName), CHIP_NO_ERROR);
-    }
-
-    {
-        uint16_t panid;
-        EXPECT_EQ(dataset.GetPanId(panid), CHIP_NO_ERROR);
-    }
-
-    {
+        EXPECT_EQ(dataset.SetMeshLocalPrefix(meshLocalPrefix), CHIP_NO_ERROR);
+        EXPECT_EQ(dataset.SetNetworkName("w00tw00t"), CHIP_NO_ERROR);
+        EXPECT_EQ(dataset.SetPanId(0x4242), CHIP_NO_ERROR);
         uint8_t pskc[Thread::kSizePSKc] = { 0 };
-        EXPECT_EQ(dataset.GetPSKc(pskc), CHIP_NO_ERROR);
+        EXPECT_EQ(dataset.SetPSKc(pskc), CHIP_NO_ERROR);
     }
 
     dataset.Clear();
@@ -262,4 +221,103 @@
     }
 }
 
+TEST_F(TestThreadOperationalDataset, TestExampleDataset)
+{
+    const uint8_t example[] = {
+        0x0e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // Active Timestamp 1
+        0x00, 0x03, 0x00, 0x00, 0x0f,                               // Channel 15
+        0x35, 0x04, 0x07, 0xff, 0xf8, 0x00,                         // Channel Mask 0x07fff800
+        0x02, 0x08, 0x39, 0x75, 0x8e, 0xc8, 0x14, 0x4b, 0x07, 0xfb, // Ext PAN ID 39758ec8144b07fb
+        0x07, 0x08, 0xfd, 0xf1, 0xf1, 0xad, 0xd0, 0x79, 0x7d, 0xc0, // Mesh Local Prefix fdf1:f1ad:d079:7dc0::/64
+        0x05, 0x10, 0xf3, 0x66, 0xce, 0xc7, 0xa4, 0x46, 0xba, 0xb9, 0x78, 0xd9, 0x0d, 0x27, 0xab, 0xe3, 0x8f, 0x23, // Network Key
+        0x03, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x2d, 0x35, 0x39, 0x33, 0x38, // "OpenThread-5938"
+        0x01, 0x02, 0x59, 0x38,                                                                               // PAN ID : 0x5938
+        0x04, 0x10, 0x3c, 0xa6, 0x7c, 0x96, 0x9e, 0xfb, 0x0d, 0x0c, 0x74, 0xa4, 0xd8, 0xee, 0x92, 0x3b, 0x57, 0x6c, // PKSc
+        0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8, // Security Policy
+    };
+    EXPECT_EQ(dataset.Init(ByteSpan(example)), CHIP_NO_ERROR);
+
+    uint64_t activeTimestamp;
+    EXPECT_EQ(dataset.GetActiveTimestamp(activeTimestamp), CHIP_NO_ERROR);
+    EXPECT_EQ(activeTimestamp, 1u);
+
+    uint16_t channel;
+    EXPECT_EQ(dataset.GetChannel(channel), CHIP_NO_ERROR);
+    EXPECT_EQ(channel, 15u);
+
+    uint8_t extPanId[Thread::kSizeExtendedPanId];
+    EXPECT_EQ(dataset.GetExtendedPanId(extPanId), CHIP_NO_ERROR);
+    const uint8_t expectedExtPanId[] = { 0x39, 0x75, 0x8e, 0xc8, 0x14, 0x4b, 0x07, 0xfb };
+    EXPECT_TRUE(ByteSpan(extPanId).data_equal(ByteSpan(expectedExtPanId)));
+
+    uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix];
+    EXPECT_EQ(dataset.GetMeshLocalPrefix(meshLocalPrefix), CHIP_NO_ERROR);
+    const uint8_t expectedMeshLocalPrefix[] = { 0xfd, 0xf1, 0xf1, 0xad, 0xd0, 0x79, 0x7d, 0xc0 };
+    EXPECT_TRUE(ByteSpan(meshLocalPrefix).data_equal(ByteSpan(expectedMeshLocalPrefix)));
+
+    uint8_t masterKey[Thread::kSizeMasterKey];
+    EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_NO_ERROR);
+    const uint8_t expectedMasterKey[] = { 0xf3, 0x66, 0xce, 0xc7, 0xa4, 0x46, 0xba, 0xb9,
+                                          0x78, 0xd9, 0x0d, 0x27, 0xab, 0xe3, 0x8f, 0x23 };
+    EXPECT_TRUE(ByteSpan(masterKey).data_equal(ByteSpan(expectedMasterKey)));
+
+    char networkName[Thread::kSizeNetworkName + 1];
+    EXPECT_EQ(dataset.GetNetworkName(networkName), CHIP_NO_ERROR);
+    EXPECT_EQ(strncmp(networkName, "OpenThread-5938", sizeof(networkName)), 0);
+
+    uint16_t panId;
+    EXPECT_EQ(dataset.GetPanId(panId), CHIP_NO_ERROR);
+    EXPECT_EQ(panId, 0x5938u);
+
+    uint8_t pksc[Thread::kSizePSKc];
+    EXPECT_EQ(dataset.GetPSKc(pksc), CHIP_NO_ERROR);
+    const uint8_t expectedPksc[] = {
+        0x3c, 0xa6, 0x7c, 0x96, 0x9e, 0xfb, 0x0d, 0x0c, 0x74, 0xa4, 0xd8, 0xee, 0x92, 0x3b, 0x57, 0x6c
+    };
+    EXPECT_TRUE(ByteSpan(pksc).data_equal(ByteSpan(expectedPksc)));
+}
+
+TEST_F(TestThreadOperationalDataset, TestInvalidExampleDataset)
+{
+    const uint8_t invalid[] = {
+        0x0e, 0x01, 0x01,                                                                                     // Active Timestamp
+        0x00, 0x01, 0x0f,                                                                                     // Channel
+        0x35, 0x00,                                                                                           // Channel Mask
+        0x02, 0x09, 0x39, 0x75, 0x8e, 0xc8, 0x14, 0x4b, 0x07, 0xfb, 0xff,                                     // Ext PAN ID
+        0x07, 0x01, 0x01,                                                                                     // Mesh Local Prefix
+        0x05, 0x0f, 0xf3, 0x66, 0xce, 0xc7, 0xa4, 0x46, 0xba, 0xb9, 0x78, 0xd9, 0x0d, 0x27, 0xab, 0xe3, 0x8f, // Network Key
+        0x03, 0x11, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x2d, 0x35, 0x39, 0x33, 0x38, 0xff, 0xff, // Name
+        0x01, 0x01, 0xff,                                                                                                 // PAN ID
+        0x04, 0x01, 0x3c,                                                                                                 // PKSc
+        0x0c, 0x01, 0x01, // Security Policy
+    };
+
+    // The overall TLV structure is valid, but all TLVs have invalid sizes
+    EXPECT_EQ(dataset.Init(ByteSpan(invalid)), CHIP_NO_ERROR);
+
+    uint64_t activeTimestamp;
+    EXPECT_EQ(dataset.GetActiveTimestamp(activeTimestamp), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+    uint16_t channel;
+    EXPECT_EQ(dataset.GetChannel(channel), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+    ByteSpan extPanId;
+    EXPECT_EQ(dataset.GetExtendedPanIdAsByteSpan(extPanId), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+    uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix];
+    EXPECT_EQ(dataset.GetMeshLocalPrefix(meshLocalPrefix), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+    uint8_t masterKey[Thread::kSizeMasterKey];
+    EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+    char networkName[Thread::kSizeNetworkName + 1];
+    EXPECT_EQ(dataset.GetNetworkName(networkName), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+    uint16_t panId;
+    EXPECT_EQ(dataset.GetPanId(panId), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+    uint8_t pksc[Thread::kSizePSKc];
+    EXPECT_EQ(dataset.GetPSKc(pksc), CHIP_ERROR_INVALID_TLV_ELEMENT);
+}
+
 } // namespace