mirror of
https://github.com/asterisk/asterisk.git
synced 2026-07-05 22:32:32 -07:00
res_rtp_asterisk.c: Address 2 potential T.140 RED buffer overruns.
* Add check to red_t140_to_red() to ensure that the new primary payload can't cause the rtp_red->len array items to wrap or cause an overrun of the rtp_red->t140red_data buffer. * Add check to rtp_red_buffer() to ensure that a T.140 frame to be sent can't cause rtp_red->len array items to wrap or cause an overrun of the rtp_red->buf_data buffer. Resolves: #GHSA-vfhr-r9x9-c687 Resolves: #GHSA-j2mm-57pq-jh94
This commit is contained in:
committed by
George Joseph
parent
8e42fa57de
commit
0749d2a43e
+45
-1
@@ -5517,6 +5517,17 @@ static struct ast_frame *red_t140_to_red(struct rtp_red *red)
|
||||
/* Store length of each generation and primary data length*/
|
||||
for (i = 0; i < red->num_gen; i++)
|
||||
red->len[i] = red->len[i+1];
|
||||
|
||||
/*
|
||||
* RED generation payload sizes are limited to 255 (UCHAR_MAX) bytes by virtue of
|
||||
* red->len being an array of usigned chars. If the new primary payload exceeds that,
|
||||
* we're going to truncate it to 255.
|
||||
*/
|
||||
if (red->t140.datalen > UCHAR_MAX) {
|
||||
ast_log(LOG_WARNING, "New T.140 frame of %d bytes exceeds max of %u. Discarding %d bytes.\n",
|
||||
red->t140.datalen, UCHAR_MAX, red->t140.datalen - UCHAR_MAX);
|
||||
red->t140.datalen = UCHAR_MAX;
|
||||
}
|
||||
red->len[i] = red->t140.datalen;
|
||||
|
||||
/* write each generation length in red header */
|
||||
@@ -9301,7 +9312,13 @@ static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \pre instance is locked */
|
||||
/*! \pre instance is locked
|
||||
*
|
||||
* \warning This code was written many years ago and it's unclear why we actually
|
||||
* buffer OUTGOING T.140 text frames until a command is encountered but we do.
|
||||
*
|
||||
* This may change in the future.
|
||||
*/
|
||||
static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
|
||||
{
|
||||
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
|
||||
@@ -9312,6 +9329,8 @@ static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *f
|
||||
}
|
||||
|
||||
if (frame->datalen > 0) {
|
||||
int space_available = 0;
|
||||
|
||||
if (red->t140.datalen > 0) {
|
||||
const unsigned char *primary = red->buf_data;
|
||||
|
||||
@@ -9328,6 +9347,31 @@ static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *f
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RED generation payload sizes are limited to 255 (UCHAR_MAX) bytes by virtue of
|
||||
* red->len being an array of usigned chars. If adding the current frame will
|
||||
* exceed that, we're going to flush the saved frame then try again. If the new
|
||||
* frame fits, great otherwise we're going to toss it. Without understanding
|
||||
* the purpose of the buffering, that's all we can do now.
|
||||
*/
|
||||
space_available = UCHAR_MAX - red->t140.datalen;
|
||||
|
||||
if (frame->datalen > space_available) {
|
||||
ast_rtp_write(instance, &rtp->red->t140);
|
||||
/*
|
||||
* ast_rtp_write() calls red_t140_to_red() which resets red->t140.datalen
|
||||
* back to 0 so we now have UCHAR_MAX space available.
|
||||
*/
|
||||
space_available = UCHAR_MAX;
|
||||
}
|
||||
|
||||
if (frame->datalen > space_available) {
|
||||
ast_log(LOG_WARNING, "%s: T.140 frame of %d bytes exceeds max of %u. Discarding.\n",
|
||||
ast_rtp_instance_get_channel_id(instance),
|
||||
frame->datalen, UCHAR_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
|
||||
red->t140.datalen += frame->datalen;
|
||||
red->t140.ts = frame->ts;
|
||||
|
||||
Reference in New Issue
Block a user