Skip to content

Commit

Permalink
Prevent config corruption by checking whether memory allocation was s…
Browse files Browse the repository at this point in the history
…uccessfull.
  • Loading branch information
tbnobody committed Jan 4, 2024
1 parent c1fc907 commit 4053e31
Show file tree
Hide file tree
Showing 14 changed files with 46 additions and 43 deletions.
3 changes: 3 additions & 0 deletions include/WebApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "WebApi_device.h"
#include "WebApi_devinfo.h"
#include "WebApi_dtu.h"
#include "WebApi_errors.h"
#include "WebApi_eventlog.h"
#include "WebApi_firmware.h"
#include "WebApi_gridprofile.h"
Expand Down Expand Up @@ -34,6 +35,8 @@ class WebApiClass {

static void sendTooManyRequests(AsyncWebServerRequest* request);

static void writeConfig(JsonObject& retMsg, const WebApiError code = WebApiError::GenericSuccess, const String& message = "Settings saved!");

private:
void loop();

Expand Down
1 change: 1 addition & 0 deletions include/WebApi_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ enum WebApiError {
GenericDataTooLarge,
GenericParseError,
GenericValueMissing,
GenericWriteFailed,

DtuBase = 2000,
DtuSerialZero,
Expand Down
17 changes: 17 additions & 0 deletions src/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ bool ConfigurationClass::write()

DynamicJsonDocument doc(JSON_BUFFER_SIZE);

if (doc.capacity() == 0) {
MessageOutput.println("Failed to allocate memory");
return false;
}

JsonObject cfg = doc.createNestedObject("cfg");
cfg["version"] = config.Cfg.Version;
cfg["save_count"] = config.Cfg.SaveCount;
Expand Down Expand Up @@ -151,6 +156,12 @@ bool ConfigurationClass::read()
File f = LittleFS.open(CONFIG_FILENAME, "r", false);

DynamicJsonDocument doc(JSON_BUFFER_SIZE);

if (doc.capacity() == 0) {
MessageOutput.println("Failed to allocate memory");
return false;
}

// Deserialize the JSON document
const DeserializationError error = deserializeJson(doc, f);
if (error) {
Expand Down Expand Up @@ -311,6 +322,12 @@ void ConfigurationClass::migrate()
}

DynamicJsonDocument doc(JSON_BUFFER_SIZE);

if (doc.capacity() == 0) {
MessageOutput.println("Failed to allocate memory");
return;
}

// Deserialize the JSON document
const DeserializationError error = deserializeJson(doc, f);
if (error) {
Expand Down
12 changes: 12 additions & 0 deletions src/WebApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,16 @@ void WebApiClass::sendTooManyRequests(AsyncWebServerRequest* request)
request->send(response);
}

void WebApiClass::writeConfig(JsonObject& retMsg, const WebApiError code, const String& message)
{
if (!Configuration.write()) {
retMsg["message"] = "Write failed!";
retMsg["code"] = WebApiError::GenericWriteFailed;
} else {
retMsg["type"] = "success";
retMsg["message"] = message;
retMsg["code"] = code;
}
}

WebApiClass WebApi;
6 changes: 1 addition & 5 deletions src/WebApi_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,7 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
Display.setLanguage(config.Display.Language);
Display.Diagram().updatePeriod();

Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Settings saved!";
retMsg["code"] = WebApiError::GenericSuccess;
WebApi.writeConfig(retMsg);

response->setLength();
request->send(response);
Expand Down
5 changes: 1 addition & 4 deletions src/WebApi_dtu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,8 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
config.Dtu.Nrf.PaLevel = root["nrf_palevel"].as<uint8_t>();
config.Dtu.Cmt.PaLevel = root["cmt_palevel"].as<int8_t>();
config.Dtu.Cmt.Frequency = root["cmt_frequency"].as<uint32_t>();
Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Settings saved!";
retMsg["code"] = WebApiError::GenericSuccess;
WebApi.writeConfig(retMsg);

response->setLength();
request->send(response);
Expand Down
22 changes: 4 additions & 18 deletions src/WebApi_inverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,8 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
inverter->Serial = strtoll(root["serial"].as<String>().c_str(), NULL, 16);

strncpy(inverter->Name, root["name"].as<String>().c_str(), INV_MAX_NAME_STRLEN);
Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Inverter created!";
retMsg["code"] = WebApiError::InverterAdded;
WebApi.writeConfig(retMsg, WebApiError::InverterAdded, "Inverter created!");

response->setLength();
request->send(response);
Expand Down Expand Up @@ -294,11 +291,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
arrayCount++;
}

Configuration.write();

retMsg["type"] = "success";
retMsg["code"] = WebApiError::InverterChanged;
retMsg["message"] = "Inverter changed!";
WebApi.writeConfig(retMsg, WebApiError::InverterChanged, "Inverter changed!");

response->setLength();
request->send(response);
Expand Down Expand Up @@ -395,11 +388,8 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)

