mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
rtph263pay: Fix double free, invalid reads and leak
This commit is contained in:
parent
61bc228a71
commit
64f9d08d3d
2 changed files with 60 additions and 16 deletions
|
@ -901,14 +901,13 @@ gst_rtp_h263_pay_move_window_right (GstRtpH263PayContext * context, guint n,
|
||||||
return rest_bits;
|
return rest_bits;
|
||||||
|
|
||||||
while (n != 0 || context->win_end == ((*data_end) + 1)) {
|
while (n != 0 || context->win_end == ((*data_end) + 1)) {
|
||||||
//guint8 a = *data;
|
guint8 b = context->win_end <= *data_end ? *context->win_end : 0;
|
||||||
if (rest_bits == 0) {
|
if (rest_bits == 0) {
|
||||||
if (n > 8) {
|
if (n > 8) {
|
||||||
context->window = (context->window << 8) | *context->win_end;
|
context->window = (context->window << 8) | b;
|
||||||
n -= 8;
|
n -= 8;
|
||||||
} else {
|
} else {
|
||||||
context->window =
|
context->window = (context->window << n) | (b >> (8 - n));
|
||||||
(context->window << n) | (*context->win_end >> (8 - n));
|
|
||||||
rest_bits = 8 - n;
|
rest_bits = 8 - n;
|
||||||
if (rest_bits == 0)
|
if (rest_bits == 0)
|
||||||
context->win_end++;
|
context->win_end++;
|
||||||
|
@ -916,15 +915,14 @@ gst_rtp_h263_pay_move_window_right (GstRtpH263PayContext * context, guint n,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (n > rest_bits) {
|
if (n > rest_bits) {
|
||||||
context->window =
|
context->window = (context->window << rest_bits) |
|
||||||
(context->window << rest_bits) | (*context->
|
(b & (((guint) pow (2.0, (double) rest_bits)) - 1));
|
||||||
win_end & (((guint) pow (2.0, (double) rest_bits)) - 1));
|
|
||||||
n -= rest_bits;
|
n -= rest_bits;
|
||||||
rest_bits = 0;
|
rest_bits = 0;
|
||||||
} else {
|
} else {
|
||||||
context->window =
|
context->window = (context->window << n) |
|
||||||
(context->window << n) | ((*context->win_end & (((guint) pow (2.0,
|
((b & (((guint) pow (2.0, (double) rest_bits)) - 1)) >>
|
||||||
(double) rest_bits)) - 1)) >> (rest_bits - n));
|
(rest_bits - n));
|
||||||
rest_bits -= n;
|
rest_bits -= n;
|
||||||
if (rest_bits == 0)
|
if (rest_bits == 0)
|
||||||
context->win_end++;
|
context->win_end++;
|
||||||
|
@ -1413,7 +1411,7 @@ gst_rtp_h263_pay_mode_B_fragment (GstRtpH263Pay * rtph263pay,
|
||||||
|
|
||||||
|
|
||||||
/*---------- MODE B MODE FRAGMENTATION ----------*/
|
/*---------- MODE B MODE FRAGMENTATION ----------*/
|
||||||
GstRtpH263PayMB *mac = NULL;
|
GstRtpH263PayMB *mac, *mac0;
|
||||||
guint max_payload_size;
|
guint max_payload_size;
|
||||||
GstRtpH263PayBoundry boundry;
|
GstRtpH263PayBoundry boundry;
|
||||||
guint mb;
|
guint mb;
|
||||||
|
@ -1509,7 +1507,7 @@ gst_rtp_h263_pay_mode_B_fragment (GstRtpH263Pay * rtph263pay,
|
||||||
|
|
||||||
// We are on MB layer
|
// We are on MB layer
|
||||||
|
|
||||||
mac = gst_rtp_h263_pay_mb_new (&boundry, 0);
|
mac = mac0 = gst_rtp_h263_pay_mb_new (&boundry, 0);
|
||||||
for (mb = 0; mb < format_props[context->piclayer->ptype_srcformat][1]; mb++) {
|
for (mb = 0; mb < format_props[context->piclayer->ptype_srcformat][1]; mb++) {
|
||||||
|
|
||||||
GST_LOG ("================ START MB %d =================", mb);
|
GST_LOG ("================ START MB %d =================", mb);
|
||||||
|
@ -1521,8 +1519,13 @@ gst_rtp_h263_pay_mode_B_fragment (GstRtpH263Pay * rtph263pay,
|
||||||
GST_LOG ("Error decoding MB - sbit: %d", 8 - ebit);
|
GST_LOG ("Error decoding MB - sbit: %d", 8 - ebit);
|
||||||
GST_ERROR ("Error decoding in GOB");
|
GST_ERROR ("Error decoding in GOB");
|
||||||
|
|
||||||
|
gst_rtp_h263_pay_mb_destroy (mac0);
|
||||||
goto decode_error;
|
goto decode_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_rtp_h263_pay_mb_destroy (gob->macroblocks[mb]);
|
||||||
|
gob->macroblocks[mb] = mac;
|
||||||
|
|
||||||
//If mb_type == stuffing, don't increment the mb address
|
//If mb_type == stuffing, don't increment the mb address
|
||||||
if (mac->mb_type == 10) {
|
if (mac->mb_type == 10) {
|
||||||
mb--;
|
mb--;
|
||||||
|
@ -1531,8 +1534,6 @@ gst_rtp_h263_pay_mode_B_fragment (GstRtpH263Pay * rtph263pay,
|
||||||
gob->nmacroblocs++;
|
gob->nmacroblocs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
gob->macroblocks[mb] = mac;
|
|
||||||
|
|
||||||
if (mac->end >= gob->end) {
|
if (mac->end >= gob->end) {
|
||||||
GST_LOG ("No more MBs in this GOB");
|
GST_LOG ("No more MBs in this GOB");
|
||||||
if (!mac->ebit) {
|
if (!mac->ebit) {
|
||||||
|
@ -1545,6 +1546,7 @@ gst_rtp_h263_pay_mode_B_fragment (GstRtpH263Pay * rtph263pay,
|
||||||
mac->mba, mac->start, mac->end, mac->length, mac->sbit, mac->ebit);
|
mac->mba, mac->start, mac->end, mac->length, mac->sbit, mac->ebit);
|
||||||
GST_LOG ("================ END MB %d =================", mb);
|
GST_LOG ("================ END MB %d =================", mb);
|
||||||
}
|
}
|
||||||
|
gst_rtp_h263_pay_mb_destroy (mac0);
|
||||||
|
|
||||||
mb = 0;
|
mb = 0;
|
||||||
first = 0;
|
first = 0;
|
||||||
|
@ -1591,11 +1593,10 @@ gst_rtp_h263_pay_mode_B_fragment (GstRtpH263Pay * rtph263pay,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------- END OF MODE B FRAGMENTATION ----------*/
|
/*---------- END OF MODE B FRAGMENTATION ----------*/
|
||||||
gst_rtp_h263_pay_mb_destroy (mac);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
decode_error:
|
decode_error:
|
||||||
gst_rtp_h263_pay_mb_destroy (mac);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,21 @@
|
||||||
"application/x-rtp,media=video,encoding-name=H263,clock-rate=90000," \
|
"application/x-rtp,media=video,encoding-name=H263,clock-rate=90000," \
|
||||||
"payload=" G_STRINGIFY(p)
|
"payload=" G_STRINGIFY(p)
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
have_element (const gchar * element_name)
|
||||||
|
{
|
||||||
|
GstElement *element;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
element = gst_element_factory_make (element_name, NULL);
|
||||||
|
ret = element != NULL;
|
||||||
|
|
||||||
|
if (element)
|
||||||
|
gst_object_unref (element);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static GstBuffer *
|
static GstBuffer *
|
||||||
create_rtp_buffer (guint8 * data, gsize size, guint ts, gint seqnum)
|
create_rtp_buffer (guint8 * data, gsize size, guint ts, gint seqnum)
|
||||||
{
|
{
|
||||||
|
@ -102,6 +117,31 @@ GST_START_TEST (test_h263depay_start_packet_too_small_mode_c)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_h263pay_mode_b_snow)
|
||||||
|
{
|
||||||
|
/* Payloading one large frame (like snow) is more likely to use mode b and
|
||||||
|
* trigger issues in valgrind seen previously like double free, invalid read
|
||||||
|
* etc. */
|
||||||
|
GstHarness *h;
|
||||||
|
guint frames = 1;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (!have_element ("avenc_h263"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
h = gst_harness_new_parse (
|
||||||
|
"avenc_h263 rtp-payload-size=1 ! rtph263pay mtu=1350 ");
|
||||||
|
gst_harness_add_src_parse (h, "videotestsrc pattern=snow is-live=1 ! "
|
||||||
|
"capsfilter caps=\"video/x-raw,format=I420,width=176,height=144\"", TRUE);
|
||||||
|
|
||||||
|
for (i = 0; i < frames; i++)
|
||||||
|
gst_harness_push_from_src (h);
|
||||||
|
fail_unless (gst_harness_buffers_received (h) >= frames);
|
||||||
|
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
rtph263_suite (void)
|
rtph263_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -113,6 +153,9 @@ rtph263_suite (void)
|
||||||
tcase_add_test (tc_chain, test_h263depay_start_packet_too_small_mode_b);
|
tcase_add_test (tc_chain, test_h263depay_start_packet_too_small_mode_b);
|
||||||
tcase_add_test (tc_chain, test_h263depay_start_packet_too_small_mode_c);
|
tcase_add_test (tc_chain, test_h263depay_start_packet_too_small_mode_c);
|
||||||
|
|
||||||
|
suite_add_tcase (s, (tc_chain = tcase_create ("h263pay")));
|
||||||
|
tcase_add_test (tc_chain, test_h263pay_mode_b_snow);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue