Skip to content

Commit 2360312

Browse files
lpbeliveau-silabspull[bot]
authored andcommitted
Added check for Size ahead of loop in handler SerializeAdd/Deserialize (default) fized TLV containers and Deserialize error ocndition for extension field sets and scene map
1 parent 09c470b commit 2360312

File tree

5 files changed

+183
-72
lines changed

5 files changed

+183
-72
lines changed

src/app/clusters/scenes/ExtensionFieldSetsImpl.cpp

+25-15
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,29 @@ namespace scenes {
2424

2525
CHIP_ERROR ExtensionFieldSetsImpl::Serialize(TLV::TLVWriter & writer, TLV::Tag structTag) const
2626
{
27-
TLV::TLVType container;
28-
ReturnErrorOnFailure(writer.StartContainer(structTag, TLV::kTLVType_Structure, container));
29-
ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(TagEFS::kFieldSetArrayContainer), TLV::kTLVType_Array, container));
27+
TLV::TLVType structureContainer;
28+
ReturnErrorOnFailure(writer.StartContainer(structTag, TLV::kTLVType_Structure, structureContainer));
29+
TLV::TLVType arrayContainer;
30+
ReturnErrorOnFailure(
31+
writer.StartContainer(TLV::ContextTag(TagEFS::kFieldSetArrayContainer), TLV::kTLVType_Array, arrayContainer));
3032
for (uint8_t i = 0; i < mFieldSetsCount; i++)
3133
{
3234
ReturnErrorOnFailure(mFieldSets[i].Serialize(writer));
3335
}
3436

35-
return writer.EndContainer(container);
36-
return writer.EndContainer(container);
37+
ReturnErrorOnFailure(writer.EndContainer(arrayContainer));
38+
return writer.EndContainer(structureContainer);
3739
}
3840

3941
CHIP_ERROR ExtensionFieldSetsImpl::Deserialize(TLV::TLVReader & reader, TLV::Tag structTag)
4042
{
41-
TLV::TLVType container;
43+
TLV::TLVType structureContainer;
4244
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, structTag));
43-
ReturnErrorOnFailure(reader.EnterContainer(container));
45+
ReturnErrorOnFailure(reader.EnterContainer(structureContainer));
4446

47+
TLV::TLVType arrayContainer;
4548
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::ContextTag(TagEFS::kFieldSetArrayContainer)));
46-
ReturnErrorOnFailure(reader.EnterContainer(container));
49+
ReturnErrorOnFailure(reader.EnterContainer(arrayContainer));
4750

4851
uint8_t i = 0;
4952
CHIP_ERROR err;
@@ -54,19 +57,26 @@ CHIP_ERROR ExtensionFieldSetsImpl::Deserialize(TLV::TLVReader & reader, TLV::Tag
5457
}
5558
mFieldSetsCount = i;
5659

57-
VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
58-
return reader.ExitContainer(container);
60+
if (err != CHIP_END_OF_TLV)
61+
{
62+
if (err == CHIP_NO_ERROR)
63+
return CHIP_ERROR_BUFFER_TOO_SMALL;
64+
65+
return err;
66+
}
67+
68+
ReturnErrorOnFailure(reader.ExitContainer(arrayContainer));
69+
return reader.ExitContainer(structureContainer);
5970
}
6071

6172
void ExtensionFieldSetsImpl::Clear()
6273
{
63-
if (!this->IsEmpty())
74+
75+
for (uint8_t i = 0; i < mFieldSetsCount; i++)
6476
{
65-
for (uint8_t i = 0; i < mFieldSetsCount; i++)
66-
{
67-
mFieldSets[i].Clear();
68-
}
77+
mFieldSets[i].Clear();
6978
}
79+
7080
mFieldSetsCount = 0;
7181
}
7282

src/app/clusters/scenes/SceneTable.h

+5-7
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ class SceneHandler : public IntrusiveListNodeBase<>
6666
/// @param clusterBuffer Buffer to hold the supported cluster IDs, cannot hold more than
6767
/// CHIP_CONFIG_SCENES_MAX_CLUSTERS_PER_SCENE. The function shall use the reduce_size() method in the event it is supporting
6868
/// less than CHIP_CONFIG_SCENES_MAX_CLUSTERS_PER_SCENE clusters.
69-
7069
virtual void GetSupportedClusters(EndpointId endpoint, Span<ClusterId> & clusterBuffer) = 0;
7170

