Commit 432349278c for freeswitch.com

commit 432349278c66c5347e115b1b17f145068e71a680
Author: Dmitry Verenitsin <morbit85@gmail.com>
Date:   Sat Aug 8 22:28:34 2026 +0500

    [mod_rtmp] Guard FU-A and short frames in rtmp_rtp2rtmpH264 (#3109)

    The FU-A (type 28) handler read the 2-byte FU header and copied
    `datalen - 2` bytes into `fua_buf` without confirming the frame held
    those header bytes. On a 1-byte frame `datalen - 2` wraps to a huge
    unsigned length passed to `switch_buffer_write`, and `q[1]` is read
    past the payload. Reject FU-A frames shorter than 2 bytes.

    Also guard the function entry: bail when `datalen < 1` before reading
    `payload[0]` for the NAL type, so a zero-length frame does not read
    past the payload.

diff --git a/src/mod/endpoints/mod_rtmp/rtmp_video.c b/src/mod/endpoints/mod_rtmp/rtmp_video.c
index 3ec75725e6..5365fe830c 100644
--- a/src/mod/endpoints/mod_rtmp/rtmp_video.c
+++ b/src/mod/endpoints/mod_rtmp/rtmp_video.c
@@ -339,13 +339,19 @@ switch_status_t rtmp_rtp2rtmpH264(rtp2rtmp_helper_t *helper, switch_frame_t *fra
 	switch_rtp_hdr_t *raw_rtp = (switch_rtp_hdr_t *)packet;
 	switch_byte_t *payload = frame->data;
 	int datalen = frame->datalen;
-	int nalType = payload[0] & 0x1f;
+	int nalType;
 	uint32_t size = 0;
 	uint16_t rtp_seq = 0;
 	uint32_t rtp_ts = 0;
 	static const uint8_t rtmp_header17[] = {0x17, 1, 0, 0, 0};
 	static const uint8_t rtmp_header27[] = {0x27, 1, 0, 0, 0};

+	if (datalen < 1) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	nalType = payload[0] & 0x1f;
+
 	// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
 	// 	"read: %-4u: %02x %02x ts:%u seq:%u %s\n",
 	// 	len, payload[0], payload[1], rtp_ts, rtp_seq, raw_rtp->m ? " mark" : "");
@@ -413,11 +419,24 @@ switch_status_t rtmp_rtp2rtmpH264(rtp2rtmp_helper_t *helper, switch_frame_t *fra
 	case 28: //FU-A
 		{
 			uint8_t *q = payload;
-			uint8_t h264_start_bit = q[1] & 0x80;
-			uint8_t h264_end_bit   = q[1] & 0x40;
-			uint8_t h264_type      = q[1] & 0x1F;
-			uint8_t h264_nri       = (q[0] & 0x60) >> 5;
-			uint8_t h264_key       = (h264_nri << 5) | h264_type;
+			uint8_t h264_start_bit;
+			uint8_t h264_end_bit;
+			uint8_t h264_type;
+			uint8_t h264_nri;
+			uint8_t h264_key;
+
+			/* FU-A header is 2 bytes (FU indicator + FU header); reject anything shorter,
+			   else datalen - 2 underflows the unsigned switch_buffer_write length below */
+			if (datalen < 2) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "FU-A packet too short (datalen=%d)\n", datalen);
+				break;
+			}
+
+			h264_start_bit = q[1] & 0x80;
+			h264_end_bit   = q[1] & 0x40;
+			h264_type      = q[1] & 0x1F;
+			h264_nri       = (q[0] & 0x60) >> 5;
+			h264_key       = (h264_nri << 5) | h264_type;

 			if (h264_start_bit) {
 				/* write NAL unit code */