Fix OOB reads and infinite loop in TLV and DMAP parsers
pair_ap/pair-tlv.c (pair_tlv_parse): - Add bounds check before reading type and length bytes (i + 2 > length) - Fix off-by-one in chunked TLV scan loop (j + 1 < length) - Add bounds checks inside data copy loop to prevent OOB memcpy - Add else branch to advance index when size == 0 (prevents infinite loop) rtsp.c (handle_set_parameter_metadata): - Require 8 bytes remaining for tag + length fields (off + 8 <= cl) - Validate value length against remaining buffer before read Reported-by: Tristan Madani <tristan@talencesecurity.com> Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
This commit is contained in:
+15
-2
@@ -162,18 +162,21 @@ pair_tlv_parse(const uint8_t *buffer, size_t length, pair_tlv_values_t *values)
|
||||
size_t i = 0;
|
||||
int ret;
|
||||
while (i < length) {
|
||||
if (i + 2 > length)
|
||||
return PAIR_TLV_ERROR_INSUFFICIENT_SIZE;
|
||||
|
||||
uint8_t type = buffer[i];
|
||||
size_t size = 0;
|
||||
uint8_t *data = NULL;
|
||||
|
||||
// scan TLVs to accumulate total size of subsequent TLVs with same type (chunked data)
|
||||
size_t j = i;
|
||||
while (j < length && buffer[j] == type && buffer[j+1] == 255) {
|
||||
while (j + 1 < length && buffer[j] == type && buffer[j+1] == 255) {
|
||||
size_t chunk_size = buffer[j+1];
|
||||
size += chunk_size;
|
||||
j += chunk_size + 2;
|
||||
}
|
||||
if (j < length && buffer[j] == type) {
|
||||
if (j + 1 < length && buffer[j] == type) {
|
||||
size_t chunk_size = buffer[j+1];
|
||||
size += chunk_size;
|
||||
}
|
||||
@@ -188,12 +191,22 @@ pair_tlv_parse(const uint8_t *buffer, size_t length, pair_tlv_values_t *values)
|
||||
|
||||
size_t remaining = size;
|
||||
while (remaining) {
|
||||
if (i + 2 > length) {
|
||||
free(data);
|
||||
return PAIR_TLV_ERROR_INSUFFICIENT_SIZE;
|
||||
}
|
||||
size_t chunk_size = buffer[i+1];
|
||||
if (chunk_size > length - i - 2) {
|
||||
free(data);
|
||||
return PAIR_TLV_ERROR_INSUFFICIENT_SIZE;
|
||||
}
|
||||
memcpy(p, &buffer[i+2], chunk_size);
|
||||
p += chunk_size;
|
||||
i += chunk_size + 2;
|
||||
remaining -= chunk_size;
|
||||
}
|
||||
} else {
|
||||
i += 2;
|
||||
}
|
||||
|
||||
ret = tlv_add_value_(values, type, data, size);
|
||||
|
||||
@@ -3275,7 +3275,7 @@ static void handle_set_parameter_metadata(__attribute__((unused)) rtsp_conn_info
|
||||
unsigned int off = 8;
|
||||
|
||||
uint32_t itag, vl;
|
||||
while (off < cl) {
|
||||
while (off + 8 <= cl) {
|
||||
// pick up the metadata tag as an unsigned longint
|
||||
memcpy(&itag, (uint32_t *)(cp + off), sizeof(uint32_t)); /* can be misaligned, thus memcpy */
|
||||
itag = ntohl(itag);
|
||||
@@ -3286,6 +3286,9 @@ static void handle_set_parameter_metadata(__attribute__((unused)) rtsp_conn_info
|
||||
vl = ntohl(vl);
|
||||
off += sizeof(uint32_t);
|
||||
|
||||
if (vl > cl - off)
|
||||
break;
|
||||
|
||||
// pass the data over
|
||||
if (vl == 0)
|
||||
send_metadata('core', itag, NULL, 0, NULL, 1);
|
||||
|
||||
Reference in New Issue
Block a user