system/settings: Bound storage string handling

Use configured key, value, and filename limits while loading and saving settings storage data.

The text backend now builds backup filenames with a sized buffer and bounded formatting, and both text and binary loading reject keys or string values that are not terminated within their configured field sizes. This completes #3109 without changing the storage formats.

Signed-off-by: Nightt <87569709+nightt5879@users.noreply.github.com>
This commit is contained in:
Nightt 2026-05-27 17:18:35 +08:00 committed by CeDeROM
parent a74b2fc61b
commit c0fc208202
2 changed files with 45 additions and 15 deletions

View file

@ -96,12 +96,19 @@ extern setting_t map[CONFIG_SYSTEM_SETTINGS_MAP_SIZE];
FAR setting_t *getsetting(FAR char *key) FAR setting_t *getsetting(FAR char *key)
{ {
int i; int i;
size_t keylen;
keylen = strnlen(key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE);
if (keylen >= CONFIG_SYSTEM_SETTINGS_KEY_SIZE)
{
return NULL;
}
for (i = 0; i < CONFIG_SYSTEM_SETTINGS_MAP_SIZE; i++) for (i = 0; i < CONFIG_SYSTEM_SETTINGS_MAP_SIZE; i++)
{ {
FAR setting_t *setting = &map[i]; FAR setting_t *setting = &map[i];
if (strcmp(key, setting->key) == 0) if (strncmp(key, setting->key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE) == 0)
{ {
return setting; return setting;
} }
@ -190,6 +197,13 @@ int load_bin(FAR char *file)
continue; continue;
} }
if (setting.type == SETTING_STRING &&
strnlen(setting.val.s, CONFIG_SYSTEM_SETTINGS_VALUE_SIZE) >=
CONFIG_SYSTEM_SETTINGS_VALUE_SIZE)
{
continue;
}
memcpy(slot, &setting, sizeof(setting_t)); memcpy(slot, &setting, sizeof(setting_t));
} }

View file

@ -97,9 +97,11 @@ extern setting_t map[CONFIG_SYSTEM_SETTINGS_MAP_SIZE];
FAR setting_t *getsetting(char *key) FAR setting_t *getsetting(char *key)
{ {
int i; int i;
size_t keylen;
FAR setting_t *setting; FAR setting_t *setting;
if (strlen(key) >= CONFIG_SYSTEM_SETTINGS_KEY_SIZE) keylen = strnlen(key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE);
if (keylen >= CONFIG_SYSTEM_SETTINGS_KEY_SIZE)
{ {
return NULL; return NULL;
} }
@ -108,15 +110,14 @@ FAR setting_t *getsetting(char *key)
{ {
setting = &map[i]; setting = &map[i];
if (strcmp(key, setting->key) == 0) if (strncmp(key, setting->key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE) == 0)
{ {
return setting; return setting;
} }
if (setting->type == SETTING_EMPTY) if (setting->type == SETTING_EMPTY)
{ {
strncpy(setting->key, key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE); strlcpy(setting->key, key, CONFIG_SYSTEM_SETTINGS_KEY_SIZE);
setting->key[CONFIG_SYSTEM_SETTINGS_KEY_SIZE - 1] = '\0';
return setting; return setting;
} }
} }
@ -152,21 +153,27 @@ int load_text(FAR char *file)
FAR char *backup_file; FAR char *backup_file;
FAR char *buffer; FAR char *buffer;
FAR setting_t *setting; FAR setting_t *setting;
size_t filelen;
/* Check that the file exists */ /* Check that the file exists */
filelen = strnlen(file, CONFIG_SYSTEM_SETTINGS_MAX_FILENAME);
if (filelen >= CONFIG_SYSTEM_SETTINGS_MAX_FILENAME)
{
return -EINVAL;
}
if (access(file, F_OK) != 0) if (access(file, F_OK) != 0)
{ {
/* If not, try the backup file */ /* If not, try the backup file */
backup_file = malloc(strlen(file) + 2); backup_file = malloc(filelen + 2);
if (backup_file == NULL) if (backup_file == NULL)
{ {
return -ENODEV; return -ENODEV;
} }
strcpy(backup_file, file); snprintf(backup_file, filelen + 2, "%s~", file);
strcat(backup_file, "~");
if (access(backup_file, F_OK) == 0) if (access(backup_file, F_OK) == 0)
{ {
@ -196,10 +203,12 @@ int load_text(FAR char *file)
while (fgets(buffer, BUFFER_SIZE, f)) while (fgets(buffer, BUFFER_SIZE, f))
{ {
int i; int i;
size_t linelen;
/* Remove any line terminators */ /* Remove any line terminators */
for (i = ((int)strlen(buffer) - 1); i > 0; i--) linelen = strnlen(buffer, BUFFER_SIZE);
for (i = ((int)linelen - 1); i > 0; i--)
{ {
if (buffer[i] == ';' || buffer[i] == '\n' || buffer[i] == '\r') if (buffer[i] == ';' || buffer[i] == '\n' || buffer[i] == '\r')
{ {
@ -260,15 +269,15 @@ int load_text(FAR char *file)
{ {
/* It's a string */ /* It's a string */
if (strlen(val) >= CONFIG_SYSTEM_SETTINGS_VALUE_SIZE) if (strnlen(val, CONFIG_SYSTEM_SETTINGS_VALUE_SIZE) >=
CONFIG_SYSTEM_SETTINGS_VALUE_SIZE)
{ {
continue; continue;
} }
setting->type = SETTING_STRING; setting->type = SETTING_STRING;
strncpy(setting->val.s, val, strlcpy(setting->val.s, val,
CONFIG_SYSTEM_SETTINGS_VALUE_SIZE); CONFIG_SYSTEM_SETTINGS_VALUE_SIZE);
setting->val.s[CONFIG_SYSTEM_SETTINGS_VALUE_SIZE - 1] = '\0';
} }
} }
else else
@ -343,17 +352,24 @@ abort:
int save_text(FAR char *file) int save_text(FAR char *file)
{ {
int ret = OK; int ret = OK;
FAR char *backup_file = malloc(strlen(file) + 2); FAR char *backup_file;
FAR FILE *f; FAR FILE *f;
size_t filelen;
int i; int i;
filelen = strnlen(file, CONFIG_SYSTEM_SETTINGS_MAX_FILENAME);
if (filelen >= CONFIG_SYSTEM_SETTINGS_MAX_FILENAME)
{
return -EINVAL;
}
backup_file = malloc(filelen + 2);
if (backup_file == NULL) if (backup_file == NULL)
{ {
return -ENODEV; return -ENODEV;
} }
strcpy(backup_file, file); snprintf(backup_file, filelen + 2, "%s~", file);
strcat(backup_file, "~");
f = fopen(backup_file, "w"); f = fopen(backup_file, "w");
if (f == NULL) if (f == NULL)