Skip to content

Commit a6232e6

Browse files
Fixed some of the attribute casting issues, need to rework the spec before completing this PR
1 parent 49ec44b commit a6232e6

File tree

2 files changed

+43
-33
lines changed

2 files changed

+43
-33
lines changed

src/app/clusters/scenes-server/SceneHandlerImpl.cpp

+33-22
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,16 @@ using AttributeValuePairType = app::Clusters::ScenesManagement::Structs::Attribu
3434
/// @param EmberAfDefaultAttributeValue & defaultValue
3535
/// @return Value converted to the given working type
3636
template <typename Type>
37-
Type ConvertDefaultValueToWorkingValue(const EmberAfDefaultAttributeValue & defaultValue)
37+
typename app::NumericAttributeTraits<Type>::WorkingType
38+
ConvertDefaultValueToWorkingValue(const EmberAfDefaultAttributeValue & defaultValue)
3839
{
39-
if (sizeof(Type) <= 2)
40+
if (sizeof(typename app::NumericAttributeTraits<Type>::WorkingType) <= 2)
4041
{
41-
return static_cast<Type>(defaultValue.defaultValue);
42+
return static_cast<typename app::NumericAttributeTraits<Type>::WorkingType>(defaultValue.defaultValue);
4243
}
4344

44-
Type sValue = 0;
45-
memcpy(&sValue, defaultValue.ptrToDefaultValue, sizeof(Type));
45+
typename app::NumericAttributeTraits<Type>::StorageType sValue;
46+
memcpy(&sValue, defaultValue.ptrToDefaultValue, sizeof(sValue));
4647
return app::NumericAttributeTraits<Type>::StorageToWorking(sValue);
4748
}
4849

@@ -60,57 +61,67 @@ void CapAttributeID(AttributeValuePairType & aVPair, const EmberAfAttributeMetad
6061

6162
WorkingType maxValue;
6263

63-
if (metadata->IsBoolean())
64-
{
65-
aVPair.attributeValue = aVPair.attributeValue ? 1 : 0;
66-
return;
67-
}
68-
6964
// Check if the attribute type is signed
7065
if (metadata->IsSignedIntegerAttribute())
7166
{
67+
// We use emberAfAttributeSize for cases like INT24S, INT40S, INT48S, INT56S where numeric_limits<WorkingType>::max()
68+
// wouldn't work
7269
maxValue = static_cast<WorkingType>((1ULL << (emberAfAttributeSize(metadata) * 8 - 1)) - 1);
7370
}
7471
else
7572
{
73+
// We use emberAfAttributeSize for cases like INT24U, INT40U, INT48U, INT56U where numeric_limits<WorkingType>::max()
74+
// wouldn't work
7675
maxValue = static_cast<WorkingType>((1ULL << (emberAfAttributeSize(metadata) * 8)) - 1);
7776
}
7877

78+
// Ensure that the metadata's signedness matches the working type's signedness
79+
VerifyOrDie(metadata->IsSignedIntegerAttribute() == std::is_signed<WorkingType>::value);
80+
81+
if (metadata->IsBoolean())
82+
{
83+
// Caping the value to 1 in case values greater than 1 are set
84+
aVPair.attributeValue = aVPair.attributeValue ? 1 : 0;
85+
return;
86+
}
87+
7988
// Check metadata for min and max values
8089
if (metadata->HasMinMax())
8190
{
8291
const EmberAfAttributeMinMaxValue * minMaxValue = metadata->defaultValue.ptrToMinMaxValue;
83-
WorkingType minVal = ConvertDefaultValueToWorkingValue<WorkingType>(minMaxValue->minValue);
84-
WorkingType maxVal = ConvertDefaultValueToWorkingValue<WorkingType>(minMaxValue->maxValue);
92+
WorkingType rangeMin = ConvertDefaultValueToWorkingValue<Type>(minMaxValue->minValue);
93+
WorkingType rangeMax = ConvertDefaultValueToWorkingValue<Type>(minMaxValue->maxValue);
8594

8695
// Cap based on minimum value
87-
if (minVal > static_cast<WorkingType>(aVPair.attributeValue))
96+
if (rangeMin > static_cast<WorkingType>(aVPair.attributeValue))
8897
{
89-
aVPair.attributeValue = static_cast<std::make_unsigned_t<WorkingType>>(minVal);
98+
aVPair.attributeValue = static_cast<std::make_unsigned_t<WorkingType>>(rangeMin);
9099
// We assume the max is >= min therefore we can return
91100
return;
92101
}
93102

94103
// Adjust maxValue if greater than the meta data's max value
95-
if (maxVal < maxValue)
104+
if (rangeMax < static_cast<WorkingType>(aVPair.attributeValue))
96105
{
97-
maxValue = maxVal;
106+
maxValue = rangeMax;
98107
}
99108
}
100109

101-
// Cap based on maximum value
102-
if (metadata->IsSignedIntegerAttribute())
110+
// Cap based on type-enforced maximum value (and minnimum for signed types)
111+
if constexpr (std::is_signed<WorkingType>::value)
103112
{
104-
if (static_cast<int64_t>(aVPair.attributeValue) > static_cast<int64_t>(maxValue))
113+
// Cap on max value, check for comparison to the WorkingType size and check for overflow
114+
if (static_cast<WorkingType>(aVPair.attributeValue) > maxValue || aVPair.attributeValue & ~static_cast<uint64_t>(maxValue))
105115
{
116+
// We treat overflows as > Max value since the wrong type is being used and we cannot determine the actual value
106117
aVPair.attributeValue = static_cast<std::make_unsigned_t<WorkingType>>(maxValue);
107118
}
108119
}
109120
else
110121
{
111-
if (aVPair.attributeValue > static_cast<uint64_t>(maxValue))
122+
if (aVPair.attributeValue > maxValue)
112123
{
113-
aVPair.attributeValue = static_cast<std::make_unsigned_t<WorkingType>>(maxValue);
124+
aVPair.attributeValue = maxValue;
114125
}
115126
}
116127
}

