From 21ca4f0576b6c043b434ccc4f9d28def489076f2 Mon Sep 17 00:00:00 2001 From: Peter Matkovski Date: Thu, 9 Jul 2026 17:35:42 +0200 Subject: [PATCH] Fix CodeQL overflowing snprintf in SetPublisher JSON logging Check snprintf return values before advancing the write offset so json_cap - pos cannot underflow when output is truncated. Co-authored-by: Cursor --- components/stream-video/src/sfu/sfu_client.c | 82 ++++++++++++++------ 1 file changed, 58 insertions(+), 24 deletions(-) diff --git a/components/stream-video/src/sfu/sfu_client.c b/components/stream-video/src/sfu/sfu_client.c index 5d706fe..9ffc1d4 100644 --- a/components/stream-video/src/sfu/sfu_client.c +++ b/components/stream-video/src/sfu/sfu_client.c @@ -321,6 +321,19 @@ static const char *sfu_track_type_to_str(stream_video_sfu_models_TrackType type) } } +static bool sfu_buf_advance(size_t *pos, size_t cap, int written) +{ + if (written < 0 || *pos >= cap) { + return false; + } + size_t remaining = cap - *pos; + if ((size_t)written >= remaining) { + return false; + } + *pos += (size_t)written; + return true; +} + static char *sfu_escape_json_string(const char *input) { if (!input) { @@ -1536,34 +1549,55 @@ static stream_video_error_t sfu_send_set_publisher_http( char *json = (char *)malloc(json_cap); if (json) { size_t pos = 0; - pos += snprintf(json + pos, json_cap - pos, - "{\"sdp\":\"%s\",\"session_id\":\"%s\",\"tracks\":[", - escaped_sdp, - client->join_session_id); - for (size_t i = 0; i < track_count; ++i) { + bool json_ok = true; + int n = snprintf(json + pos, json_cap - pos, + "{\"sdp\":\"%s\",\"session_id\":\"%s\",\"tracks\":[", + escaped_sdp, + client->join_session_id); + if (!sfu_buf_advance(&pos, json_cap, n)) { + json_ok = false; + } + for (size_t i = 0; i < track_count && json_ok; ++i) { const sfu_track_info_t *t = &track_infos[i]; if (i > 0) { - pos += snprintf(json + pos, json_cap - pos, ","); + n = snprintf(json + pos, json_cap - pos, ","); + if (!sfu_buf_advance(&pos, json_cap, n)) { + json_ok = false; + break; + } + } + n = snprintf(json + pos, json_cap - pos, + "{\"track_id\":\"%s\",\"track_type\":\"%s\",\"mid\":\"%s\"," + "\"muted\":%s,\"codec\":{\"name\":\"%s\",\"fmtp\":\"%s\"}," + "\"layers\":[{\"rid\":\"%s\",\"video_dimension\":{\"width\":%u,\"height\":%u}," + "\"bitrate\":%u,\"fps\":%u}]}", + t->track_id, + sfu_track_type_to_str(t->track_type), + t->mid, + t->muted ? "true" : "false", + t->codec_name, + t->fmtp, + t->video_rid[0] ? t->video_rid : "", + (unsigned)t->video_width, + (unsigned)t->video_height, + (unsigned)t->video_bitrate, + (unsigned)t->video_fps); + if (!sfu_buf_advance(&pos, json_cap, n)) { + json_ok = false; + break; } - pos += snprintf(json + pos, json_cap - pos, - "{\"track_id\":\"%s\",\"track_type\":\"%s\",\"mid\":\"%s\"," - "\"muted\":%s,\"codec\":{\"name\":\"%s\",\"fmtp\":\"%s\"}," - "\"layers\":[{\"rid\":\"%s\",\"video_dimension\":{\"width\":%u,\"height\":%u}," - "\"bitrate\":%u,\"fps\":%u}]}", - t->track_id, - sfu_track_type_to_str(t->track_type), - t->mid, - t->muted ? "true" : "false", - t->codec_name, - t->fmtp, - t->video_rid[0] ? t->video_rid : "", - (unsigned)t->video_width, - (unsigned)t->video_height, - (unsigned)t->video_bitrate, - (unsigned)t->video_fps); } - snprintf(json + pos, json_cap - pos, "]}"); - ESP_LOGI(TAG, "SetPublisher request JSON: %s", json); + if (json_ok) { + n = snprintf(json + pos, json_cap - pos, "]}"); + if (!sfu_buf_advance(&pos, json_cap, n)) { + json_ok = false; + } + } + if (json_ok) { + ESP_LOGI(TAG, "SetPublisher request JSON: %s", json); + } else { + ESP_LOGW(TAG, "SetPublisher request JSON truncated (buffer too small)"); + } free(json); } free(escaped_sdp);