Commit 6fd35e87 authored by Gildas Bazin's avatar Gildas Bazin

* modules/codec/dvbsub.c: another bunch of sanity checks to make the decoder...

* modules/codec/dvbsub.c: another bunch of sanity checks to make the decoder more resiliant to bad streams.
parent 03e12b35
...@@ -785,9 +785,9 @@ static void decode_region_composition( decoder_t *p_dec, bs_t *s ) ...@@ -785,9 +785,9 @@ static void decode_region_composition( decoder_t *p_dec, bs_t *s )
static void dvbsub_render_pdata( decoder_t *, dvbsub_region_t *, int, int, static void dvbsub_render_pdata( decoder_t *, dvbsub_region_t *, int, int,
uint8_t *, int ); uint8_t *, int );
static void dvbsub_pdata2bpp( bs_t *, uint8_t *, int * ); static void dvbsub_pdata2bpp( bs_t *, uint8_t *, int, int * );
static void dvbsub_pdata4bpp( bs_t *, uint8_t *, int * ); static void dvbsub_pdata4bpp( bs_t *, uint8_t *, int, int * );
static void dvbsub_pdata8bpp( bs_t *, uint8_t *, int * ); static void dvbsub_pdata8bpp( bs_t *, uint8_t *, int, int * );
static void decode_object( decoder_t *p_dec, bs_t *s ) static void decode_object( decoder_t *p_dec, bs_t *s )
{ {
...@@ -896,50 +896,73 @@ static void dvbsub_render_pdata( decoder_t *p_dec, dvbsub_region_t *p_region, ...@@ -896,50 +896,73 @@ static void dvbsub_render_pdata( decoder_t *p_dec, dvbsub_region_t *p_region,
int i_x, int i_y, int i_x, int i_y,
uint8_t *p_field, int i_field ) uint8_t *p_field, int i_field )
{ {
uint8_t *p_pixbuf = p_region->p_pixbuf + i_y * p_region->i_width; uint8_t *p_pixbuf;
bs_t bs;
int i_offset = 0; int i_offset = 0;
bs_t bs;
/* Sanity check */
if( !p_region->p_pixbuf )
{
msg_Err( p_dec, "region %i has no pixel buffer!", p_region->i_id );
return;
}
if( i_y < 0 || i_x < 0 || i_y >= p_region->i_height ||
i_x >= p_region->i_width )
{
msg_Dbg( p_dec, "invalid offset (%i,%i)", i_x, i_y );
return;
}
p_pixbuf = p_region->p_pixbuf + i_y * p_region->i_width;
bs_init( &bs, p_field, i_field ); bs_init( &bs, p_field, i_field );
while( !bs_eof( &bs ) ) while( !bs_eof( &bs ) )
{ {
/* Sanity check */
if( i_y >= p_region->i_height ) return;
switch( bs_read( &bs, 8 ) ) switch( bs_read( &bs, 8 ) )
{ {
case 0x10: case 0x10:
dvbsub_pdata2bpp( &bs, p_pixbuf + i_x, &i_offset ); dvbsub_pdata2bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
&i_offset );
break; break;
case 0x11: case 0x11:
dvbsub_pdata4bpp( &bs, p_pixbuf + i_x, &i_offset ); dvbsub_pdata4bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
&i_offset );
break; break;
case 0x12: case 0x12:
dvbsub_pdata8bpp( &bs, p_pixbuf + i_x, &i_offset ); dvbsub_pdata8bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
&i_offset );
break; break;
case 0x20: case 0x20:
case 0x21: case 0x21:
case 0x22: case 0x22:
/* We don't use map tables */ /* We don't use map tables */
break; break;
case 0xf0:
p_pixbuf += 2*p_region->i_width; /* End of line code */ case 0xf0: /* End of line code */
i_offset = 0; p_pixbuf += 2*p_region->i_width;
i_offset = 0; i_y += 2;
break; break;
} }
} }
} }
static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int *pi_off ) static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
{ {
vlc_bool_t b_stop = 0; vlc_bool_t b_stop = 0;
uint16_t i_count = 0;
uint8_t i_color = 0;
while( !b_stop && !bs_eof( s ) ) while( !b_stop && !bs_eof( s ) )
{ {
int i_count = 0, i_color = 0;
if( (i_color = bs_read( s, 2 )) != 0x00 ) if( (i_color = bs_read( s, 2 )) != 0x00 )
{ {
p[*pi_off] = i_color; i_count = 1;
(*pi_off)++;
} }
else else
{ {
...@@ -947,8 +970,6 @@ static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int *pi_off ) ...@@ -947,8 +970,6 @@ static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int *pi_off )
{ {
i_count = 3 + bs_read( s, 3 ); i_count = 3 + bs_read( s, 3 );
i_color = bs_read( s, 2 ); i_color = bs_read( s, 2 );
memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
} }
else else
{ {
...@@ -957,23 +978,18 @@ static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int *pi_off ) ...@@ -957,23 +978,18 @@ static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int *pi_off )
switch( bs_read( s, 2 ) ) //Switch3 switch( bs_read( s, 2 ) ) //Switch3
{ {
case 0x00: case 0x00:
b_stop=1; b_stop = 1;
break; break;
case 0x01: case 0x01:
memset( p + *pi_off, 0, 2 ); i_count = 2;
(*pi_off) += 2;
break; break;
case 0x02: case 0x02:
i_count = 12 + bs_read( s, 4 ); i_count = 12 + bs_read( s, 4 );
i_color = bs_read( s, 2 ); i_color = bs_read( s, 2 );
memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
break; break;
case 0x03: case 0x03:
i_count = 29 + bs_read( s, 8 ); i_count = 29 + bs_read( s, 8 );
i_color = bs_read( s, 2 ); i_color = bs_read( s, 2 );
memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
break; break;
default: default:
break; break;
...@@ -982,29 +998,37 @@ static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int *pi_off ) ...@@ -982,29 +998,37 @@ static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int *pi_off )
else else
{ {
/* 1 pixel color 0 */ /* 1 pixel color 0 */
p[*pi_off] = 0; i_count = 0;
(*pi_off)++;
} }
} }
} }
if( !i_count ) continue;
/* Sanity check */
if( i_count + *pi_off > i_width ) break;
if( i_count == 1 ) p[*pi_off] = i_color;
else memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
} }
bs_align( s ); bs_align( s );
} }
static void dvbsub_pdata4bpp( bs_t *s, uint8_t* p, int *pi_off ) static void dvbsub_pdata4bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
{ {
vlc_bool_t b_stop = 0; vlc_bool_t b_stop = 0;
uint16_t i_count = 0;
uint8_t i_color = 0;
while( !b_stop && !bs_eof( s ) ) while( !b_stop && !bs_eof( s ) )
{ {
int i_count = 0, i_color = 0;
if( (i_color = bs_read( s, 4 )) != 0x00 ) if( (i_color = bs_read( s, 4 )) != 0x00 )
{ {
/* Add 1 pixel */ /* Add 1 pixel */
p[*pi_off] = i_color; i_count = 1;
(*pi_off)++;
} }
else else
{ {
...@@ -1013,13 +1037,11 @@ static void dvbsub_pdata4bpp( bs_t *s, uint8_t* p, int *pi_off ) ...@@ -1013,13 +1037,11 @@ static void dvbsub_pdata4bpp( bs_t *s, uint8_t* p, int *pi_off )
if( bs_show( s, 3 ) != 0x00 ) if( bs_show( s, 3 ) != 0x00 )
{ {
i_count = 2 + bs_read( s, 3 ); i_count = 2 + bs_read( s, 3 );
memset( p + *pi_off, 0, i_count );
(*pi_off) += i_count;
} }
else else
{ {
bs_skip( s, 3 ); bs_skip( s, 3 );
b_stop=1; b_stop = 1;
} }
} }
else else
...@@ -1028,55 +1050,56 @@ static void dvbsub_pdata4bpp( bs_t *s, uint8_t* p, int *pi_off ) ...@@ -1028,55 +1050,56 @@ static void dvbsub_pdata4bpp( bs_t *s, uint8_t* p, int *pi_off )
{ {
i_count = 4 + bs_read( s, 2 ); i_count = 4 + bs_read( s, 2 );
i_color = bs_read( s, 4 ); i_color = bs_read( s, 4 );
memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
} }
else else
{ {
switch ( bs_read( s, 2 ) ) //Switch3 switch ( bs_read( s, 2 ) ) //Switch3
{ {
case 0x0: case 0x0:
memset( p + *pi_off, 0, 1 ); i_count = 1;
(*pi_off) += 1;
break; break;
case 0x1: case 0x1:
memset( p + *pi_off, 0, 2 ); i_count = 2;
(*pi_off) += 2;
break; break;
case 0x2: case 0x2:
i_count = 9 + bs_read( s, 4 ); i_count = 9 + bs_read( s, 4 );
i_color = bs_read( s, 4 ); i_color = bs_read( s, 4 );
memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
break; break;
case 0x3: case 0x3:
i_count= 25 + bs_read( s, 8 ); i_count= 25 + bs_read( s, 8 );
i_color = bs_read( s, 4 ); i_color = bs_read( s, 4 );
memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
break; break;
} }
} }
} }
} }
if( !i_count ) continue;
/* Sanity check */
if( i_count + *pi_off > i_width ) break;
if( i_count == 1 ) p[*pi_off] = i_color;
else memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
} }
bs_align( s ); bs_align( s );
} }
static void dvbsub_pdata8bpp( bs_t *s, uint8_t* p, int *pi_off ) static void dvbsub_pdata8bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
{ {
vlc_bool_t b_stop = 0; vlc_bool_t b_stop = 0;
uint16_t i_count = 0;
uint8_t i_color = 0;
while( !b_stop && !bs_eof( s ) ) while( !b_stop && !bs_eof( s ) )
{ {
int i_count = 0, i_color = 0;
if( (i_color = bs_read( s, 8 )) != 0x00 ) if( (i_color = bs_read( s, 8 )) != 0x00 )
{ {
/* Add 1 pixel */ /* Add 1 pixel */
p[*pi_off] = i_color; i_count = 1;
(*pi_off)++;
} }
else else
{ {
...@@ -1085,8 +1108,6 @@ static void dvbsub_pdata8bpp( bs_t *s, uint8_t* p, int *pi_off ) ...@@ -1085,8 +1108,6 @@ static void dvbsub_pdata8bpp( bs_t *s, uint8_t* p, int *pi_off )
if( bs_show( s, 7 ) != 0x00 ) if( bs_show( s, 7 ) != 0x00 )
{ {
i_count = bs_read( s, 7 ); i_count = bs_read( s, 7 );
memset( p + *pi_off, 0, i_count );
(*pi_off) += i_count;
} }
else else
{ {
...@@ -1098,10 +1119,18 @@ static void dvbsub_pdata8bpp( bs_t *s, uint8_t* p, int *pi_off ) ...@@ -1098,10 +1119,18 @@ static void dvbsub_pdata8bpp( bs_t *s, uint8_t* p, int *pi_off )
{ {
i_count = bs_read( s, 7 ); i_count = bs_read( s, 7 );
i_color = bs_read( s, 8 ); i_color = bs_read( s, 8 );
memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
} }
} }
if( !i_count ) continue;
/* Sanity check */
if( i_count + *pi_off > i_width ) break;
if( i_count == 1 ) p[*pi_off] = i_color;
else memset( p + *pi_off, i_color, i_count );
(*pi_off) += i_count;
} }
bs_align( s ); bs_align( s );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment