fix(reporter): accept int JSON for max_move + reject malformed config fields
- max_move now accepts bare int JSON literals (server may emit 12 vs 12.0) - Present-but-wrong-type fields reject the whole update with a log, preventing cfg_version from advancing on malformed payloads - Zero-init CVTuning& out in cv_get_tuning before mutex take for safety
This commit is contained in:
@@ -37,6 +37,7 @@ void cv_apply_tuning(const CVTuning& incoming) {
|
||||
}
|
||||
|
||||
void cv_get_tuning(CVTuning& out) {
|
||||
out = CVTuning{};
|
||||
if (!s_cv_mutex) return;
|
||||
if (xSemaphoreTake(s_cv_mutex, pdMS_TO_TICKS(500)) == pdTRUE) {
|
||||
out = g_cv.tuning;
|
||||
|
||||
@@ -199,12 +199,37 @@ void reporter_heartbeat(const DeviceConfig& cfg, uint32_t uptime_s, int wifi_rss
|
||||
|
||||
CVTuning candidate = current;
|
||||
candidate.cfg_version = new_ver;
|
||||
if (obj["diff_thresh"].is<int>()) candidate.diff_thresh = (uint8_t)obj["diff_thresh"].as<int>();
|
||||
if (obj["min_blob_px"].is<int>()) candidate.min_blob_px = obj["min_blob_px"].as<int>();
|
||||
if (obj["max_move"].is<float>() || obj["max_move"].is<double>())
|
||||
candidate.max_move = obj["max_move"].as<float>();
|
||||
if (obj["max_missed"].is<int>()) candidate.max_missed = obj["max_missed"].as<int>();
|
||||
if (obj["line_offset"].is<int>()) candidate.line_offset = (uint8_t)obj["line_offset"].as<int>();
|
||||
|
||||
// Present-but-wrong-type fields reject the whole update. Absent fields
|
||||
// (isNull == true) fall back to the current value. This prevents
|
||||
// cfg_version bumping while silently dropping malformed fields.
|
||||
bool bad_type = false;
|
||||
if (!obj["diff_thresh"].isNull()) {
|
||||
if (!obj["diff_thresh"].is<int>()) bad_type = true;
|
||||
else candidate.diff_thresh = (uint8_t)obj["diff_thresh"].as<int>();
|
||||
}
|
||||
if (!obj["min_blob_px"].isNull()) {
|
||||
if (!obj["min_blob_px"].is<int>()) bad_type = true;
|
||||
else candidate.min_blob_px = obj["min_blob_px"].as<int>();
|
||||
}
|
||||
if (!obj["max_move"].isNull()) {
|
||||
// max_move is float — accept int literal too (JSON 12 vs 12.0)
|
||||
if (!(obj["max_move"].is<float>() || obj["max_move"].is<double>()
|
||||
|| obj["max_move"].is<int>())) bad_type = true;
|
||||
else candidate.max_move = obj["max_move"].as<float>();
|
||||
}
|
||||
if (!obj["max_missed"].isNull()) {
|
||||
if (!obj["max_missed"].is<int>()) bad_type = true;
|
||||
else candidate.max_missed = obj["max_missed"].as<int>();
|
||||
}
|
||||
if (!obj["line_offset"].isNull()) {
|
||||
if (!obj["line_offset"].is<int>()) bad_type = true;
|
||||
else candidate.line_offset = (uint8_t)obj["line_offset"].as<int>();
|
||||
}
|
||||
if (bad_type) {
|
||||
Serial.printf("[CFG] rejected malformed config v=%u\n", (unsigned)new_ver);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cv_tuning_validate(candidate)) {
|
||||
Serial.printf("[CFG] rejected invalid config v=%u\n", (unsigned)new_ver);
|
||||
|
||||
Reference in New Issue
Block a user