From 8d426310459955bee2c0d77b8d269c965031dbb3 Mon Sep 17 00:00:00 2001 From: acidburns Date: Tue, 17 Feb 2026 00:32:48 +0100 Subject: [PATCH] Harden history parsing and single-point chart rendering --- src/web_server.cpp | 75 +++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/src/web_server.cpp b/src/web_server.cpp index f233089..40cc317 100644 --- a/src/web_server.cpp +++ b/src/web_server.cpp @@ -252,6 +252,40 @@ static String history_date_from_epoch(uint32_t ts_utc) { return String(buf); } +static bool history_parse_u32_field(const char *start, size_t len, uint32_t &out) { + if (!start || len == 0 || len >= 16) { + return false; + } + char buf[16]; + memcpy(buf, start, len); + buf[len] = '\0'; + + char *end = nullptr; + unsigned long value = strtoul(buf, &end, 10); + if (end == buf || *end != '\0' || value > static_cast(UINT32_MAX)) { + return false; + } + out = static_cast(value); + return true; +} + +static bool history_parse_float_field(const char *start, size_t len, float &out) { + if (!start || len == 0 || len >= 24) { + return false; + } + char buf[24]; + memcpy(buf, start, len); + buf[len] = '\0'; + + char *end = nullptr; + float value = strtof(buf, &end); + if (end == buf || *end != '\0') { + return false; + } + out = value; + return true; +} + static bool history_open_next_file() { if (!g_history.active || g_history.done || g_history.error) { return false; @@ -274,40 +308,32 @@ static bool history_parse_line(const char *line, uint32_t &ts_out, float &p_out) if (!line || line[0] < '0' || line[0] > '9') { return false; } + const char *comma1 = strchr(line, ','); if (!comma1) { return false; } - char ts_buf[16]; - size_t ts_len = static_cast(comma1 - line); - if (ts_len >= sizeof(ts_buf)) { - return false; - } - memcpy(ts_buf, line, ts_len); - ts_buf[ts_len] = '\0'; - char *end = nullptr; - uint32_t ts = static_cast(strtoul(ts_buf, &end, 10)); - if (end == ts_buf) { + + uint32_t ts = 0; + if (!history_parse_u32_field(line, static_cast(comma1 - line), ts)) { return false; } + const char *comma2 = strchr(comma1 + 1, ','); if (!comma2) { return false; } - const char *p_start = comma2 + 1; - const char *p_end = strchr(p_start, ','); - char p_buf[16]; - size_t p_len = p_end ? static_cast(p_end - p_start) : strlen(p_start); - if (p_len == 0 || p_len >= sizeof(p_buf)) { - return false; - } - memcpy(p_buf, p_start, p_len); - p_buf[p_len] = '\0'; - char *endp = nullptr; - float p = strtof(p_buf, &endp); - if (endp == p_buf) { - return false; + + float p = 0.0f; + if (!history_parse_float_field(comma1 + 1, static_cast(comma2 - (comma1 + 1)), p)) { + const char *p_start = comma2 + 1; + const char *p_end = strchr(p_start, ','); + size_t p_len = p_end ? static_cast(p_end - p_start) : strlen(p_start); + if (!history_parse_float_field(p_start, p_len, p)) { + return false; + } } + ts_out = ts; p_out = p; return true; @@ -649,10 +675,11 @@ static void handle_sender() { html += "if(min===max){min=0;}"; html += "ctx.strokeStyle='#333';ctx.lineWidth=1;ctx.beginPath();"; html += "let first=true;"; + html += "const xDen=series.length>1?(series.length-1):1;"; html += "for(let i=0;i