fix(firmware): preserve buffered records appended during flush POST

reporter_flush() snapshotted the buffers under lock, released the lock
to POST, then unconditionally cleared the entire buffer on success.
Records appended by reporter_submit_*() during the in-flight POST were
silently erased. Replace clear() with erase() of just the snapshotted
prefix so concurrent appends survive.

Found via adversarial review (gpt-5.5 reviewer, run 2026-05-01-190903).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-01 13:19:11 -07:00
parent a585a56cff
commit a0eee0e6d4

View File

@@ -6,6 +6,7 @@
#include <HTTPClient.h> #include <HTTPClient.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <WiFi.h> #include <WiFi.h>
#include <algorithm>
#include <vector> #include <vector>
#include <time.h> #include <time.h>
#include <freertos/semphr.h> #include <freertos/semphr.h>
@@ -296,7 +297,10 @@ void reporter_flush(const DeviceConfig& cfg) {
String body = build_camera_batch(cfg, cam_snap); String body = build_camera_batch(cfg, cam_snap);
if (post_json(cfg, "/api/v1/camera/events/batch", body)) { if (post_json(cfg, "/api/v1/camera/events/batch", body)) {
xSemaphoreTake(s_buf_mutex, portMAX_DELAY); xSemaphoreTake(s_buf_mutex, portMAX_DELAY);
s_cam_buf.clear(); // Erase only the prefix we snapshotted; FIFO append from
// submit_camera during the in-flight POST stays buffered.
size_t n = std::min(cam_snap.size(), s_cam_buf.size());
s_cam_buf.erase(s_cam_buf.begin(), s_cam_buf.begin() + n);
xSemaphoreGive(s_buf_mutex); xSemaphoreGive(s_buf_mutex);
} }
} }
@@ -304,7 +308,8 @@ void reporter_flush(const DeviceConfig& cfg) {
String body = build_ble_batch(cfg, ble_snap); String body = build_ble_batch(cfg, ble_snap);
if (post_json(cfg, "/api/v1/events/batch", body)) { if (post_json(cfg, "/api/v1/events/batch", body)) {
xSemaphoreTake(s_buf_mutex, portMAX_DELAY); xSemaphoreTake(s_buf_mutex, portMAX_DELAY);
s_ble_buf.clear(); size_t n = std::min(ble_snap.size(), s_ble_buf.size());
s_ble_buf.erase(s_ble_buf.begin(), s_ble_buf.begin() + n);
xSemaphoreGive(s_buf_mutex); xSemaphoreGive(s_buf_mutex);
} }
} }