mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-08 18:39:54 +00:00
mxfdemux: Fix integer overflow causing out of bounds writes when handling invalid uncompressed video
Check ahead of time when parsing the track information whether width, height and bpp are valid and usable without overflows. Fixes ZDI-CAN-21660, CVE-2023-40474 Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2896 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5362>
This commit is contained in:
parent
ff91a3d8d6
commit
ce17e968e4
1 changed files with 43 additions and 8 deletions
|
@ -118,6 +118,8 @@ mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer,
|
|||
gpointer mapping_data, GstBuffer ** outbuf)
|
||||
{
|
||||
MXFUPMappingData *data = mapping_data;
|
||||
gsize expected_in_stride = 0, out_stride = 0;
|
||||
gsize expected_in_size = 0, out_size = 0;
|
||||
|
||||
/* SMPTE 384M 7.1 */
|
||||
if (key->u[12] != 0x15 || (key->u[14] != 0x01 && key->u[14] != 0x02
|
||||
|
@ -146,22 +148,25 @@ mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer,
|
|||
}
|
||||
}
|
||||
|
||||
if (gst_buffer_get_size (buffer) != data->bpp * data->width * data->height) {
|
||||
// Checked for overflows when parsing the descriptor
|
||||
expected_in_stride = data->bpp * data->width;
|
||||
out_stride = GST_ROUND_UP_4 (expected_in_stride);
|
||||
expected_in_size = expected_in_stride * data->height;
|
||||
out_size = out_stride * data->height;
|
||||
|
||||
if (gst_buffer_get_size (buffer) != expected_in_size) {
|
||||
GST_ERROR ("Invalid buffer size");
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
if (data->bpp != 4
|
||||
|| GST_ROUND_UP_4 (data->width * data->bpp) != data->width * data->bpp) {
|
||||
if (data->bpp != 4 || out_stride != expected_in_stride) {
|
||||
guint y;
|
||||
GstBuffer *ret;
|
||||
GstMapInfo inmap, outmap;
|
||||
guint8 *indata, *outdata;
|
||||
|
||||
ret =
|
||||
gst_buffer_new_and_alloc (GST_ROUND_UP_4 (data->width * data->bpp) *
|
||||
data->height);
|
||||
ret = gst_buffer_new_and_alloc (out_size);
|
||||
gst_buffer_map (buffer, &inmap, GST_MAP_READ);
|
||||
gst_buffer_map (ret, &outmap, GST_MAP_WRITE);
|
||||
indata = inmap.data;
|
||||
|
@ -169,8 +174,8 @@ mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer,
|
|||
|
||||
for (y = 0; y < data->height; y++) {
|
||||
memcpy (outdata, indata, data->width * data->bpp);
|
||||
outdata += GST_ROUND_UP_4 (data->width * data->bpp);
|
||||
indata += data->width * data->bpp;
|
||||
outdata += out_stride;
|
||||
indata += expected_in_stride;
|
||||
}
|
||||
|
||||
gst_buffer_unmap (buffer, &inmap);
|
||||
|
@ -378,6 +383,36 @@ mxf_up_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (caps) {
|
||||
MXFUPMappingData *data = *mapping_data;
|
||||
gsize expected_in_stride = 0, out_stride = 0;
|
||||
gsize expected_in_size = 0, out_size = 0;
|
||||
|
||||
// Do some checking of the parameters to see if they're valid and
|
||||
// we can actually work with them.
|
||||
if (data->image_start_offset > data->image_end_offset) {
|
||||
GST_WARNING ("Invalid image start/end offset");
|
||||
g_free (data);
|
||||
*mapping_data = NULL;
|
||||
gst_clear_caps (&caps);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_size_checked_mul (&expected_in_stride, data->bpp, data->width) ||
|
||||
(out_stride = GST_ROUND_UP_4 (expected_in_stride)) < expected_in_stride
|
||||
|| !g_size_checked_mul (&expected_in_size, expected_in_stride,
|
||||
data->height)
|
||||
|| !g_size_checked_mul (&out_size, out_stride, data->height)) {
|
||||
GST_ERROR ("Invalid resolution or bit depth");
|
||||
g_free (data);
|
||||
*mapping_data = NULL;
|
||||
gst_clear_caps (&caps);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue