Skip to content

Commit d481fa9

Browse files
committed
Merge branch 'fix-str-len-checks' into 'main'
Fix problems with string type attributes See merge request app-frameworks/esp-matter!618
2 parents 105e898 + 700aebe commit d481fa9

9 files changed

+57
-25
lines changed

RELEASE_NOTES.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 14-February-2024
2+
3+
- An optional argument, `max_val_size`, has been introduced to the `esp_matter::attribute::create()` API.
4+
This argument is utilized specifically when creating attributes of the char string and long char string data types
5+
to specify the maximum supported value size of an attribute.
6+
17
# 29-January-2024
28

39
- Add a new parameter for esp_matter::client::connect() to set the CASESessionManager for finding or establishing the CASE sessions.

components/esp_matter/esp_matter_attribute.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#include <esp_log.h>
1616
#include <esp_matter_attribute.h>
17+
#include <esp_matter.h>
18+
#include <esp_matter_core.h>
1719

1820
static const char *TAG = "esp_matter_attribute";
1921

@@ -183,7 +185,7 @@ attribute_t *create_node_label(cluster_t *cluster, char *value, uint16_t length)
183185
}
184186
return esp_matter::attribute::create(cluster, BasicInformation::Attributes::NodeLabel::Id,
185187
ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NONVOLATILE,
186-
esp_matter_char_str(value, length));
188+
esp_matter_char_str(value, length), k_max_node_label_length);
187189
}
188190

189191
attribute_t *create_location(cluster_t *cluster, char *value, uint16_t length)
@@ -926,7 +928,7 @@ attribute_t *create_node_label(cluster_t *cluster, char *value, uint16_t length)
926928
}
927929
return esp_matter::attribute::create(cluster, BridgedDeviceBasicInformation::Attributes::NodeLabel::Id,
928930
ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NONVOLATILE,
929-
esp_matter_char_str(value, length));
931+
esp_matter_char_str(value, length), k_max_node_label_length);
930932
}
931933

932934
attribute_t *create_hardware_version(cluster_t *cluster, uint16_t value)
@@ -3652,7 +3654,9 @@ attribute_t *create_mode_select_description(cluster_t *cluster, const char * val
36523654
ESP_LOGE(TAG, "Could not create attribute, string length out of bound");
36533655
return NULL;
36543656
}
3655-
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::Description::Id, ATTRIBUTE_FLAG_NONE, esp_matter_char_str((char *)value, length));
3657+
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::Description::Id, ATTRIBUTE_FLAG_NONE,
3658+
esp_matter_char_str((char *)value, length),
3659+
k_max_mode_select_description_length);
36563660
}
36573661

36583662
attribute_t *create_standard_namespace(cluster_t *cluster, const nullable<uint16_t> value)
@@ -3708,7 +3712,8 @@ attribute_t *create_description(cluster_t *cluster, const char * value, uint16_t
37083712
ESP_LOGE(TAG, "Could not create attribute, string length out of bound");
37093713
return NULL;
37103714
}
3711-
return esp_matter::attribute::create(cluster, PowerSource::Attributes::Description::Id, ATTRIBUTE_FLAG_NONE, esp_matter_char_str((char *)value, length));
3715+
return esp_matter::attribute::create(cluster, PowerSource::Attributes::Description::Id, ATTRIBUTE_FLAG_NONE,
3716+
esp_matter_char_str((char *)value, length), k_max_description_length);
37123717
}
37133718

37143719
attribute_t *create_wired_assessed_input_voltage(cluster_t *cluster, nullable<uint32_t> value, nullable<uint32_t> min, nullable<uint32_t> max)
@@ -3853,7 +3858,9 @@ attribute_t *create_bat_replacement_description(cluster_t *cluster, const char *
38533858
ESP_LOGE(TAG, "Could not create attribute, string size out of bound");
38543859
return NULL;
38553860
}
3856-
return esp_matter::attribute::create(cluster, PowerSource::Attributes::BatReplacementDescription::Id, ATTRIBUTE_FLAG_NONE, esp_matter_char_str((char *)value, length));
3861+
return esp_matter::attribute::create(cluster, PowerSource::Attributes::BatReplacementDescription::Id,
3862+
ATTRIBUTE_FLAG_NONE, esp_matter_char_str((char *)value, length),
3863+
k_max_bat_replacement_description_length);
38573864
}
38583865

38593866
attribute_t *create_bat_common_designation(cluster_t *cluster, const uint8_t value, uint8_t min, uint8_t max)

components/esp_matter/esp_matter_attribute.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#pragma once
1616

17-
#include <esp_matter.h>
1817
#include <esp_matter_core.h>
1918

2019
namespace esp_matter {
@@ -768,6 +767,9 @@ attribute_t *state_value(cluster_t *cluster, bool value);
768767
} /* boolean_state */
769768

