From ab0eba2035f934e5e67b5ebc527c0a4302c86f88 Mon Sep 17 00:00:00 2001 From: cjkas Date: Mon, 12 Oct 2026 17:59:39 +0200 Subject: [PATCH] fix: leave out /controller items that overflow instead of breaking the JSON The formatter drops a value that doesn't fit but keeps appending the commas and braces after it, so an oversized shade or group streamed invalid JSON. Check overflowed() after each unit, log the item and skip it, and keep producing until a unit or the end so a skip never ends the stream early. Co-Authored-By: Claude Opus 5.5 --- src/Web.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Web.cpp b/src/Web.cpp index 4cc1276..c93ae66 100644 --- a/src/Web.cpp +++ b/src/Web.cpp @@ -533,8 +533,23 @@ private: fmt.setBuffer(unit + offset, sizeof(unit) - offset); } + // An item too big for the unit buffer is left out so the JSON stays valid. + // Skipping one produces nothing, so go on to the next until something is + // produced or the document is done. void produceNext() { consumed = 0; + do produceUnit(); while(unitLen == 0 && section != S_DONE); + } + + // True when the unit just formatted didn't fit. It is logged and skipped. + bool overflowed(const char *what, uint8_t id) { + if(!fmt.overflowed()) return false; + ESP_LOGE(TAG, "/controller: %s %u doesn't fit in %u bytes, leaving it out", what, id, (unsigned)sizeof(unit)); + unitLen = 0; + return true; + } + + void produceUnit() { unitLen = 0; switch(section) { case S_HEADER: { @@ -555,6 +570,8 @@ private: serializeGitVersion(fmt); fmt.endObject(); fmt.beginArray("rooms"); + // Only fixed size values so this can't happen short of a bug. + if(fmt.overflowed()) ESP_LOGE(TAG, "/controller: header doesn't fit in %u bytes", (unsigned)sizeof(unit)); unitLen = fmt.length(); section = S_ROOMS; idx = 0; @@ -577,6 +594,7 @@ private: fmt.beginObject(); serializeRoom(&somfy.rooms[idx], fmt); fmt.endObject(); + if(overflowed("room", somfy.rooms[idx].roomId)) { idx++; return; } unitLen = pos + fmt.length(); idx++; firstInArray = false; @@ -599,6 +617,7 @@ private: fmt.beginObject(); serializeShade(&somfy.shades[idx], fmt); fmt.endObject(); + if(overflowed("shade", somfy.shades[idx].getShadeId())) { idx++; return; } unitLen = pos + fmt.length(); idx++; firstInArray = false; @@ -622,6 +641,7 @@ private: fmt.beginObject(); serializeGroupRef(g, fmt); fmt.beginArray("linkedShades"); + if(overflowed("group", g->getGroupId())) { idx++; return; } unitLen = pos + fmt.length(); lsIdx = 0; firstInArray = false; @@ -650,6 +670,7 @@ private: fmt.beginObject(); serializeShadeRef(lshade, fmt); fmt.endObject(); + if(overflowed("linked shade", lshade->getShadeId())) { lsIdx++; return; } unitLen = pos + fmt.length(); lsIdx++; firstInLSArray = false;