7271
/// @brief Returns whether or not a cluster for scenes is supported on an endpoint
@@ -81,14 +80,13 @@ class SceneHandler : public IntrusiveListNodeBase<>
8180
///
8281
/// @param endpoint[in] Endpoint ID
8382
/// @param extensionFieldSet[in] ExtensionFieldSets provided by the AddScene Command, pre initialized
84-
/// @param cluster[out] Cluster in the Extension field set, filled by the function
8583
/// @param serialisedBytes[out] Buffer to fill from the ExtensionFieldSet in command
8684
/// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise
8785
/// @note Only gets called after the scene-cluster has previously verified that the endpoint,cluster valuer pair is supported by
8886
/// the handler. It is therefore the implementation's reponsibility to also implement the SupportsCluster method.
8987
virtual CHIP_ERROR SerializeAdd(EndpointId endpoint,
9088
const app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType & extensionFieldSet,
91-
ClusterId & cluster, MutableByteSpan & serialisedBytes) = 0;
89+
MutableByteSpan & serialisedBytes) = 0;
9290

9391
/// @brief Called when handling StoreScene, and only if the handler supports the given endpoint and cluster.
9492
///
@@ -98,7 +96,7 @@ class SceneHandler : public IntrusiveListNodeBase<>
9896
/// @param cluster[in] Target Cluster
9997
/// @param serializedBytes[out] Output buffer, data needs to be writen in there and size adjusted to the size of the data
10098
/// written.
101-
99+
///
102100
/// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise
103101
virtual CHIP_ERROR SerializeSave(EndpointId endpoint, ClusterId cluster, MutableByteSpan & serializedBytes) = 0;
104102

@@ -123,6 +121,7 @@ class SceneHandler : public IntrusiveListNodeBase<>
123121
///
124122
/// @param timeMs[in] Transition time in ms to apply the scene
125123
/// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise
124+
/// @note Only gets called for handlers for which SupportsCluster() is true for the given endpoint and cluster.
126125
virtual CHIP_ERROR ApplyScene(EndpointId endpoint, ClusterId cluster, const ByteSpan & serializedBytes,
127126
TransitionTimeMs timeMs) = 0;
128127
};
@@ -219,9 +218,8 @@ class SceneTable
219218

220219
bool operator==(const SceneData & other)
221220
{
222-
return (mNameLength == other.mNameLength && !memcmp(mName, other.mName,mNameLength) &&
223-
(mSceneTransitionTimeMs == other.mSceneTransitionTimeMs) &&
224-
(mExtensionFieldSets == other.mExtensionFieldSets));
221+
return (mNameLength == other.mNameLength && !memcmp(mName, other.mName, mNameLength) &&
222+
(mSceneTransitionTimeMs == other.mSceneTransitionTimeMs) && (mExtensionFieldSets == other.mExtensionFieldSets));
225223
}
226224

227225
void operator=(const SceneData & other)

src/app/clusters/scenes/SceneTableImpl.cpp

+20-15
Original file line numberDiff line numberDiff line change
@@ -176,55 +176,60 @@ struct FabricSceneData : public PersistentData<kPersistentFabricBufferMax>
176176

177177
CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
178178
{
179-
TLV::TLVType container;
180-
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));
179+
TLV::TLVType fabricSceneContainer;
180+
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, fabricSceneContainer));
181181
ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kSceneCount), scene_count));
182-
ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(TagScene::kStorageIDArray), TLV::kTLVType_Array, container));
182+
TLV::TLVType sceneMapContainer;
183+
ReturnErrorOnFailure(
184+
writer.StartContainer(TLV::ContextTag(TagScene::kStorageIDArray), TLV::kTLVType_Array, sceneMapContainer));
183185

184186
// Storing the scene map
185187
for (uint8_t i = 0; i < kMaxScenesPerFabric; i++)
186188
{
187-
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));
189+
TLV::TLVType sceneIdContainer;
190+
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, sceneIdContainer));
188191
ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kEndpointID), (scene_map[i].mEndpointId)));
189192
ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kGroupID), (scene_map[i].mGroupId)));
190193
ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kSceneID), (scene_map[i].mSceneId)));
191-
ReturnErrorOnFailure(writer.EndContainer(container));
194+
ReturnErrorOnFailure(writer.EndContainer(sceneIdContainer));
192195
}
193-
ReturnErrorOnFailure(writer.EndContainer(container));
194-
return writer.EndContainer(container);
196+
ReturnErrorOnFailure(writer.EndContainer(sceneMapContainer));
197+
return writer.EndContainer(fabricSceneContainer);
195198
}
196199