inverter.Serial = 0;
strncpy(inverter.Name, "", sizeof(inverter.Name));
Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Inverter deleted!";
retMsg["code"] = WebApiError::InverterDeleted;
WebApi.writeConfig(retMsg, WebApiError::InverterDeleted, "Inverter deleted!");

response->setLength();
request->send(response);
Expand Down Expand Up @@ -466,11 +456,7 @@ void WebApiInverterClass::onInverterOrder(AsyncWebServerRequest* request)
order++;
}

Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Inverter order saved!";
retMsg["code"] = WebApiError::InverterOrdered;
WebApi.writeConfig(retMsg, WebApiError::InverterOrdered, "Inverter order saved!");

response->setLength();
request->send(response);
Expand Down
5 changes: 1 addition & 4 deletions src/WebApi_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,11 +334,8 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
config.Mqtt.Hass.Retain = root["mqtt_hass_retain"].as<bool>();
config.Mqtt.Hass.IndividualPanels = root["mqtt_hass_individualpanels"].as<bool>();
strlcpy(config.Mqtt.Hass.Topic, root["mqtt_hass_topic"].as<String>().c_str(), sizeof(config.Mqtt.Hass.Topic));
Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Settings saved!";
retMsg["code"] = WebApiError::GenericSuccess;
WebApi.writeConfig(retMsg);

response->setLength();
request->send(response);
Expand Down
5 changes: 1 addition & 4 deletions src/WebApi_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,8 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
}
config.WiFi.ApTimeout = root["aptimeout"].as<uint>();
config.Mdns.Enabled = root["mdnsenabled"].as<bool>();
Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Settings saved!";
retMsg["code"] = WebApiError::GenericSuccess;
WebApi.writeConfig(retMsg);

response->setLength();
request->send(response);
Expand Down
5 changes: 1 addition & 4 deletions src/WebApi_ntp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,8 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
config.Ntp.Latitude = root["latitude"].as<double>();
config.Ntp.Longitude = root["longitude"].as<double>();
config.Ntp.SunsetType = root["sunsettype"].as<uint8_t>();
Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Settings saved!";
retMsg["code"] = WebApiError::GenericSuccess;
WebApi.writeConfig(retMsg);

response->setLength();
request->send(response);
Expand Down
5 changes: 1 addition & 4 deletions src/WebApi_security.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,8 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
CONFIG_T& config = Configuration.get();
strlcpy(config.Security.Password, root["password"].as<String>().c_str(), sizeof(config.Security.Password));
config.Security.AllowReadonly = root["allow_readonly"].as<bool>();
Configuration.write();

retMsg["type"] = "success";
retMsg["message"] = "Settings saved!";
retMsg["code"] = WebApiError::GenericSuccess;
WebApi.writeConfig(retMsg);

response->setLength();
request->send(response);
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"1003": "Daten zu groß!",
"1004": "Fehler beim interpretieren der Daten!",
"1005": "Benötigte Werte fehlen!",
"1006": "Schreiben fehlgeschlagen!",
"2001": "Die Seriennummer darf nicht 0 sein!",
"2002": "Das Abfraginterval muss größer als 0 sein!",
"2003": "Ungültige Sendeleistung angegeben!",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"1003": "Data too large!",
"1004": "Failed to parse data!",
"1005": "Values are missing!",
"1006": "Write failed!",
"2001": "Serial cannot be zero!",
"2002": "Poll interval must be greater zero!",
"2003": "Invalid power level setting!",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"1003": "Données trop importantes !",
"1004": "Échec de l'analyse des données !",
"1005": "Certaines valeurs sont manquantes !",
"1006": "Write failed!",
"2001": "Le numéro de série ne peut pas être nul !",
"2002": "L'intervalle de sondage doit être supérieur à zéro !",
"2003": "Réglage du niveau de puissance invalide !",
Expand Down

0 comments on commit 4053e31

Please sign in to comment.