mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-08-19 09:40:21 +00:00
Merge commit from fork
`rtmp_rtmp2rtpH264()` parses two kinds of inbound H.264 RTMP video messages: an AVC configuration record (`0x17/0x00`) that captures SPS/PPS, and NAL-unit messages (`0x17`/`0x27` with `0x01`). Both paths trusted wire-supplied sizes and counts without checking them against the bytes actually present, leading to out-of-bounds reads. NAL-unit walk: - The length-prefix walk advanced the cursor and decremented the unsigned remaining-byte counter by the wire NAL size with no check that the size fit. A NAL size larger than the remaining payload underflowed the counter to near `UINT32_MAX`, kept the loop running, and read the next size prefix from a cursor already past the end of the buffer. The initializer `pdata_len = len - 5` underflowed the same way for a message shorter than the 5-byte AVC header. - Reject `len < 5`, change the loop guard to `pdata_len > lenSize` so each size-prefix read stays in bounds, and reject any NAL whose declared size exceeds the bytes remaining after its prefix. AVC configuration record: - The fixed header fields (`configurationVersion`, `lengthSizeMinusOne`, `numOfSequenceParameterSets`) plus each 2-byte SPS/PPS length prefix and the PPS count byte were read with no minimum-length check. The existing per-entry checks bounded only the SPS/PPS body copies and ran after the length reads. - Reject `len < 11` before the fixed header, and add a remaining-bytes check before each `ntohs` length read and before the PPS count byte. Both changes are correctness-only: well-formed records and NAL streams hit none of the new guards. Malformed or truncated input is rejected with the existing "corrupted data" diagnostic.
This commit is contained in:
@@ -128,7 +128,15 @@ switch_status_t rtmp_rtmp2rtpH264(rtmp2rtp_helper_t *read_helper, uint8_t* data
|
||||
|
||||
if (data[0] == 0x17 && data[1] == 0) {
|
||||
switch_byte_t *pdata = data + 2;
|
||||
int cfgVer = pdata[3];
|
||||
int cfgVer;
|
||||
|
||||
if (len < 11) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "corrupted data\n");
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
cfgVer = pdata[3];
|
||||
if (cfgVer == 1) {
|
||||
int i = 0;
|
||||
int numSPS = 0;
|
||||
@@ -140,6 +148,12 @@ switch_status_t rtmp_rtmp2rtpH264(rtmp2rtp_helper_t *read_helper, uint8_t* data
|
||||
numSPS = pdata[8] & 0x1f;
|
||||
pdata += 9;
|
||||
for (i = 0; i < numSPS; i++) {
|
||||
if (end - pdata < 2) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "corrupted data\n");
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
lenSPS = ntohs(*(uint16_t *)pdata);
|
||||
pdata += 2;
|
||||
|
||||
@@ -154,9 +168,21 @@ switch_status_t rtmp_rtmp2rtpH264(rtmp2rtp_helper_t *read_helper, uint8_t* data
|
||||
pdata += lenSPS;
|
||||
}
|
||||
//pps
|
||||
if (end - pdata < 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "corrupted data\n");
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
numPPS = pdata[0];
|
||||
pdata += 1;
|
||||
for (i = 0; i < numPPS; i++) {
|
||||
if (end - pdata < 2) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "corrupted data\n");
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
lenPPS = ntohs(*(uint16_t *)pdata);
|
||||
pdata += 2;
|
||||
if (lenPPS > end - pdata) {
|
||||
@@ -195,12 +221,20 @@ switch_status_t rtmp_rtmp2rtpH264(rtmp2rtp_helper_t *read_helper, uint8_t* data
|
||||
} else if ((data[0] == 0x17 || data[0] == 0x27) && data[1] == 1) {
|
||||
if (read_helper->sps && read_helper->pps) {
|
||||
switch_byte_t * pdata = data + 5;
|
||||
uint32_t pdata_len = len - 5;
|
||||
uint32_t pdata_len;
|
||||
uint32_t lenSize = read_helper->lenSize;
|
||||
switch_byte_t *nal_buf = NULL;
|
||||
uint32_t nal_len = 0;
|
||||
|
||||
while (pdata_len > 0) {
|
||||
if (len < 5) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "corrupted data\n");
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
pdata_len = len - 5;
|
||||
|
||||
while (pdata_len > lenSize) {
|
||||
uint32_t nalSize = 0;
|
||||
switch (lenSize) {
|
||||
case 1:
|
||||
@@ -220,6 +254,13 @@ switch_status_t rtmp_rtmp2rtpH264(rtmp2rtp_helper_t *read_helper, uint8_t* data
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* reject a NAL that claims more bytes than remain after its length prefix */
|
||||
if (nalSize > pdata_len - lenSize) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "corrupted data\n");
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
nal_buf = pdata + lenSize;
|
||||
nal_len = nalSize;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user