mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 09:40:37 +00:00
rtpjpegpay: do some more sanitity checks
Protect some more against invalid input.
This commit is contained in:
parent
a482677a14
commit
2ed53fd77f
1 changed files with 65 additions and 44 deletions
|
@ -302,7 +302,6 @@ invalid_dimension:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static guint
|
static guint
|
||||||
gst_rtp_jpeg_pay_header_size (const guint8 * data, guint offset)
|
gst_rtp_jpeg_pay_header_size (const guint8 * data, guint offset)
|
||||||
{
|
{
|
||||||
|
@ -310,70 +309,91 @@ gst_rtp_jpeg_pay_header_size (const guint8 * data, guint offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
static guint
|
||||||
gst_rtp_jpeg_pay_read_quant_table (const guint8 * data, guint offset,
|
gst_rtp_jpeg_pay_read_quant_table (const guint8 * data, guint size,
|
||||||
RtpQuantTable tables[], guint remainingBufferSize)
|
guint offset, RtpQuantTable tables[])
|
||||||
{
|
{
|
||||||
gint quant_size, size, result;
|
guint quant_size, tab_size;
|
||||||
guint8 prec;
|
guint8 prec;
|
||||||
guint8 id;
|
guint8 id;
|
||||||
|
|
||||||
result = quant_size = gst_rtp_jpeg_pay_header_size (data, offset);
|
if (offset + 2 > size)
|
||||||
|
return size;
|
||||||
|
|
||||||
|
quant_size = gst_rtp_jpeg_pay_header_size (data, offset);
|
||||||
|
if (quant_size < 2)
|
||||||
|
return size;
|
||||||
|
|
||||||
|
/* clamp to available data */
|
||||||
|
if (offset + quant_size > size)
|
||||||
|
quant_size = size - offset;
|
||||||
|
|
||||||
offset += 2;
|
offset += 2;
|
||||||
quant_size -= 2;
|
quant_size -= 2;
|
||||||
|
|
||||||
/* Protect against rogue data by checking against remainingBufferSize */
|
while (quant_size > 0) {
|
||||||
while (quant_size > 0 && quant_size < remainingBufferSize) {
|
/* not enough to read the id */
|
||||||
|
if (offset + 1 > size)
|
||||||
|
break;
|
||||||
|
|
||||||
id = data[offset] & 0xf;
|
id = data[offset] & 0xf;
|
||||||
|
if (id == 15)
|
||||||
|
/* invalid id received - corrupt data */
|
||||||
|
break;
|
||||||
|
|
||||||
/* Protect against data corruption - limit to max number of quantization tables */
|
prec = (data[offset] & 0xf0) >> 4;
|
||||||
if (id < 15) {
|
if (prec)
|
||||||
prec = (data[offset] & 0xf0) >> 4;
|
tab_size = 128;
|
||||||
if (prec)
|
else
|
||||||
size = 128;
|
tab_size = 64;
|
||||||
else
|
|
||||||
size = 64;
|
|
||||||
|
|
||||||
GST_LOG ("read quant table %d, size %d, prec %02x", id, size, prec);
|
/* there is not enough for the table */
|
||||||
|
if (quant_size < tab_size + 1)
|
||||||
|
break;
|
||||||
|
|
||||||
tables[id].size = size;
|
GST_LOG ("read quant table %d, tab_size %d, prec %02x", id, tab_size, prec);
|
||||||
tables[id].data = &data[offset + 1];
|
|
||||||
|
|
||||||
size += 1;
|
tables[id].size = tab_size;
|
||||||
quant_size -= size;
|
tables[id].data = &data[offset + 1];
|
||||||
offset += size;
|
|
||||||
remainingBufferSize -= size;
|
tab_size += 1;
|
||||||
} else {
|
quant_size -= tab_size;
|
||||||
/*invalid id received - corrupt data */
|
offset += tab_size;
|
||||||
break; /* exit loop */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return offset + quant_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtp_jpeg_pay_read_sof (GstRtpJPEGPay * pay, const guint8 * data,
|
gst_rtp_jpeg_pay_read_sof (GstRtpJPEGPay * pay, const guint8 * data,
|
||||||
guint * offset, CompInfo info[])
|
guint size, guint * offset, CompInfo info[])
|
||||||
{
|
{
|
||||||
guint sof_size;
|
guint sof_size, off;
|
||||||
guint width, height, infolen;
|
guint width, height, infolen;
|
||||||
CompInfo elem;
|
CompInfo elem;
|
||||||
gint i, j;
|
gint i, j;
|
||||||
|
|
||||||
sof_size = gst_rtp_jpeg_pay_header_size (data, *offset);
|
off = *offset;
|
||||||
|
|
||||||
|
/* we need at least 17 bytes for the SOF */
|
||||||
|
if (off + 17 > size)
|
||||||
|
goto wrong_length;
|
||||||
|
|
||||||
|
sof_size = gst_rtp_jpeg_pay_header_size (data, off);
|
||||||
if (sof_size < 17)
|
if (sof_size < 17)
|
||||||
goto wrong_length;
|
goto wrong_length;
|
||||||
|
|
||||||
|
*offset += sof_size;
|
||||||
|
|
||||||
/* skip size */
|
/* skip size */
|
||||||
*offset += 2;
|
off += 2;
|
||||||
|
|
||||||
/* precision should be 8 */
|
/* precision should be 8 */
|
||||||
if (data[(*offset)++] != 8)
|
if (data[off++] != 8)
|
||||||
goto bad_precision;
|
goto bad_precision;
|
||||||
|
|
||||||
/* read dimensions */
|
/* read dimensions */
|
||||||
height = data[*offset] << 8 | data[*offset + 1];
|
height = data[off] << 8 | data[off + 1];
|
||||||
width = data[*offset + 2] << 8 | data[*offset + 3];
|
width = data[off + 2] << 8 | data[off + 3];
|
||||||
*offset += 4;
|
off += 4;
|
||||||
|
|
||||||
GST_LOG_OBJECT (pay, "got dimensions %ux%u", height, width);
|
GST_LOG_OBJECT (pay, "got dimensions %ux%u", height, width);
|
||||||
|
|
||||||
|
@ -386,14 +406,14 @@ gst_rtp_jpeg_pay_read_sof (GstRtpJPEGPay * pay, const guint8 * data,
|
||||||
pay->width = width / 8;
|
pay->width = width / 8;
|
||||||
|
|
||||||
/* we only support 3 components */
|
/* we only support 3 components */
|
||||||
if (data[(*offset)++] != 3)
|
if (data[off++] != 3)
|
||||||
goto bad_components;
|
goto bad_components;
|
||||||
|
|
||||||
infolen = 0;
|
infolen = 0;
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
elem.id = data[(*offset)++];
|
elem.id = data[off++];
|
||||||
elem.samp = data[(*offset)++];
|
elem.samp = data[off++];
|
||||||
elem.qt = data[(*offset)++];
|
elem.qt = data[off++];
|
||||||
GST_LOG_OBJECT (pay, "got comp %d, samp %02x, qt %d", elem.id, elem.samp,
|
GST_LOG_OBJECT (pay, "got comp %d, samp %02x, qt %d", elem.id, elem.samp,
|
||||||
elem.qt);
|
elem.qt);
|
||||||
/* insertion sort from the last element to the first */
|
/* insertion sort from the last element to the first */
|
||||||
|
@ -470,8 +490,9 @@ gst_rtp_jpeg_pay_scan_marker (const guint8 * data, guint size, guint * offset)
|
||||||
} else {
|
} else {
|
||||||
guint8 marker;
|
guint8 marker;
|
||||||
|
|
||||||
marker = data[(*offset)++];
|
marker = data[*offset];
|
||||||
GST_LOG ("found %02x marker", marker);
|
GST_LOG ("found %02x marker at offset %u", marker, *offset);
|
||||||
|
(*offset)++;
|
||||||
return marker;
|
return marker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -515,24 +536,24 @@ gst_rtp_jpeg_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
sos_found = FALSE;
|
sos_found = FALSE;
|
||||||
dqt_found = FALSE;
|
dqt_found = FALSE;
|
||||||
sof_found = FALSE;
|
sof_found = FALSE;
|
||||||
|
|
||||||
while (!sos_found && (offset < size)) {
|
while (!sos_found && (offset < size)) {
|
||||||
GST_LOG_OBJECT (pay, "checking from offset %u", offset);
|
GST_LOG_OBJECT (pay, "checking from offset %u", offset);
|
||||||
switch (gst_rtp_jpeg_pay_scan_marker (data, size, &offset)) {
|
switch (gst_rtp_jpeg_pay_scan_marker (data, size, &offset)) {
|
||||||
case JPEG_MARKER_JFIF:
|
case JPEG_MARKER_JFIF:
|
||||||
case JPEG_MARKER_CMT:
|
case JPEG_MARKER_CMT:
|
||||||
case JPEG_MARKER_DHT:
|
case JPEG_MARKER_DHT:
|
||||||
|
GST_LOG_OBJECT (pay, "skipping marker");
|
||||||
offset += gst_rtp_jpeg_pay_header_size (data, offset);
|
offset += gst_rtp_jpeg_pay_header_size (data, offset);
|
||||||
break;
|
break;
|
||||||
case JPEG_MARKER_SOF:
|
case JPEG_MARKER_SOF:
|
||||||
if (!gst_rtp_jpeg_pay_read_sof (pay, data, &offset, info))
|
if (!gst_rtp_jpeg_pay_read_sof (pay, data, size, &offset, info))
|
||||||
goto invalid_format;
|
goto invalid_format;
|
||||||
sof_found = TRUE;
|
sof_found = TRUE;
|
||||||
break;
|
break;
|
||||||
case JPEG_MARKER_DQT:
|
case JPEG_MARKER_DQT:
|
||||||
GST_LOG ("DQT found");
|
GST_LOG ("DQT found");
|
||||||
offset +=
|
offset = gst_rtp_jpeg_pay_read_quant_table (data, size, offset, tables);
|
||||||
gst_rtp_jpeg_pay_read_quant_table (data, offset, tables,
|
|
||||||
(size - offset));
|
|
||||||
dqt_found = TRUE;
|
dqt_found = TRUE;
|
||||||
break;
|
break;
|
||||||
case JPEG_MARKER_SOS:
|
case JPEG_MARKER_SOS:
|
||||||
|
|
Loading…
Reference in a new issue