src/app/util/mock/attribute-storage.cpp

+10-11
Original file line numberDiff line numberDiff line change
@@ -69,30 +69,29 @@ bool mockAttribute1 = true;
6969
int16_t mockAttribute2 = 42;
7070
uint64_t mockAttribute3 = 0xdeadbeef0000cafe;
7171
uint8_t mockAttribute4[256] = {
72-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
73-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
74-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
75-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
76-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
77-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
78-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
79-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
72+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
73+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
74+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
75+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
76+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
77+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
78+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
79+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
8080
};
8181

8282
const uint8_t defaultValueData[] = { 0x01, 0x02, 0x03, 0x04 };
8383
const uint8_t minValueData[] = { 0xFF, 0xFF, 0xFF, 0xFF };
8484
#if CHIP_CONFIG_BIG_ENDIAN_TARGET
8585
const uint8_t maxValueData[] = { 0x00, 0x7F, 0xFF, 0xFF };
86-
7
8786
#else
8887
const uint8_t maxValueData[] = { 0xFF, 0xFF, 0x7F, 0x00 }; // Equivalent, in little-endian, to 0x007FFFFF
8988
#endif
9089

91-
EmberAfAttributeMinMaxValue minMaxValue = { defaultValueData, minValueData, maxValueData };
90+
EmberAfAttributeMinMaxValue minMaxValue = { defaultValueData, minValueData, maxValueData };
9291

9392
EmberAfAttributeMetadata mockmetadata = { .defaultValue = EmberAfDefaultOrMinMaxAttributeValue(&minMaxValue),
9493
.attributeId = 0,
95-
.size = sizeof(int32_t),
94+
.size = 3,
9695
.attributeType = ZCL_INT24S_ATTRIBUTE_TYPE,
9796
.mask = ATTRIBUTE_MASK_MIN_MAX }; // namespace
9897

0 commit comments

Comments
 (0)