From 127fc2432ca38d71472183be2ff3ca701673ec09 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:39:37 +0200 Subject: [PATCH] Fix exception if number of devices increases after allocating memory (#23724) WIP --- .../xdrv_07_ufs_domoticz.ino | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_07_ufs_domoticz.ino b/tasmota/tasmota_xdrv_driver/xdrv_07_ufs_domoticz.ino index 81a406001..7c28439f9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_07_ufs_domoticz.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_07_ufs_domoticz.ino @@ -92,6 +92,7 @@ typedef struct Domoticz_t { uint32_t fan_debounce; // iFan02 state debounce timer #endif // USE_SONOFF_IFAN int update_timer; + uint8_t devices; uint8_t keys; uint8_t switches; bool subscribe; @@ -122,7 +123,7 @@ bool DomoticzLoadData(void) { Domoticz->Settings.update_timer = root.getUInt(PSTR("Update"), Domoticz->Settings.update_timer); JsonParserArray arr = root[PSTR("Relay")]; if (arr) { - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { if (arr[i]) { Domoticz->Settings.relay_idx[i] = arr[i].getUInt(); } } } @@ -153,9 +154,9 @@ bool DomoticzSaveData(void) { "\"Update\":%u"), Domoticz->Settings.crc32, Domoticz->Settings.update_timer); - if (TasmotaGlobal.devices_present) { + if (Domoticz->devices) { ResponseAppend_P(PSTR(",\"Relay\":")); - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { ResponseAppend_P(PSTR("%c%d"), (0==i)?'[':',', Domoticz->Settings.relay_idx[i]); } ResponseAppend_P(PSTR("]")); @@ -199,7 +200,7 @@ void DomoticzSettingsLoad(bool erase) { // memset(&Domoticz->Settings, 0x00, sizeof(DzSettings_t)); // Won't work as we need to keep our pointers Domoticz->Settings.update_timer = 0; - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { Domoticz->Settings.relay_idx[i] = 0; if (i < Domoticz->keys) { Domoticz->Settings.key_idx[i] = 0; @@ -216,7 +217,7 @@ void DomoticzSettingsLoad(bool erase) { // Init any other parameter in struct DzSettings Domoticz->Settings.update_timer = Settings->domoticz_update_timer; for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { - if (i < TasmotaGlobal.devices_present) { + if (i < Domoticz->devices) { Domoticz->Settings.relay_idx[i] = Settings->domoticz_relay_idx[i]; } if (i < Domoticz->keys) { @@ -250,8 +251,8 @@ void DomoticzSettingsLoad(bool erase) { void DomoticzSettingsSave(void) { // Called from FUNC_SAVE_SETTINGS every SaveData second and at restart uint32_t crc32 = GetCfgCrc32((uint8_t*)&Domoticz->Settings +4, sizeof(DzSettings_t) -4); // Skip crc32 - if (TasmotaGlobal.devices_present) { - crc32 += GetCfgCrc32((uint8_t*)Domoticz->Settings.relay_idx, TasmotaGlobal.devices_present * sizeof(uintdz_t)); + if (Domoticz->devices) { + crc32 += GetCfgCrc32((uint8_t*)Domoticz->Settings.relay_idx, Domoticz->devices * sizeof(uintdz_t)); } if (Domoticz->keys) { crc32 += GetCfgCrc32((uint8_t*)Domoticz->Settings.key_idx, Domoticz->keys * sizeof(uintdz_t)); @@ -301,12 +302,12 @@ int DomoticzRssiQuality(void) { } uint32_t DomoticzRelayIdx(uint32_t relay) { - if (relay >= TasmotaGlobal.devices_present) { return 0; } + if (relay >= Domoticz->devices) { return 0; } return Domoticz->Settings.relay_idx[relay]; } void DomoticzSetRelayIdx(uint32_t relay, uint32_t idx) { - if (relay >= TasmotaGlobal.devices_present) { return; } + if (relay >= Domoticz->devices) { return; } Domoticz->Settings.relay_idx[relay] = idx; } @@ -342,7 +343,7 @@ void DomoticzUpdateFanState(void) { void MqttPublishDomoticzPowerState(uint8_t device) { if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT if (device < 1) { device = 1; } - if (device > TasmotaGlobal.devices_present) { return; } + if (device > Domoticz->devices) { return; } if (DomoticzRelayIdx(device -1)) { #ifdef USE_SHUTTER if (Domoticz->is_shutter) { @@ -388,7 +389,7 @@ void DomoticzMqttUpdate(void) { Domoticz->update_timer--; if (Domoticz->update_timer <= 0) { Domoticz->update_timer = Domoticz->Settings.update_timer; - for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 1; i <= Domoticz->devices; i++) { #ifdef USE_SHUTTER if (Domoticz->is_shutter) { // no power state updates for shutters @@ -412,7 +413,7 @@ void DomoticzMqttUpdate(void) { void DomoticzMqttSubscribe(void) { bool any_relay = false; - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { if (DomoticzRelayIdx(i)) { any_relay = true; break; @@ -433,7 +434,7 @@ void DomoticzMqttSubscribe(void) { int DomoticzIdx2Relay(uint32_t idx) { if (idx > 0) { - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { if (idx == DomoticzRelayIdx(i)) { return i; } @@ -571,7 +572,7 @@ bool DomoticzMqttData(void) { return true; // Stop loop } char stemp1[10]; - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (TasmotaGlobal.devices_present > 1) ? itoa(relay_index +1, stemp1, 10) : ""); + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (Domoticz->devices > 1) ? itoa(relay_index +1, stemp1, 10) : ""); snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); } else { return true; // No command received @@ -745,10 +746,11 @@ void DomoticzInit(void) { Domoticz = (Domoticz_t*)calloc(1, sizeof(Domoticz_t)); // Need calloc to reset registers to 0/false if (nullptr == Domoticz) { return; } - if (TasmotaGlobal.devices_present) { - Domoticz->Settings.relay_idx = (uintdz_t*)calloc(TasmotaGlobal.devices_present, sizeof(uintdz_t)); + Domoticz->devices = TasmotaGlobal.devices_present; + if (Domoticz->devices) { + Domoticz->Settings.relay_idx = (uintdz_t*)calloc(Domoticz->devices, sizeof(uintdz_t)); if (nullptr == Domoticz->Settings.relay_idx) { return; } - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { if (ButtonUsed(i)) { Domoticz->keys++; } if (SwitchUsed(i)) { Domoticz->switches++; } } @@ -763,7 +765,7 @@ void DomoticzInit(void) { } AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DOMOTICZ "Support %d Device(s), %d Button(s), %d Switch(es) and %d Sensors"), - TasmotaGlobal.devices_present, Domoticz->keys, Domoticz->switches, DZ_MAX_SENSORS); + Domoticz->devices, Domoticz->keys, Domoticz->switches, DZ_MAX_SENSORS); DomoticzSettingsLoad(0); Domoticz->update_flag = true; @@ -778,10 +780,10 @@ void CmndDomoticzIdx(void) { // DzIdx0 0 - Reset all disabling subscription too // DzIdx1 403 - Relate relay1 (=Power1) to Domoticz Idx 403 persistent // DzIdx5 403 - Relate relay5 (=Power5) to Domoticz Idx 403 non-persistent (need a rule at boot to become persistent) - if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) { + if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= Domoticz->devices)) { if (XdrvMailbox.payload >= 0) { if (0 == XdrvMailbox.index) { - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { DomoticzSetRelayIdx(i, 0); } } else { @@ -900,7 +902,7 @@ void HandleDomoticzConfiguration(void) { WSContentStart_P(PSTR(D_CONFIGURE_DOMOTICZ)); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_DOMOTICZ, (Domoticz->switches)? D_DOMOTICZ_SWITCH :"", (Domoticz->keys)? D_DOMOTICZ_KEY :""); - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { WSContentSend_P(HTTP_FORM_DOMOTICZ_INDEX, i +1); if (i < Domoticz->switches) { WSContentSend_P(HTTP_FORM_DOMOTICZ_INPUT, 's', i, Domoticz->Settings.switch_idx[i]); @@ -942,7 +944,7 @@ void DomoticzSaveSettings(void) { cmnd += AddWebCommand(PSTR(D_PRFX_DOMOTICZ D_CMND_UPDATETIMER), PSTR("ut"), STR(DOMOTICZ_UPDATE_TIMER)); char arg_idx[5]; char cmnd2[24]; - for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + for (uint32_t i = 0; i < Domoticz->devices; i++) { snprintf_P(cmnd2, sizeof(cmnd2), PSTR(D_PRFX_DOMOTICZ D_CMND_IDX "%d"), i +1); snprintf_P(arg_idx, sizeof(arg_idx), PSTR("r%d"), i); cmnd += DomoticzAddWebCommand(cmnd2, arg_idx, Domoticz->Settings.relay_idx[i]);