diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp index 24a86a61e..4b9f76089 100644 --- a/src/core/thread/mle_types.hpp +++ b/src/core/thread/mle_types.hpp @@ -666,7 +666,10 @@ public: * @retval TRUE If the Router ID bit is set in the mask. * @retval FALSE If the Router ID bit is not set in the mask. */ - bool IsAllocated(uint8_t aRouterId) const { return (mMask[aRouterId / 8] & MaskFor(aRouterId)) != 0; } + bool IsAllocated(uint8_t aRouterId) const + { + return (aRouterId <= kMaxRouterId) && ((mMask[aRouterId / 8] & MaskFor(aRouterId)) != 0); + } /** * Sets a given Router ID in the mask. diff --git a/src/core/thread/router_table.hpp b/src/core/thread/router_table.hpp index 824c92f6d..e8c3b8860 100644 --- a/src/core/thread/router_table.hpp +++ b/src/core/thread/router_table.hpp @@ -465,7 +465,10 @@ private: // remaining reuse delay time (in seconds). RouterIdMap(void) { Clear(); } - bool IsAllocated(uint8_t aRouterId) const { return (mIndexes[aRouterId] & kAllocatedFlag); } + bool IsAllocated(uint8_t aRouterId) const + { + return (aRouterId <= Mle::kMaxRouterId) && ((mIndexes[aRouterId] & kAllocatedFlag) != 0); + } uint8_t GetIndex(uint8_t aRouterId) const { return (mIndexes[aRouterId] & kIndexMask); } void SetIndex(uint8_t aRouterId, uint8_t aIndex) { mIndexes[aRouterId] = kAllocatedFlag | aIndex; } bool CanAllocate(uint8_t aRouterId) const { return (mIndexes[aRouterId] == 0); } diff --git a/tests/unit/test_mle.cpp b/tests/unit/test_mle.cpp index 186c35a36..3e4f60935 100644 --- a/tests/unit/test_mle.cpp +++ b/tests/unit/test_mle.cpp @@ -37,6 +37,7 @@ #include "thread/mle_tlvs.hpp" #include "thread/mle_types.hpp" #include "thread/network_data_leader.hpp" +#include "thread/router_table.hpp" namespace ot { @@ -849,15 +850,67 @@ void TestLeaderWeightCalculation(void) #endif // #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE +void TestRouterIdMask(void) +{ + Mle::RouterIdMask mask; + + mask.Clear(); + VerifyOrQuit(mask.IsValid()); + VerifyOrQuit(mask.DetermineAllocatedCount() == 0); + + for (uint16_t routerId = 0; routerId <= 255; routerId++) + { + VerifyOrQuit(!mask.IsAllocated(static_cast(routerId))); + } + + mask.Add(0); + mask.Add(10); + mask.Add(Mle::kMaxRouterId); + + VerifyOrQuit(mask.IsAllocated(0)); + VerifyOrQuit(mask.IsAllocated(10)); + VerifyOrQuit(mask.IsAllocated(Mle::kMaxRouterId)); + VerifyOrQuit(!mask.IsAllocated(1)); + VerifyOrQuit(!mask.IsAllocated(61)); + + for (uint16_t routerId = Mle::kMaxRouterId + 1; routerId <= 255; routerId++) + { + VerifyOrQuit(!mask.IsAllocated(static_cast(routerId))); + } + + mask.Remove(10); + VerifyOrQuit(!mask.IsAllocated(10)); + + printf("TestRouterIdMask passed\n"); +} + +#if OPENTHREAD_FTD +void TestRouterTableRouterIdBounds(void) +{ + Instance *instance = static_cast(testInitInstance()); + RouterTable &routerTable = instance->Get(); + + for (uint16_t routerId = 0; routerId <= 255; routerId++) + { + VerifyOrQuit(!routerTable.IsAllocated(static_cast(routerId))); + } + + testFreeInstance(instance); + printf("TestRouterTableRouterIdBounds passed\n"); +} +#endif + } // namespace ot int main(void) { ot::TestDeviceMode(); + ot::TestRouterIdMask(); ot::UnitTester::TestChildIdResponseNetworkDataHandling(); #if OPENTHREAD_FTD ot::UnitTester::TestTxChallengeTable(); + ot::TestRouterTableRouterIdBounds(); #endif #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE