From 38944a12872dabe0a8f92bdeb189dd2c68b809bb Mon Sep 17 00:00:00 2001 From: Thomas Faour Date: Wed, 22 Jul 2026 16:21:23 -0400 Subject: [PATCH] Fix stack buffer overflow in face-labels parsing fetch_face_labels() clamped the server-reported label count against max_labels by casting the count to int first -- a value >= 2^31 (a perfectly ordinary decimal in JSON) went negative under that cast, so the comparison was always false and the clamp never fired. The loop then ran with the full, unclamped count, writing past the caller's fixed MANAGE_FACE_LABELS_MAX-element stack array on a crafted /frame/face-labels response. Reachable by a compromised/malicious tools server, or a MITM on the default plain-HTTP connection. Fixed by comparing unsigned instead of casting to int. --- firmware/main/frame_client.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/firmware/main/frame_client.c b/firmware/main/frame_client.c index e635090..1ee16d4 100644 --- a/firmware/main/frame_client.c +++ b/firmware/main/frame_client.c @@ -591,7 +591,12 @@ static int fetch_face_labels(const frame_config_t *cfg, manage_face_label_t *out uint32_t count = 0; json_extract_uint(body, "count", &count); - if ((int)count > max_labels) { + /* Unsigned compare: casting count to int first let a server-supplied + * value >= 2^31 (still a perfectly ordinary decimal in the JSON) go + * negative, skipping this clamp entirely and driving the loop below + * with the full attacker/server-controlled count -- out[found] is a + * fixed MANAGE_FACE_LABELS_MAX-element caller stack array. */ + if (count > (uint32_t)max_labels) { count = (uint32_t)max_labels; }