197200
CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
198201
{
199202
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
200203

201-
TLV::TLVType container;
202-
ReturnErrorOnFailure(reader.EnterContainer(container));
204+
TLV::TLVType fabricSceneContainer;
205+
ReturnErrorOnFailure(reader.EnterContainer(fabricSceneContainer));
203206

204207
ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kSceneCount)));
205208
ReturnErrorOnFailure(reader.Get(scene_count));
206209
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::ContextTag(TagScene::kStorageIDArray)));
207-
ReturnErrorOnFailure(reader.EnterContainer(container));
210+
TLV::TLVType sceneMapContainer;
211+
ReturnErrorOnFailure(reader.EnterContainer(sceneMapContainer));
208212

209213
uint8_t i = 0;
210214
CHIP_ERROR err;
211215
while ((err = reader.Next(TLV::AnonymousTag())) == CHIP_NO_ERROR && i < kMaxScenesPerFabric)
212216
{
213-
ReturnErrorOnFailure(reader.EnterContainer(container));
217+
TLV::TLVType sceneIdContainer;
218+
ReturnErrorOnFailure(reader.EnterContainer(sceneIdContainer));
214219
ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kEndpointID)));
215220
ReturnErrorOnFailure(reader.Get(scene_map[i].mEndpointId));
216221
ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kGroupID)));
217222
ReturnErrorOnFailure(reader.Get(scene_map[i].mGroupId));
218223
ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kSceneID)));
219224
ReturnErrorOnFailure(reader.Get(scene_map[i].mSceneId));
220-
ReturnErrorOnFailure(reader.ExitContainer(container));
225+
ReturnErrorOnFailure(reader.ExitContainer(sceneIdContainer));
221226

222227
i++;
223228
}
224-
VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
229+
VerifyOrReturnError(err == CHIP_END_OF_TLV || err == CHIP_NO_ERROR, err);
225230

226-
ReturnErrorOnFailure(reader.ExitContainer(container));
227-
return reader.ExitContainer(container);
231+
ReturnErrorOnFailure(reader.ExitContainer(sceneMapContainer));
232+
return reader.ExitContainer(fabricSceneContainer);
228233
}
229234

230235
/// @brief Finds the index where to insert current scene by going through the whole table and looking if the scene is already in

src/app/clusters/scenes/SceneTableImpl.h

