This is an automated email from the ASF dual-hosted git repository.

cederom pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit a74b2fc61b87cce26cfc8867032122a6d3ac6520
Author: Nightt <[email protected]>
AuthorDate: Wed May 27 17:17:04 2026 +0800

    system/settings: Bound public string handling
    
    Use strnlen() for public key, value, and storage path length checks so 
user-provided settings strings are validated against the configured maximum 
sizes before they are scanned.
    
    Use bounded key comparisons and strlcpy() for fixed-size settings fields. 
This addresses part of #3109 without changing the settings API or storage 
formats.
    
    Signed-off-by: Nightt <[email protected]>
---
 system/settings/settings.c | 47 ++++++++++++++++++++++++++++------------------
 1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/system/settings/settings.c b/system/settings/settings.c
index 1625c3f5a..3949a384f 100644
--- a/system/settings/settings.c
+++ b/system/settings/settings.c
@@ -152,6 +152,13 @@ static int get_setting(FAR char *key, FAR setting_t 
**setting)
 
   assert(*setting == NULL);
 
+  if (strnlen(key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE) >=
+      CONFIG_SYSTEM_SETTINGS_KEY_SIZE)
+    {
+      ret = -EINVAL;
+      goto exit;
+    }
+
   for (i = 0; i < CONFIG_SYSTEM_SETTINGS_MAP_SIZE; i++)
     {
       if (map[i].type == SETTING_EMPTY)
@@ -160,7 +167,7 @@ static int get_setting(FAR char *key, FAR setting_t 
**setting)
           goto exit;
         }
 
-      if (strcmp(map[i].key, key) == 0)
+      if (strncmp(map[i].key, key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE) == 0)
         {
           *setting = &map[i];
           goto exit;
@@ -201,16 +208,16 @@ static size_t get_string(FAR setting_t *setting, FAR char 
*buffer,
   if (setting->type == SETTING_STRING)
     {
       FAR const char *s = setting->val.s;
-      size_t len = strlen(s);
+      size_t len = strnlen(s, CONFIG_SYSTEM_SETTINGS_VALUE_SIZE);
 
+      assert(len < CONFIG_SYSTEM_SETTINGS_VALUE_SIZE);
       assert(len < size);
-      if (len >= size)
+      if (len >= CONFIG_SYSTEM_SETTINGS_VALUE_SIZE || len >= size)
         {
           return 0;
         }
 
-      strncpy(buffer, s, size);
-      buffer[size - 1] = '\0';
+      strlcpy(buffer, s, size);
 
       return len;
     }
@@ -221,7 +228,7 @@ static size_t get_string(FAR setting_t *setting, FAR char 
*buffer,
       inet_ntop(AF_INET, &setting->val.ip, buffer, size);
       buffer[size - 1] = '\0';
 
-      return strlen(buffer);
+      return strnlen(buffer, size);
     }
 
   return 0;
@@ -244,6 +251,8 @@ static size_t get_string(FAR setting_t *setting, FAR char 
*buffer,
 
 static int set_string(FAR setting_t *setting, FAR char *str)
 {
+  size_t len;
+
   assert(setting);
 
   if ((setting->type != SETTING_STRING) &&
@@ -252,19 +261,19 @@ static int set_string(FAR setting_t *setting, FAR char 
*str)
       return -EACCES;
     }
 
-  if (strlen(str) >= CONFIG_SYSTEM_SETTINGS_VALUE_SIZE)
+  len = strnlen(str, CONFIG_SYSTEM_SETTINGS_VALUE_SIZE);
+  if (len >= CONFIG_SYSTEM_SETTINGS_VALUE_SIZE)
     {
       return -EINVAL;
     }
 
-  if (strlen(str) && (sanity_check(str) < 0))
+  if (len > 0 && (sanity_check(str) < 0))
     {
       return -EINVAL;
     }
 
   setting->type = SETTING_STRING;
-  strncpy(setting->val.s, str, CONFIG_SYSTEM_SETTINGS_VALUE_SIZE);
-  setting->val.s[CONFIG_SYSTEM_SETTINGS_VALUE_SIZE - 1] = '\0';
+  strlcpy(setting->val.s, str, CONFIG_SYSTEM_SETTINGS_VALUE_SIZE);
 
   return OK;
 }
@@ -825,6 +834,7 @@ int settings_setstorage(FAR char *file, enum storage_type_e 
type)
   int ret = OK;
   int idx = 0;
   uint32_t h;
+  size_t filelen;
 
   assert(g_settings.initialized);
 
@@ -847,16 +857,16 @@ int settings_setstorage(FAR char *file, enum 
storage_type_e type)
       goto errout;
     }
 
-  assert(strlen(file) < CONFIG_SYSTEM_SETTINGS_MAX_FILENAME);
-  if (strlen(file) >= CONFIG_SYSTEM_SETTINGS_MAX_FILENAME)
+  filelen = strnlen(file, CONFIG_SYSTEM_SETTINGS_MAX_FILENAME);
+  assert(filelen < CONFIG_SYSTEM_SETTINGS_MAX_FILENAME);
+  if (filelen >= CONFIG_SYSTEM_SETTINGS_MAX_FILENAME)
     {
       ret = -EINVAL;
       goto errout;
     }
 
   storage = &g_settings.store[idx];
-  strncpy(storage->file, file, sizeof(storage->file));
-  storage->file[sizeof(storage->file) - 1] = '\0';
+  strlcpy(storage->file, file, sizeof(storage->file));
 
   switch (type)
   {
@@ -1114,6 +1124,7 @@ int settings_create(FAR char *key, enum settings_type_e 
type, ...)
 {
   int ret = OK;
   FAR setting_t *setting = NULL;
+  size_t keylen;
   int j;
 
   assert(g_settings.initialized);
@@ -1123,7 +1134,8 @@ int settings_create(FAR char *key, enum settings_type_e 
type, ...)
       return -EINVAL;
     }
 
-  if (strlen(key) == 0 || strlen(key) >= CONFIG_SYSTEM_SETTINGS_KEY_SIZE)
+  keylen = strnlen(key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE);
+  if (keylen == 0 || keylen >= CONFIG_SYSTEM_SETTINGS_KEY_SIZE)
     {
       return -EINVAL;
     }
@@ -1141,7 +1153,7 @@ int settings_create(FAR char *key, enum settings_type_e 
type, ...)
 
   for (j = 0; j < CONFIG_SYSTEM_SETTINGS_MAP_SIZE; j++)
     {
-      if (strcmp(key, map[j].key) == 0)
+      if (strncmp(key, map[j].key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE) == 0)
         {
           setting = &map[j];
 
@@ -1153,8 +1165,7 @@ int settings_create(FAR char *key, enum settings_type_e 
type, ...)
       if (map[j].type == SETTING_EMPTY)
         {
           setting = &map[j];
-          strncpy(setting->key, key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE);
-          setting->key[CONFIG_SYSTEM_SETTINGS_KEY_SIZE - 1] = '\0';
+          strlcpy(setting->key, key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE);
 
           /* This setting is empty/unused - we can use it */
 

Reply via email to