770769
namespace localization_configuration {
770+
771+
constexpr uint8_t k_max_active_locale_length = 35;
772+
771773
namespace attribute {
772774
attribute_t *create_active_locale(cluster_t *cluster, char *value, uint16_t length);
773775
attribute_t *create_supported_locales(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count);
@@ -861,6 +863,7 @@ constexpr uint8_t k_max_description_length = 60;
861863
constexpr uint8_t k_max_fault_count = 8;
862864
constexpr uint8_t k_max_designation_count = 20;
863865
constexpr uint8_t k_max_charge_faults_count = 16;
866+
constexpr uint8_t k_max_bat_replacement_description_length = 60;
864867

865868
namespace attribute {
866869
attribute_t *create_status(cluster_t *cluster, uint8_t value);

components/esp_matter/esp_matter_cluster.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags)
246246
/* Attributes not managed internally */
247247
if (config) {
248248
global::attribute::create_cluster_revision(cluster, config->cluster_revision);
249-
attribute::create_node_label(cluster, config->node_label, sizeof(config->node_label));
249+
attribute::create_node_label(cluster, config->node_label, strlen(config->node_label));
250250
} else {
251251
ESP_LOGE(TAG, "Config is NULL. Cannot add some attributes.");
252252
}
@@ -937,7 +937,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_
937937
global::attribute::create_cluster_revision(cluster, config->cluster_revision);
938938
attribute::create_status(cluster, config->status);
939939
attribute::create_order(cluster, config->order, 0x00, 0xFF);
940-
attribute::create_description(cluster, config->description, sizeof(config->description));
940+
attribute::create_description(cluster, config->description, strlen(config->description));
941941
} else {
942942
ESP_LOGE(TAG, "Config is NULL. Cannot add some attributes.");
943943
}
@@ -2704,7 +2704,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags)
27042704
if (config) {
27052705
/* Attributes not managed internally */
27062706
global::attribute::create_cluster_revision(cluster, config->cluster_revision);
2707-
attribute::create_active_locale(cluster, config->active_locale, sizeof(config->active_locale));
2707+
attribute::create_active_locale(cluster, config->active_locale, strlen(config->active_locale));
27082708

27092709
/* Attributes managed internally */
27102710
attribute::create_supported_locales(cluster, NULL, 0, 0);
@@ -2968,7 +2968,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_
29682968
/** Attributes not managed internally **/
29692969
if (config) {
29702970
global::attribute::create_cluster_revision(cluster, config->cluster_revision);
2971-
attribute::create_mode_select_description(cluster, config->mode_select_description, sizeof(config->mode_select_description));
2971+
attribute::create_mode_select_description(cluster, config->mode_select_description, strlen(config->mode_select_description));
29722972
attribute::create_standard_namespace(cluster, config->standard_namespace);
29732973
attribute::create_current_mode(cluster, config->current_mode);
29742974
} else {

components/esp_matter/esp_matter_cluster.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#pragma once
1616

1717
#include <esp_matter_core.h>
18+
#include <esp_matter_attribute.h>
1819
#include <esp_matter_feature.h>
1920
#include <stdint.h>
2021

@@ -70,7 +71,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags);
7071
namespace basic_information {
7172
typedef struct config {
7273
uint16_t cluster_revision;
73-
char node_label[32];
74+
char node_label[k_max_node_label_length + 1];
7475
config() : cluster_revision(3), node_label{0} {}
7576
} config_t;
7677

@@ -231,7 +232,7 @@ typedef struct config {
231232
uint16_t cluster_revision;
232233
uint8_t status;
233234
uint8_t order;
234-
char description[61];
235+
char description[k_max_description_length + 1];
235236
feature::wired::config_t wired;
236237
feature::battery::config_t battery;
237238
feature::rechargeable::config_t rechargeable;
@@ -627,7 +628,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags);
627628
namespace localization_configuration {
628629
typedef struct config {
629630
uint16_t cluster_revision;
630-
char active_locale[35];
631+
char active_locale[k_max_active_locale_length + 1];
631632
config() : cluster_revision(4), active_locale{0} {}
632633
} config_t;
633634

@@ -708,7 +709,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags);
708709
namespace mode_select {
709710
typedef struct config {
710711
uint16_t cluster_revision;
711-
char mode_select_description[64];
712+
char mode_select_description[k_max_mode_select_description_length + 1];
712713
const nullable<uint16_t> standard_namespace;
713714
uint8_t current_mode;
714715
feature::on_off::config_t on_off;

components/esp_matter/esp_matter_core.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ typedef struct _attribute {
154154
esp_matter_attr_bounds_t *bounds;
155155
EmberAfDefaultOrMinMaxAttributeValue default_value;
156156
uint16_t default_value_size;
157+
// This is required when creating metadata for char string and long char string types of attributes.
158+
// The size in the attribute metadata remains constant and is verified during write operations.
159+
uint16_t max_val_size;
157160
attribute::callback_t override_callback;
158161
struct _attribute *next;
159162
} _attribute_t;
@@ -617,8 +620,14 @@ esp_err_t enable(endpoint_t *endpoint)
617620
* when writing a longer string.
618621
*/
619622
if (attribute->val.type == ESP_MATTER_VAL_TYPE_CHAR_STRING ||
620-
attribute->val.type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING) {
621-
matter_attributes[attribute_index].size = attribute->val.val.a.s;
623+
attribute->val.type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING) {
624+
// Once the metadata is created, the attribute size becomes fixed and cannot be modified thereafter.
625+
// For string and long string types, the size should be the maximum size defined in the specification
626+
// plus the size_for_storing_str_len. The length byte is 1 for char string and 2 for long char string.
627+
// For example, the maximum size of the Node-Label in the basic information cluster is 32 bytes,
628+
// and it is a char string. Therefore, the size should be (32 + 1).
629+
uint16_t size_for_storing_str_len = attribute->val.val.a.t - attribute->val.val.a.s;
630+
matter_attributes[attribute_index].size = attribute->max_val_size + size_for_storing_str_len;
622631
}
623632

624633
matter_clusters[cluster_index].clusterSize += matter_attributes[attribute_index].size;
@@ -1094,7 +1103,8 @@ esp_err_t factory_reset()
10941103
}
10951104

10961105
namespace attribute {
1097-
attribute_t *create(cluster_t *cluster, uint32_t attribute_id, uint8_t flags, esp_matter_attr_val_t val)
1106+
attribute_t *create(cluster_t *cluster, uint32_t attribute_id, uint8_t flags, esp_matter_attr_val_t val,
1107+
uint16_t max_val_size)
10981108
{
10991109
/* Find */
11001110
if (!cluster) {
@@ -1122,6 +1132,7 @@ attribute_t *create(cluster_t *cluster, uint32_t attribute_id, uint8_t flags, es
11221132
attribute->endpoint_id = current_cluster->endpoint_id;
11231133
attribute->flags = flags;
11241134
attribute->flags |= ATTRIBUTE_FLAG_EXTERNAL_STORAGE;
1135+
attribute->max_val_size = max_val_size;
11251136

11261137
// After reboot, string and array are treated as Invalid. So need to store val.type and size of attribute value.
11271138
attribute->val.type = val.type;

components/esp_matter/esp_matter_core.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,19 @@ namespace attribute {
425425
*
426426
* This will create a new attribute and add it to the cluster.
427427
*
428-
* @param[in] cluster Cluster handle.
429-
* @param[in] attribute_id Attribute ID for the attribute.
430-
* @param[in] flags Bitmap of `attribute_flags_t`.
431-
* @param[in] val Default type and value of the attribute. Use appropriate elements as per the value type.
428+
* @param[in] cluster Cluster handle.
429+
* @param[in] attribute_id Attribute ID for the attribute.
430+
* @param[in] flags Bitmap of `attribute_flags_t`.
431+
* @param[in] val Default type and value of the attribute. Use appropriate elements as per the value type.
432+
* @param[in] max_val_size For attributes of type char string and long char string, the size should correspond to the
433+
* maximum size defined in the specification. However, for other types of attributes, this
434+
* parameter remains unused, and therefore the default value is set to 0
432435
*
433436
* @return Attribute handle on success.
434437
* @return NULL in case of failure.
435438
*/
436-
attribute_t *create(cluster_t *cluster, uint32_t attribute_id, uint8_t flags, esp_matter_attr_val_t val);
439+
attribute_t *create(cluster_t *cluster, uint32_t attribute_id, uint8_t flags, esp_matter_attr_val_t val,
440+
uint16_t max_val_size = 0);
437441

438442
/** Get attribute
439443
*

components/esp_matter/esp_matter_feature.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ esp_err_t add(cluster_t *cluster, config_t *config)
222222
update_feature_map(cluster, get_id());
223223

224224
/* Attributes not managed internally */
225-
attribute::create_bat_replacement_description(cluster, config->bat_replacement_description, sizeof(config->bat_replacement_description));
225+
attribute::create_bat_replacement_description(cluster, config->bat_replacement_description, strlen(config->bat_replacement_description));
226226
attribute::create_bat_quantity(cluster, config->bat_quantity, 0, 255);
227227
} else {
228228
ESP_LOGE(TAG, "Cluster shall support Battery feature");

components/esp_matter/esp_matter_feature.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
#pragma once
1616

17-
#include <esp_matter_core.h>
1817
#include <stdint.h>
18+
#include <esp_matter_attribute.h>
1919

2020
#define ESP_MATTER_NONE_FEATURE_ID 0x0000
2121

@@ -101,7 +101,7 @@ esp_err_t add(cluster_t *cluster, config_t *config);
101101
// Replaceable feature one must add Battery feature first.
102102
namespace replaceable {
103103
typedef struct config {
104-
char bat_replacement_description[61];
104+
char bat_replacement_description[k_max_bat_replacement_description_length + 1];
105105
uint8_t bat_quantity;
106106
config(): bat_replacement_description{0}, bat_quantity(0) {}
107107
} config_t;

0 commit comments

Comments
 (0)