From f735ea7b0d1193bc6c9e8877ca2a04e92474baad Mon Sep 17 00:00:00 2001 From: Marcel Peterkau Date: Sun, 24 Aug 2025 13:31:27 +0200 Subject: [PATCH] hardened EEPROM against out of Bounds and garbage in RAM --- Software/src/config.cpp | 58 ++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/Software/src/config.cpp b/Software/src/config.cpp index 1dc6652..c451ef7 100644 --- a/Software/src/config.cpp +++ b/Software/src/config.cpp @@ -283,9 +283,8 @@ void StoreConfig_EEPROM() /** * @brief Load configuration from EEPROM and validate. * - * Performs CRC check and sanity validation and raises the respective DTCs: - * - DTC_EEPROM_CFG_BAD if CRC fails - * - DTC_EEPROM_CFG_SANITY with bitmask payload if values are out of bounds + * On CRC failure: raise DTC_EEPROM_CFG_BAD and fall back to in-RAM defaults (no writes). + * On CRC OK: run sanity with autocorrect=true and raise DTC_EEPROM_CFG_SANITY with bitmask if needed. */ void GetConfig_EEPROM() { @@ -297,12 +296,20 @@ void GetConfig_EEPROM() const uint32_t checksum = LubeConfig.checksum; LubeConfig.checksum = 0; - MaintainDTC(DTC_EEPROM_CFG_BAD, - (Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)) != checksum)); + const bool badCrc = (Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)) != checksum); + MaintainDTC(DTC_EEPROM_CFG_BAD, badCrc); + if (badCrc) { + // Don’t keep corrupted data in RAM + LubeConfig = LubeConfig_defaults; + LubeConfig.EEPROM_Version = EEPROM_STRUCTURE_REVISION; // explicit in-RAM version + return; + } + + // CRC OK → restore checksum and sanitize (with autocorrect) LubeConfig.checksum = checksum; - const uint32_t sanity = ConfigSanityCheck(false); + const uint32_t sanity = ConfigSanityCheck(true); MaintainDTC(DTC_EEPROM_CFG_SANITY, (sanity > 0), sanity); } @@ -333,33 +340,48 @@ void StorePersistence_EEPROM() * * If the stored start address is out of range, the persistence partition is reset, * formatted, and DTC_EEPROM_PDSADRESS_BAD is raised. - * Otherwise, the record is read and checked; DTC_EEPROM_PDS_BAD is raised on CRC failure. + * Otherwise, the record is read and checked; on CRC failure DTC_EEPROM_PDS_BAD is raised + * and the in-RAM persistence data is reset to a safe default (no writes performed here). */ void GetPersistence_EEPROM() { if (!EEPROM_Available()) return; + // Read wear-level start address ee.readBlock(0, (uint8_t *)&globals.eePersistenceAddress, sizeof(globals.eePersistenceAddress)); - if (globals.eePersistenceAddress < startofPersistence || globals.eePersistenceAddress > ee.getDeviceSize()) + const uint16_t addr = globals.eePersistenceAddress; + const uint16_t need = sizeof(PersistenceData); + const uint16_t dev = ee.getDeviceSize(); + + // Strict range check: addr must be within partition and block must fit into device + if (addr < startofPersistence || (uint32_t)addr + (uint32_t)need > (uint32_t)dev) { MovePersistencePage_EEPROM(true); FormatPersistence_EEPROM(); MaintainDTC(DTC_EEPROM_PDSADRESS_BAD, true); + return; } - else + + // Safe to read the record + ee.readBlock(addr, (uint8_t *)&PersistenceData, sizeof(PersistenceData)); + + const uint32_t checksum = PersistenceData.checksum; + PersistenceData.checksum = 0; + + const bool badCrc = (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum); + MaintainDTC(DTC_EEPROM_PDS_BAD, badCrc); + + if (badCrc) { - ee.readBlock(globals.eePersistenceAddress, (uint8_t *)&PersistenceData, sizeof(PersistenceData)); - - const uint32_t checksum = PersistenceData.checksum; - PersistenceData.checksum = 0; - - MaintainDTC(DTC_EEPROM_PDS_BAD, - (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum)); - - PersistenceData.checksum = checksum; + // Do not keep corrupted data in RAM; leave DTC set, no EEPROM writes here + PersistenceData = {0}; + return; } + + // CRC ok -> restore checksum into the struct kept in RAM + PersistenceData.checksum = checksum; } /**