fix: fehlende Felder in gekürzten Settings-Records auf echte Defaults setzen

read_rec() füllte den Puffer bisher mit memset(0) statt mit
nl_settings_defaults() vor, bevor die tatsächlich vorhandenen hdr.length
Bytes darübergeschrieben werden. Ein gekürzter Record, dessen Länge vor
fade_in_ms/fade_out_ms endet, aber token noch enthält, lief damit mit
fade_in_ms=0/fade_out_ms=0 statt der spezifizierten 500 ms - genau der Fall,
für den die Längentoleranz gedacht war. Die davor eingebaute "leerer Record"
Sonderbehandlung in nl_settings_load() (fade_in_ms==0 && fade_out_ms==0 &&
token[0]=='\0' -> volle Defaults) ist dadurch überflüssig geworden und
entfernt.

test_load_accepts_shorter_record kürzt jetzt bis vor fade_in_ms und prüft
explizit auf die echten Defaults (500/500/0) statt nur auf Felder vor dem
gekürzten Bereich. test_load_rejects_longer_record verzichtet auf die tote
CRC-Neuberechnung, da read_rec() zu lange Records schon anhand der Länge
verwirft, bevor Payload oder CRC gelesen werden.
This commit is contained in:
Michael Sauer
2026-09-12 01:11:18 +02:00
parent 8805aa764d
commit c96e0442c0
2 changed files with 22 additions and 19 deletions
+12 -7
View File
@@ -1,3 +1,4 @@
#include <stddef.h>
#include <string.h>
#include "unity.h"
#include "fake_flash.h"
@@ -89,11 +90,14 @@ static void test_load_accepts_shorter_record(void)
{
nl_settings_t in, out;
uint32_t crc;
/* simulate a record written by an older firmware: length = sizeof - 4, payload truncated */
/* simulate a record written by a firmware that predates fade_in_ms/fade_out_ms/
* ota_pending: length ends right before fade_in_ms. Those fields must come back as
* their real defaults (500 ms / 0), not as zero just because the record didn't carry
* them - that's the whole point of the length tolerance. */
in = sample("alt");
nl_settings_save(&in);
{
uint16_t shorter = (uint16_t)(sizeof(nl_settings_t) - 4);
uint16_t shorter = (uint16_t)offsetof(nl_settings_t, fade_in_ms);
memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 6], &shorter, 2); /* header.length */
crc = nl_crc32(0, &fake_flash_mem[NL_FL_SETTINGS_A], 12 + shorter);
memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 12 + shorter], &crc, 4);
@@ -101,19 +105,20 @@ static void test_load_accepts_shorter_record(void)
TEST_ASSERT_TRUE(nl_settings_load(&out));
TEST_ASSERT_EQUAL_STRING("alt", out.name);
TEST_ASSERT_EQUAL_STRING("ninHome", out.wifi_ssid);
TEST_ASSERT_EQUAL_UINT16(500, out.fade_in_ms);
TEST_ASSERT_EQUAL_UINT16(500, out.fade_out_ms);
TEST_ASSERT_EQUAL_UINT8(0, out.ota_pending);
}
static void test_load_rejects_longer_record(void)
{
nl_settings_t in = sample("x"), out;
uint16_t longer = (uint16_t)(sizeof(nl_settings_t) + 1);
uint32_t crc;
nl_settings_save(&in);
/* read_rec() rejects hdr.length > sizeof(nl_settings_t) outright, before it even reads
* the payload or the CRC - so the stored CRC is irrelevant here and deliberately left
* as whatever nl_settings_save() wrote for the original (shorter) length. */
memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 6], &longer, 2); /* header.length */
/* recompute the CRC over the (bogus, longer) length so the length check itself is
* what rejects the record, not a CRC mismatch left over from the original length */
crc = nl_crc32(0, &fake_flash_mem[NL_FL_SETTINGS_A], 12 + longer);
memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 12 + longer], &crc, 4);
TEST_ASSERT_FALSE(nl_settings_load(&out)); /* unknown newer layout -> defaults */
}