summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-09-07 13:51:37 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2010-09-07 13:56:53 +0200
commit6be0c7b7626a30ef3479e2032599271f0f3f17ab (patch)
tree6226b8b3f369c9717c234474cfe242a5050840c3
parentf604e20499901bdaf3cf136b9cf383d66c422d9a (diff)
vrawdepay: handle invalid payload better
Make sure we don't read more data than available in the input buffer. Clip the input data into the output buffer.
-rw-r--r--gst/rtp/gstrtpvrawdepay.c147
1 files changed, 102 insertions, 45 deletions
diff --git a/gst/rtp/gstrtpvrawdepay.c b/gst/rtp/gstrtpvrawdepay.c
index 77ca7979f..70d5f8118 100644
--- a/gst/rtp/gstrtpvrawdepay.c
+++ b/gst/rtp/gstrtpvrawdepay.c
@@ -266,9 +266,10 @@ static GstBuffer *
gst_rtp_vraw_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{
GstRtpVRawDepay *rtpvrawdepay;
- guint8 *payload, *data, *yp, *up, *vp, *headers;
+ guint8 *payload, *data, *dataend, *yp, *up, *vp, *headers;
guint32 timestamp;
- guint cont, ystride, uvstride, pgroup;
+ guint cont, ystride, uvstride, pgroup, payload_len, size;
+ gint width, height, xinc, yinc;
rtpvrawdepay = GST_RTP_VRAW_DEPAY (depayload);
@@ -299,6 +300,8 @@ gst_rtp_vraw_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
}
data = GST_BUFFER_DATA (rtpvrawdepay->outbuf);
+ size = GST_BUFFER_SIZE (rtpvrawdepay->outbuf);
+ dataend = data + size;
/* get pointer and strides of the planes */
yp = data + rtpvrawdepay->yp;
@@ -308,41 +311,79 @@ gst_rtp_vraw_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
ystride = rtpvrawdepay->ystride;
uvstride = rtpvrawdepay->uvstride;
pgroup = rtpvrawdepay->pgroup;
+ width = rtpvrawdepay->width;
+ height = rtpvrawdepay->height;
+ xinc = rtpvrawdepay->xinc;
+ yinc = rtpvrawdepay->yinc;
payload = gst_rtp_buffer_get_payload (buf);
+ payload_len = gst_rtp_buffer_get_payload_len (buf);
+
+ if (payload_len < 3)
+ goto short_packet;
/* skip extended seqnum */
- payload++;
- payload++;
+ payload += 2;
+ payload_len -= 2;
/* remember header position */
headers = payload;
/* find data start */
do {
+ if (payload_len < 6)
+ goto short_packet;
+
cont = payload[4] & 0x80;
+
payload += 6;
+ payload_len -= 6;
} while (cont);
while (TRUE) {
- guint length, line, offs;
+ guint length, line, offs, plen;
guint8 *datap;
- /* read length and cont */
+ /* stop when we run out of data */
+ if (payload_len == 0)
+ break;
+
+ /* read length and cont. This should work because we iterated the headers
+ * above. */
length = (headers[0] << 8) | headers[1];
line = ((headers[2] & 0x7f) << 8) | headers[3];
offs = ((headers[4] & 0x7f) << 8) | headers[5];
cont = headers[4] & 0x80;
headers += 6;
+ /* length must be a multiple of pgroup */
+ if (length % pgroup != 0)
+ goto wrong_length;
+
+ if (length > payload_len)
+ length = payload_len;
+
/* sanity check */
- if (line > (rtpvrawdepay->height - rtpvrawdepay->yinc))
- continue;
- if (offs > (rtpvrawdepay->width - rtpvrawdepay->xinc))
- continue;
+ if (line > (height - yinc)) {
+ GST_WARNING_OBJECT (depayload, "skipping line %d: out of range", line);
+ goto next;
+ }
+ if (offs > (width - xinc)) {
+ GST_WARNING_OBJECT (depayload, "skipping offset %d: out of range", offs);
+ goto next;
+ }
+
+ /* calculate the maximim amount of bytes we can use per line */
+ if (offs + ((length / pgroup) * xinc) > (width - xinc)) {
+ plen = ((width - offs) * pgroup) / xinc;
+ GST_WARNING_OBJECT (depayload, "clipping length %d, offset %d", length,
+ offs);
+ } else
+ plen = length;
- GST_LOG_OBJECT (depayload, "writing length %u, line %u, offset %u", length,
- line, offs);
+ GST_LOG_OBJECT (depayload,
+ "writing length %u/%u, line %u, offset %u, remaining %u", plen, length,
+ line, offs, payload_len);
switch (rtpvrawdepay->format) {
case GST_VIDEO_FORMAT_RGB:
@@ -351,25 +392,27 @@ gst_rtp_vraw_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
case GST_VIDEO_FORMAT_BGRA:
case GST_VIDEO_FORMAT_UYVY:
/* samples are packed just like gstreamer packs them */
- offs /= rtpvrawdepay->xinc;
+ offs /= xinc;
datap = yp + (line * ystride) + (offs * pgroup);
- memcpy (datap, payload, length);
- payload += length;
+
+ memcpy (datap, payload, plen);
break;
case GST_VIDEO_FORMAT_AYUV:
{
gint i;
+ guint8 *p;
datap = yp + (line * ystride) + (offs * 4);
+ p = payload;
/* samples are packed in order Cb-Y-Cr for both interlaced and
* progressive frames */
- for (i = 0; i < length; i += pgroup) {
+ for (i = 0; i < plen; i += pgroup) {
*datap++ = 0;
- *datap++ = payload[1];
- *datap++ = payload[0];
- *datap++ = payload[2];
- payload += pgroup;
+ *datap++ = p[1];
+ *datap++ = p[0];
+ *datap++ = p[2];
+ p += pgroup;
}
break;
}
@@ -377,25 +420,25 @@ gst_rtp_vraw_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{
gint i;
guint uvoff;
- guint8 *yd1p, *yd2p, *udp, *vdp;
+ guint8 *yd1p, *yd2p, *udp, *vdp, *p;
yd1p = yp + (line * ystride) + (offs);
yd2p = yd1p + ystride;
- uvoff =
- (line / rtpvrawdepay->yinc * uvstride) +
- (offs / rtpvrawdepay->xinc);
+ uvoff = (line / yinc * uvstride) + (offs / xinc);
+
udp = up + uvoff;
vdp = vp + uvoff;
+ p = payload;
/* line 0/1: Y00-Y01-Y10-Y11-Cb00-Cr00 Y02-Y03-Y12-Y13-Cb01-Cr01 ... */
- for (i = 0; i < length; i += pgroup) {
- *yd1p++ = payload[0];
- *yd1p++ = payload[1];
- *yd2p++ = payload[2];
- *yd2p++ = payload[3];
- *udp++ = payload[4];
- *vdp++ = payload[5];
- payload += pgroup;
+ for (i = 0; i < plen; i += pgroup) {
+ *yd1p++ = p[0];
+ *yd1p++ = p[1];
+ *yd2p++ = p[2];
+ *yd2p++ = p[3];
+ *udp++ = p[4];
+ *vdp++ = p[5];
+ p += pgroup;
}
break;
}
@@ -403,25 +446,25 @@ gst_rtp_vraw_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{
gint i;
guint uvoff;
- guint8 *ydp, *udp, *vdp;
+ guint8 *ydp, *udp, *vdp, *p;
ydp = yp + (line * ystride) + (offs);
- uvoff =
- (line / rtpvrawdepay->yinc * uvstride) +
- (offs / rtpvrawdepay->xinc);
+ uvoff = (line / yinc * uvstride) + (offs / xinc);
+
udp = up + uvoff;
vdp = vp + uvoff;
+ p = payload;
/* Samples are packed in order Cb0-Y0-Y1-Cr0-Y2-Y3 for both interlaced
* and progressive scan lines */
- for (i = 0; i < length; i += pgroup) {
- *udp++ = payload[0];
- *ydp++ = payload[1];
- *ydp++ = payload[2];
- *vdp++ = payload[3];
- *ydp++ = payload[4];
- *ydp++ = payload[5];
- payload += pgroup;
+ for (i = 0; i < plen; i += pgroup) {
+ *udp++ = p[0];
+ *ydp++ = p[1];
+ *ydp++ = p[2];
+ *vdp++ = p[3];
+ *ydp++ = p[4];
+ *ydp++ = p[5];
+ p += pgroup;
}
break;
}
@@ -429,8 +472,12 @@ gst_rtp_vraw_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
goto unknown_sampling;
}
+ next:
if (!cont)
break;
+
+ payload += length;
+ payload_len -= length;
}
if (gst_rtp_buffer_get_marker (buf)) {
@@ -453,7 +500,17 @@ unknown_sampling:
}
alloc_failed:
{
- GST_DEBUG_OBJECT (depayload, "failed to alloc output buffer");
+ GST_WARNING_OBJECT (depayload, "failed to alloc output buffer");
+ return NULL;
+ }
+wrong_length:
+ {
+ GST_WARNING_OBJECT (depayload, "length not multiple of pgroup");
+ return NULL;
+ }
+short_packet:
+ {
+ GST_WARNING_OBJECT (depayload, "short packet");
return NULL;
}
}