ogg: fix possible buffer overrun

If an ogg stream does not match our expectations of how the end of a
buffer may be structured, it was possible to read memory past the end of
the buffer parsed by libogg.  Include a bounds check for this case and
stop parsing.

Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3930

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2134>
This commit is contained in:
Matthew Waters 2022-04-08 11:10:49 +10:00 committed by GStreamer Marge Bot
parent 4c98e2d289
commit 62d09f73b7
3 changed files with 15 additions and 4 deletions

View file

@ -916,14 +916,16 @@ setup_vorbis_mapper (GstOggStream * pad, ogg_packet * packet)
static gboolean static gboolean
is_header_vorbis (GstOggStream * pad, ogg_packet * packet) is_header_vorbis (GstOggStream * pad, ogg_packet * packet)
{ {
int res = 0;
if (packet->bytes == 0 || (packet->packet[0] & 0x01) == 0) if (packet->bytes == 0 || (packet->packet[0] & 0x01) == 0)
return FALSE; return FALSE;
if (packet->packet[0] == 5) { if (packet->packet[0] == 5) {
gst_parse_vorbis_setup_packet (pad, packet); res = gst_parse_vorbis_setup_packet (pad, packet);
} }
return TRUE; return res == 0;
} }
static void static void

View file

@ -97,7 +97,7 @@ gst_parse_vorbis_header_packet (GstOggStream * pad, ogg_packet * packet)
pad->nsn_increment = short_size >> 1; pad->nsn_increment = short_size >> 1;
} }
void int
gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op) gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op)
{ {
/* /*
@ -220,6 +220,10 @@ gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op)
current_pos += 1; current_pos += 1;
current_pos += 5; current_pos += 5;
size -= 1; size -= 1;
/* have we overrun? */
if (current_pos >= op->packet + op->bytes)
return -1;
} }
/* Store mode size information in our info struct */ /* Store mode size information in our info struct */
@ -235,6 +239,11 @@ gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op)
current_pos += 1; current_pos += 1;
*mode_size_ptr++ = (current_pos[0] >> offset) & 0x1; *mode_size_ptr++ = (current_pos[0] >> offset) & 0x1;
current_pos += 5; current_pos += 5;
/* have we overrun? */
if (current_pos >= op->packet + op->bytes)
return -1;
} }
return 0;
} }

View file

@ -27,6 +27,6 @@
G_GNUC_INTERNAL G_GNUC_INTERNAL
void gst_parse_vorbis_header_packet (GstOggStream * pad, ogg_packet * packet); void gst_parse_vorbis_header_packet (GstOggStream * pad, ogg_packet * packet);
G_GNUC_INTERNAL G_GNUC_INTERNAL
void gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op); int gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op);
#endif /* __GST_VORBIS_PARSE_H__ */ #endif /* __GST_VORBIS_PARSE_H__ */