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
+10 -12
View File
@@ -44,11 +44,15 @@ void nl_settings_init(uint32_t addr_a, uint32_t addr_b)
s_addr[1] = addr_b;
}
/* Reads a record and validates it. `r->data` is filled from the on-flash payload,
* zero-extended when an older/shorter layout is found (hdr.length < sizeof(nl_settings_t)):
* the CRC only covers the bytes actually written, so it is checked over the stored length,
* not over the current struct size. A record whose length exceeds the current struct
* (an unknown, newer layout) is rejected outright. */
/* Reads a record and validates it. `r->data` is pre-filled with nl_settings_defaults()
* and only the bytes actually on flash (hdr.length, possibly less than sizeof(nl_settings_t)
* for a record written by an older firmware) are copied over that. Fields a shorter record
* never had (e.g. fade_in_ms/fade_out_ms/token added later) therefore keep their real
* default (500 ms, NINLIGHT_TOKEN_DEFAULT, ...), not zero - a zeroed fade time or an empty
* token would be a behaviour change, not just "unset". The CRC only covers the bytes
* actually written, so it is checked over the stored length, not over the current struct
* size. A record whose length exceeds the current struct (an unknown, newer layout) is
* rejected outright, before either payload or CRC is even read. */
static bool read_rec(int slot, rec_t *r)
{
rec_hdr_t hdr;
@@ -60,8 +64,8 @@ static bool read_rec(int slot, rec_t *r)
hdr.length > sizeof(nl_settings_t))
return false;
memset(r, 0, sizeof *r);
r->hdr = hdr;
nl_settings_defaults(&r->data);
if (nl_flash_read(s_addr[slot] + sizeof hdr, &r->data, hdr.length) != 0)
return false;
if (nl_flash_read(s_addr[slot] + sizeof hdr + hdr.length, &stored_crc, sizeof stored_crc) != 0)
@@ -92,12 +96,6 @@ bool nl_settings_load(nl_settings_t *out)
out->wifi_pass[NL_PASS_LEN - 1] = '\0';
out->token[NL_TOKEN_LEN - 1] = '\0';
out->name[NL_NAME_LEN - 1] = '\0';
/* A record so severely truncated that fade_in_ms/fade_out_ms/token all read back as
* zero carries no usable data; treat it as if nothing was stored at all. */
if (out->fade_in_ms == 0 && out->fade_out_ms == 0 && out->token[0] == '\0') {
nl_settings_defaults(out);
return false;
}
return true;
}