+36-28
Original file line numberDiff line numberDiff line change
@@ -45,42 +45,44 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler
4545
/// @brief From command AddScene, allows handler to filter through clusters in command to serialize only the supported ones.
4646
/// @param endpoint[in] Endpoint ID
4747
/// @param extensionFieldSet[in] ExtensionFieldSets provided by the AddScene Command, pre initialized
48-
/// @param cluster[out] Cluster in the Extension field set, filled by the function
4948
/// @param serialisedBytes[out] Buffer to fill from the ExtensionFieldSet in command
5049
/// @return CHIP_NO_ERROR if successful, CHIP_ERROR_INVALID_ARGUMENT if the cluster is not supported, CHIP_ERROR value otherwise
5150
virtual CHIP_ERROR SerializeAdd(EndpointId endpoint,
5251
const app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType & extensionFieldSet,
53-
ClusterId & cluster, MutableByteSpan & serializedBytes) override
52+
MutableByteSpan & serializedBytes) override
5453
{
5554
app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType aVPair;
5655
TLV::TLVWriter writer;
5756
TLV::TLVType outer;
57+
size_t pairTotal = 0;
58+
uint8_t pairCount = 0;
5859

59-
uint8_t pairCount = 0;
60-
uint8_t valueBytes = 0;
61-
62-
VerifyOrReturnError(SupportsCluster(endpoint, extensionFieldSet.clusterID), CHIP_ERROR_INVALID_ARGUMENT);
63-
64-
cluster = extensionFieldSet.clusterID;
60+
// Verify size of list
61+
extensionFieldSet.attributeValueList.ComputeSize(&pairTotal);
62+
VerifyOrReturnError(pairTotal <= kMaxAvPair, CHIP_ERROR_BUFFER_TOO_SMALL);
6563

6664
auto pair_iterator = extensionFieldSet.attributeValueList.begin();
6765
while (pair_iterator.Next() && pairCount < kMaxAvPair)
6866
{
6967
aVPair = pair_iterator.GetValue();
7068
mAVPairs[pairCount].attributeID = aVPair.attributeID;
71-
auto value_iterator = aVPair.attributeValue.begin();
69+
size_t valueBytesTotal = 0;
70+
uint8_t valueBytesCount = 0;
7271

73-
valueBytes = 0;
74-
while (value_iterator.Next() && valueBytes < kMaxValueSize)
72+
aVPair.attributeValue.ComputeSize(&valueBytesTotal);
73+
VerifyOrReturnError(valueBytesTotal <= kMaxValueSize, CHIP_ERROR_BUFFER_TOO_SMALL);
74+
75+
auto value_iterator = aVPair.attributeValue.begin();
76+
while (value_iterator.Next())
7577
{
76-
mValueBuffer[pairCount][valueBytes] = value_iterator.GetValue();
77-
valueBytes++;
78+
mValueBuffer[pairCount][valueBytesCount] = value_iterator.GetValue();
79+
valueBytesCount++;
7880
}
7981
// Check we could go through all bytes of the value
8082
ReturnErrorOnFailure(value_iterator.GetStatus());
8183

8284
mAVPairs[pairCount].attributeValue = mValueBuffer[pairCount];
83-
mAVPairs[pairCount].attributeValue.reduce_size(valueBytes);
85+
mAVPairs[pairCount].attributeValue.reduce_size(valueBytesCount);
8486
pairCount++;
8587
}
8688
// Check we could go through all pairs in incomming command
@@ -90,7 +92,7 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler
9092
attributeValueList = mAVPairs;
9193
attributeValueList.reduce_size(pairCount);
9294

93-
writer.Init(serialisedBytes);
95+
writer.Init(serializedBytes);
9496
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
9597
ReturnErrorOnFailure(app::DataModel::Encode(
9698
writer, TLV::ContextTag(app::Clusters::Scenes::Structs::ExtensionFieldSet::Fields::kAttributeValueList),
@@ -114,38 +116,44 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler
114116

115117
TLV::TLVReader reader;
116118
TLV::TLVType outer;
117-
uint8_t pairCount = 0;
118-
uint8_t valueBytes = 0;
119-
120-
VerifyOrReturnError(SupportsCluster(endpoint, cluster), CHIP_ERROR_INVALID_ARGUMENT);
119+
size_t pairTotal = 0;
120+
uint8_t pairCount = 0;
121121

122122
extensionFieldSet.clusterID = cluster;
123123
reader.Init(serialisedBytes);
124124
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
125125
ReturnErrorOnFailure(reader.EnterContainer(outer));
126126
ReturnErrorOnFailure(reader.Next(
127-
TLV::kTLVType_Array,
128-
TLV::ContextTag(app::Clusters::Scenes::Structs::ExtensionFieldSet::Fields::kAttributeValueList)));
127+
TLV::kTLVType_Array, TLV::ContextTag(app::Clusters::Scenes::Structs::ExtensionFieldSet::Fields::kAttributeValueList)));
129128
attributeValueList.Decode(reader);
130129

130+
// Verify size of list
131+
attributeValueList.ComputeSize(&pairTotal);
132+
VerifyOrReturnError(pairTotal <= kMaxAvPair, CHIP_ERROR_BUFFER_TOO_SMALL);
133+
131134
auto pair_iterator = attributeValueList.begin();
132-
while (pair_iterator.Next() && pairCount < kMaxAvPair)
135+
while (pair_iterator.Next())
133136
{
134137
decodePair = pair_iterator.GetValue();
135138
mAVPairs[pairCount].attributeID = decodePair.attributeID;
136-
auto value_iterator = decodePair.attributeValue.begin();
137-
valueBytes = 0;
139+
size_t valueBytesTotal = 0;
140+
uint8_t valueBytesCount = 0;
141+
142+
// Verify size of attribute value
143+
decodePair.attributeValue.ComputeSize(&valueBytesTotal);
144+
VerifyOrReturnError(valueBytesTotal <= kMaxValueSize, CHIP_ERROR_BUFFER_TOO_SMALL);
138145

139-
while (value_iterator.Next() && valueBytes < kMaxValueSize)
146+
auto value_iterator = decodePair.attributeValue.begin();
147+
while (value_iterator.Next() && valueBytesCount < kMaxValueSize)
140148
{
141-
mValueBuffer[pairCount][valueBytes] = value_iterator.GetValue();
142-
valueBytes++;
149+
mValueBuffer[pairCount][valueBytesCount] = value_iterator.GetValue();
150+
valueBytesCount++;
143151
}
144152
// Check we could go through all bytes of the value
145153
ReturnErrorOnFailure(value_iterator.GetStatus());
146154

147155
mAVPairs[pairCount].attributeValue = mValueBuffer[pairCount];
148-
mAVPairs[pairCount].attributeValue.reduce_size(valueBytes);
156+
mAVPairs[pairCount].attributeValue.reduce_size(valueBytesCount);
149157
pairCount++;
150158
};
151159
// Check we could go through all pairs stored in memory

0 commit comments

Comments
 (0)