From f8b639351e498b7f7e67246c82bb715ec40bc044 Mon Sep 17 00:00:00 2001 From: Karsten Sperling Date: Tue, 21 Oct 2025 13:39:54 +1300 Subject: [PATCH 1/3] Remove AttributeList from Device Layer It was only used in a single place and probably didn't belong in the device layer in the first place. Use a Span instead for DeviceInforProvider::SetUserLabelList. Also simplify DeviceInforProvider::ClearUserLabelList(). --- src/BUILD.gn | 1 - .../user-label-server/user-label-cluster.cpp | 27 ++-- src/include/platform/AttributeList.h | 142 ------------------ src/include/platform/DeviceInfoProvider.h | 4 +- src/include/platform/PlatformManager.h | 1 - src/include/platform/tests/BUILD.gn | 28 ---- .../platform/tests/TestAttributeList.cpp | 132 ---------------- src/platform/DeviceInfoProvider.cpp | 26 +--- 8 files changed, 17 insertions(+), 344 deletions(-) delete mode 100644 src/include/platform/AttributeList.h delete mode 100644 src/include/platform/tests/BUILD.gn delete mode 100644 src/include/platform/tests/TestAttributeList.cpp diff --git a/src/BUILD.gn b/src/BUILD.gn index 14eb5e836c4d9a..08ea030e415ff2 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -83,7 +83,6 @@ if (chip_build_tests) { "${chip_root}/src/crypto/tests", "${chip_root}/src/data-model-providers/codedriven/endpoint/tests", "${chip_root}/src/inet/tests", - "${chip_root}/src/include/platform/tests", "${chip_root}/src/lib/address_resolve/tests", "${chip_root}/src/app/server-cluster/tests", "${chip_root}/src/lib/asn1/tests", diff --git a/src/app/clusters/user-label-server/user-label-cluster.cpp b/src/app/clusters/user-label-server/user-label-cluster.cpp index 8052183c309a41..83c0b03969109b 100644 --- a/src/app/clusters/user-label-server/user-label-cluster.cpp +++ b/src/app/clusters/user-label-server/user-label-cluster.cpp @@ -19,6 +19,8 @@ #include #include +#include + namespace chip::app::Clusters { using namespace UserLabel; @@ -73,19 +75,6 @@ bool IsValidLabelEntry(const Structs::LabelStruct::Type & entry) return (entry.label.size() <= kMaxLabelSize) && (entry.value.size() <= kMaxValueSize); } -bool IsValidLabelEntryList(const LabelList::TypeInfo::DecodableType & list) -{ - auto iter = list.begin(); - while (iter.Next()) - { - if (!IsValidLabelEntry(iter.GetValue())) - { - return false; - } - } - return true; -} - CHIP_ERROR WriteLabelList(const ConcreteDataAttributePath & path, AttributeValueDecoder & decoder) { DeviceLayer::DeviceInfoProvider * provider = DeviceLayer::GetDeviceInfoProvider(); @@ -96,20 +85,22 @@ CHIP_ERROR WriteLabelList(const ConcreteDataAttributePath & path, AttributeValue if (!path.IsListItemOperation()) { - DeviceLayer::AttributeList labelList; + size_t numLabels = 0; + std::array labels; LabelList::TypeInfo::DecodableType decodablelist; ReturnErrorOnFailure(decoder.Decode(decodablelist)); - VerifyOrReturnError(IsValidLabelEntryList(decodablelist), CHIP_IM_GLOBAL_STATUS(ConstraintError)); - auto iter = decodablelist.begin(); while (iter.Next()) { - ReturnErrorOnFailure(labelList.add(iter.GetValue())); + auto & label = iter.GetValue(); + VerifyOrReturnError(IsValidLabelEntry(label), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + VerifyOrReturnError(numLabels < labels.size(), CHIP_ERROR_NO_MEMORY); + labels[numLabels++] = label; } ReturnErrorOnFailure(iter.GetStatus()); - return provider->SetUserLabelList(endpoint, labelList); + return provider->SetUserLabelList(endpoint, Span(labels.data(), numLabels)); } if (path.mListOp == ConcreteDataAttributePath::ListOperation::AppendItem) diff --git a/src/include/platform/AttributeList.h b/src/include/platform/AttributeList.h deleted file mode 100644 index 81fe3d12420a23..00000000000000 --- a/src/include/platform/AttributeList.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * This is a list of attribute. Each entry is an attribute of type T. - */ - -#pragma once - -#include -#include - -namespace chip { -namespace DeviceLayer { - -template -class AttributeList -{ -public: - /* The iterator */ - class Iterator - { - public: - Iterator(const AttributeList * AttributeList, int index); - const T & operator*() const; - Iterator & operator++(); - bool operator!=(const Iterator & other) const; - bool operator==(const Iterator & other) const; - - private: - const AttributeList * mAttributeListPtr; - int mIndex = -1; - }; - - AttributeList() = default; - ~AttributeList() { mSize = 0; } - - CHIP_ERROR add(const T & label); - - size_t size() const; - const T & operator[](int index) const; - - Iterator begin() const; - Iterator end() const; - -private: - T mList[N]; - int mSize = 0; -}; - -/* - * AttributeList methods - **/ -template -inline CHIP_ERROR AttributeList::add(const T & label) -{ - if (mSize == N) - { - return CHIP_ERROR_NO_MEMORY; - } - - // add the new element - mList[mSize] = label; - ++mSize; - return CHIP_NO_ERROR; -} - -template -inline size_t AttributeList::size() const -{ - return static_cast(mSize); -} - -template -inline const T & AttributeList::operator[](int index) const -{ - VerifyOrDie(index < mSize); - return mList[index]; -} - -template -inline typename AttributeList::Iterator AttributeList::begin() const -{ - return AttributeList::Iterator{ this, 0 }; -} - -template -inline typename AttributeList::Iterator AttributeList::end() const -{ - return AttributeList::Iterator{ this, mSize }; -} - -/* - * Iterator methods - **/ -template -inline AttributeList::Iterator::Iterator(const AttributeList * pAttributeList, int index) : - mAttributeListPtr(pAttributeList), mIndex(index) -{} - -template -inline const T & AttributeList::Iterator::operator*() const -{ - return mAttributeListPtr->operator[](mIndex); -} - -template -inline typename AttributeList::Iterator & AttributeList::Iterator::operator++() -{ - ++mIndex; - return *this; -} - -template -inline bool AttributeList::Iterator::operator!=(const AttributeList::Iterator & other) const -{ - return !(*this == other); -} - -template -inline bool AttributeList::Iterator::operator==(const AttributeList::Iterator & other) const -{ - return mAttributeListPtr == other.mAttributeListPtr && mIndex == other.mIndex; -} - -} // namespace DeviceLayer -} // namespace chip diff --git a/src/include/platform/DeviceInfoProvider.h b/src/include/platform/DeviceInfoProvider.h index 33ff9b4424b536..fcd3bd3b418745 100644 --- a/src/include/platform/DeviceInfoProvider.h +++ b/src/include/platform/DeviceInfoProvider.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace chip { namespace DeviceLayer { @@ -101,7 +101,7 @@ class DeviceInfoProvider * @return CHIP_NO_ERROR on success. * @return CHIP_ERROR if an error occurs. */ - CHIP_ERROR SetUserLabelList(EndpointId endpoint, const AttributeList & labelList); + CHIP_ERROR SetUserLabelList(EndpointId endpoint, Span labelList); /** * @brief Clears the user label list for a specified endpoint. diff --git a/src/include/platform/PlatformManager.h b/src/include/platform/PlatformManager.h index 8470e32642d5fd..8f2c086916c9fe 100644 --- a/src/include/platform/PlatformManager.h +++ b/src/include/platform/PlatformManager.h @@ -23,7 +23,6 @@ #pragma once -#include #include #include #include diff --git a/src/include/platform/tests/BUILD.gn b/src/include/platform/tests/BUILD.gn deleted file mode 100644 index ccfeab22b1313a..00000000000000 --- a/src/include/platform/tests/BUILD.gn +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") - -import("${chip_root}/build/chip/chip_test_suite.gni") - -chip_test_suite("tests") { - output_name = "libIncludePlatformTests" - - test_sources = [ "TestAttributeList.cpp" ] - - cflags = [ "-Wconversion" ] - - public_deps = [ "${chip_root}/src/platform" ] -} diff --git a/src/include/platform/tests/TestAttributeList.cpp b/src/include/platform/tests/TestAttributeList.cpp deleted file mode 100644 index ab34f0f75cc7f7..00000000000000 --- a/src/include/platform/tests/TestAttributeList.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include - -#include - -namespace chip { -namespace DeviceLayer { - -class TestAttributeList : public ::testing::Test -{ -}; - -// Test an empty list -TEST_F(TestAttributeList, TestEmpty) -{ - AttributeList list; - EXPECT_EQ(list.size(), 0u); - EXPECT_EQ(list.begin(), list.end()); - - // This will abort/die - // list[0]; -} - -// Test adding elements and overflow -TEST_F(TestAttributeList, TestAddAndOverflow) -{ - AttributeList list; - - EXPECT_EQ(list.add(10), CHIP_NO_ERROR); - EXPECT_EQ(list.size(), 1u); - - EXPECT_EQ(list.add(20), CHIP_NO_ERROR); - EXPECT_EQ(list.size(), 2u); - - EXPECT_EQ(list.add(30), CHIP_NO_ERROR); - EXPECT_EQ(list.size(), 3u); - - EXPECT_EQ(list.add(40), CHIP_NO_ERROR); - EXPECT_EQ(list.size(), 4u); - - EXPECT_EQ(list.add(50), CHIP_NO_ERROR); - EXPECT_EQ(list.size(), 5u); - - EXPECT_EQ(list.add(60), CHIP_ERROR_NO_MEMORY); - EXPECT_EQ(list.size(), 5u); -} - -// Test operator[] -TEST_F(TestAttributeList, TestIndexing) -{ - AttributeList list; - - EXPECT_EQ(list.add(10), CHIP_NO_ERROR); - EXPECT_EQ(list.add(20), CHIP_NO_ERROR); - EXPECT_EQ(list.add(30), CHIP_NO_ERROR); - - ASSERT_EQ(list.size(), 3u); - - EXPECT_EQ(list[0], 10); - EXPECT_EQ(list[1], 20); - EXPECT_EQ(list[2], 30); - - // This will abort/die - // list[3]; -} - -// Test the iterator methods -TEST_F(TestAttributeList, TestIterator) -{ - AttributeList list; - - EXPECT_EQ(list.begin(), list.end()); - - EXPECT_EQ(list.add(10), CHIP_NO_ERROR); - EXPECT_NE(list.begin(), list.end()); - - EXPECT_EQ(list.add(20), CHIP_NO_ERROR); - EXPECT_EQ(list.add(30), CHIP_NO_ERROR); - - ASSERT_EQ(list.size(), 3u); - - auto it = list.begin(); - EXPECT_EQ(*it, 10); - - ++it; - EXPECT_NE(it, list.end()); - EXPECT_EQ(*it, 20); - - ++it; - EXPECT_EQ(*it, 30); - - ++it; - EXPECT_EQ(it, list.end()); -}; - -// Test range-based for loop -TEST_F(TestAttributeList, TestRangeBasedFor) -{ - AttributeList list; - EXPECT_EQ(list.add(10), CHIP_NO_ERROR); - EXPECT_EQ(list.add(20), CHIP_NO_ERROR); - EXPECT_EQ(list.add(30), CHIP_NO_ERROR); - - int expected_values[] = { 10, 20, 30 }; - int i = 0; - for (const auto & val : list) - { - ASSERT_LT(i, 3); - EXPECT_EQ(val, expected_values[i]); - i++; - } - EXPECT_EQ(i, 3); -} - -// Test iterators from different lists -TEST_F(TestAttributeList, TestIteratorFromDifferentLists) -{ - AttributeList list1; - AttributeList list2; - - // Both iterators will have index 0, but point to different lists. - // They should not be equal. - EXPECT_NE(list1.begin(), list2.begin()); - - EXPECT_EQ(list1.add(10), CHIP_NO_ERROR); - EXPECT_EQ(list2.add(20), CHIP_NO_ERROR); - - // Both iterators will have index 0, but point to different lists. - EXPECT_NE(list1.begin(), list2.begin()); -} - -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/DeviceInfoProvider.cpp b/src/platform/DeviceInfoProvider.cpp index 28191cd4f82352..105313a1445452 100644 --- a/src/platform/DeviceInfoProvider.cpp +++ b/src/platform/DeviceInfoProvider.cpp @@ -35,15 +35,16 @@ DeviceInfoProvider * gDeviceInfoProvider = nullptr; } // namespace -CHIP_ERROR DeviceInfoProvider::SetUserLabelList(EndpointId endpoint, - const AttributeList & labelList) +CHIP_ERROR DeviceInfoProvider::SetUserLabelList(EndpointId endpoint, Span labelList) { size_t index = 0; size_t previousLength = 0; size_t currentLength = labelList.size(); + VerifyOrReturnError(labelList.size() <= kMaxUserLabelListLength, CHIP_ERROR_NO_MEMORY); + CHIP_ERROR err = GetUserLabelLength(endpoint, previousLength); - VerifyOrReturnError(err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND || err == CHIP_NO_ERROR, err); + VerifyOrReturnError(err == CHIP_NO_ERROR || err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, err); ReturnErrorOnFailure(SetUserLabelLength(endpoint, currentLength)); @@ -64,18 +65,7 @@ CHIP_ERROR DeviceInfoProvider::SetUserLabelList(EndpointId endpoint, CHIP_ERROR DeviceInfoProvider::ClearUserLabelList(EndpointId endpoint) { - size_t length; - - CHIP_ERROR err = GetUserLabelLength(endpoint, length); - VerifyOrReturnError(err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, CHIP_NO_ERROR); - ReturnErrorOnFailure(err); - - for (size_t i = 0; i < length; i++) - { - ReturnErrorOnFailure(DeleteUserLabelAt(endpoint, i)); - } - - return CHIP_NO_ERROR; + return SetUserLabelList(endpoint, Span()); } CHIP_ERROR DeviceInfoProvider::AppendUserLabel(EndpointId endpoint, const UserLabelType & label) @@ -84,11 +74,7 @@ CHIP_ERROR DeviceInfoProvider::AppendUserLabel(EndpointId endpoint, const UserLa // Fetch current list length ReturnErrorOnFailure(GetUserLabelLength(endpoint, length)); - - if (length >= kMaxUserLabelListLength) - { - return CHIP_ERROR_NO_MEMORY; - } + VerifyOrReturnError(length < kMaxUserLabelListLength, CHIP_ERROR_NO_MEMORY); // Add the new entry to the list ReturnErrorOnFailure(SetUserLabelLength(endpoint, length + 1)); From 77b277cac58e9a50818d99fe947bc152bcef1d1a Mon Sep 17 00:00:00 2001 From: Karsten Sperling Date: Wed, 29 Oct 2025 14:29:20 +1300 Subject: [PATCH 2/3] Add missing const to Span type --- src/platform/DeviceInfoProvider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/DeviceInfoProvider.cpp b/src/platform/DeviceInfoProvider.cpp index 105313a1445452..914543a6e54c43 100644 --- a/src/platform/DeviceInfoProvider.cpp +++ b/src/platform/DeviceInfoProvider.cpp @@ -65,7 +65,7 @@ CHIP_ERROR DeviceInfoProvider::SetUserLabelList(EndpointId endpoint, Span()); + return SetUserLabelList(endpoint, Span()); } CHIP_ERROR DeviceInfoProvider::AppendUserLabel(EndpointId endpoint, const UserLabelType & label) From e10370ff61e0e1f0004da9a5880ac6ec5c0cd7fa Mon Sep 17 00:00:00 2001 From: Karsten Sperling Date: Fri, 7 Nov 2025 09:56:26 +1300 Subject: [PATCH 3/3] Move max size constants into the header and add more tests --- .../tests/TestUserLabelCluster.cpp | 92 ++++++++++++++++++- .../user-label-server/user-label-cluster.cpp | 5 +- .../user-label-server/user-label-cluster.h | 4 + 3 files changed, 95 insertions(+), 6 deletions(-) diff --git a/src/app/clusters/user-label-server/tests/TestUserLabelCluster.cpp b/src/app/clusters/user-label-server/tests/TestUserLabelCluster.cpp index 2a500ec964d390..8cbd2fb8955426 100644 --- a/src/app/clusters/user-label-server/tests/TestUserLabelCluster.cpp +++ b/src/app/clusters/user-label-server/tests/TestUserLabelCluster.cpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace { @@ -35,21 +36,55 @@ using namespace chip::app::Clusters::UserLabel; using namespace chip::app::Clusters::UserLabel::Attributes; using namespace chip::Test; +// Mock DeviceInfoProvider for testing +class MockDeviceInfoProvider : public DeviceLayer::DeviceInfoProvider +{ +public: + MockDeviceInfoProvider() = default; + ~MockDeviceInfoProvider() override = default; + + FixedLabelIterator * IterateFixedLabel(EndpointId endpoint) override { return nullptr; } + UserLabelIterator * IterateUserLabel(EndpointId endpoint) override { return nullptr; } + SupportedCalendarTypesIterator * IterateSupportedCalendarTypes() override { return nullptr; } + SupportedLocalesIterator * IterateSupportedLocales() override { return nullptr; } + +protected: + // Simple no-op implementations - we only need these to return success + // so that the cluster's validation logic can be tested + CHIP_ERROR SetUserLabelLength(EndpointId endpoint, size_t val) override { return CHIP_NO_ERROR; } + CHIP_ERROR GetUserLabelLength(EndpointId endpoint, size_t & val) override + { + val = 0; + return CHIP_NO_ERROR; + } + CHIP_ERROR SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel) override { return CHIP_NO_ERROR; } + CHIP_ERROR DeleteUserLabelAt(EndpointId endpoint, size_t index) override { return CHIP_NO_ERROR; } +}; + struct TestUserLabelCluster : public ::testing::Test { static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); } static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } - void SetUp() override { ASSERT_EQ(userLabel.Startup(context), CHIP_NO_ERROR); } + void SetUp() override + { + DeviceLayer::SetDeviceInfoProvider(&mDeviceInfoProvider); + ASSERT_EQ(userLabel.Startup(context), CHIP_NO_ERROR); + } - void TearDown() override { userLabel.Shutdown(); } + void TearDown() override + { + userLabel.Shutdown(); + DeviceLayer::SetDeviceInfoProvider(nullptr); + } TestUserLabelCluster() : context(testContext.Create()), userLabel(kRootEndpointId) {} chip::Test::TestServerClusterContext testContext; ServerClusterContext context; UserLabelCluster userLabel; + MockDeviceInfoProvider mDeviceInfoProvider; }; } // namespace @@ -83,3 +118,56 @@ TEST_F(TestUserLabelCluster, ReadAttributeTest) ASSERT_GT(it.GetValue().label.size(), 0u); } } + +TEST_F(TestUserLabelCluster, WriteValidLabelListTest) +{ + ClusterTester tester(userLabel); + Structs::LabelStruct::Type labels[] = { + { .label = "room"_span, .value = "bedroom 2"_span }, + { .label = "orientation"_span, .value = "North"_span }, + }; + ASSERT_EQ(tester.WriteAttribute(LabelList::Id, DataModel::List(labels)), CHIP_NO_ERROR); +} + +TEST_F(TestUserLabelCluster, WriteLabelWithLabelTooLongTest) +{ + ClusterTester tester(userLabel); + constexpr auto tooLongLabel = "this_label_is_way_too_long"_span; + static_assert(tooLongLabel.size() > UserLabelCluster::kMaxLabelSize); + Structs::LabelStruct::Type labels[] = { + { .label = tooLongLabel, .value = "value"_span }, + }; + ASSERT_EQ(tester.WriteAttribute(LabelList::Id, DataModel::List(labels)), CHIP_IM_GLOBAL_STATUS(ConstraintError)); +} + +TEST_F(TestUserLabelCluster, WriteLabelWithValueTooLongTest) +{ + ClusterTester tester(userLabel); + constexpr auto tooLongValue = "this_value_is_way_too_long"_span; + static_assert(tooLongValue.size() > UserLabelCluster::kMaxValueSize); + Structs::LabelStruct::Type labels[] = { + { .label = "room"_span, .value = tooLongValue }, + }; + ASSERT_EQ(tester.WriteAttribute(LabelList::Id, DataModel::List(labels)), CHIP_IM_GLOBAL_STATUS(ConstraintError)); +} + +TEST_F(TestUserLabelCluster, WriteEmptyLabelsTest) +{ + ClusterTester tester(userLabel); + Structs::LabelStruct::Type labels[] = { + { .label = ""_span, .value = ""_span }, // empty label and value are allowed per spec + }; + ASSERT_EQ(tester.WriteAttribute(LabelList::Id, DataModel::List(labels)), CHIP_NO_ERROR); +} + +TEST_F(TestUserLabelCluster, WriteMaxSizeLabelListTest) +{ + ClusterTester tester(userLabel); + std::array labels; + for (size_t i = 0; i < labels.size(); i++) + { + labels[i].label = "label"_span; + labels[i].value = "value"_span; + } + ASSERT_EQ(tester.WriteAttribute(LabelList::Id, DataModel::List(labels.data(), labels.size())), CHIP_NO_ERROR); +} diff --git a/src/app/clusters/user-label-server/user-label-cluster.cpp b/src/app/clusters/user-label-server/user-label-cluster.cpp index 83c0b03969109b..65abad0a1ec351 100644 --- a/src/app/clusters/user-label-server/user-label-cluster.cpp +++ b/src/app/clusters/user-label-server/user-label-cluster.cpp @@ -68,11 +68,8 @@ CHIP_ERROR ReadLabelList(EndpointId endpoint, AttributeValueEncoder & encoder) /// Matches constraints on a LabelStruct. bool IsValidLabelEntry(const Structs::LabelStruct::Type & entry) { - constexpr size_t kMaxLabelSize = 16; - constexpr size_t kMaxValueSize = 16; - // NOTE: spec default for label and value is empty, so empty is accepted here - return (entry.label.size() <= kMaxLabelSize) && (entry.value.size() <= kMaxValueSize); + return (entry.label.size() <= UserLabelCluster::kMaxLabelSize) && (entry.value.size() <= UserLabelCluster::kMaxValueSize); } CHIP_ERROR WriteLabelList(const ConcreteDataAttributePath & path, AttributeValueDecoder & decoder) diff --git a/src/app/clusters/user-label-server/user-label-cluster.h b/src/app/clusters/user-label-server/user-label-cluster.h index dd3fe3d757231c..ec42b5ca6382f1 100644 --- a/src/app/clusters/user-label-server/user-label-cluster.h +++ b/src/app/clusters/user-label-server/user-label-cluster.h @@ -37,6 +37,10 @@ class UserLabelCluster : public DefaultServerCluster, public chip::FabricTable:: DataModel::ActionReturnStatus WriteAttribute(const DataModel::WriteAttributeRequest & request, AttributeValueDecoder & decoder) override; CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; + + // Constraints for label entries + static constexpr size_t kMaxLabelSize = 16; + static constexpr size_t kMaxValueSize = 16; }; } // namespace chip::app::Clusters