[vlc-devel] [RFC] demux/xa: Open: fix xa-header parsing
Filip Roséen
filip at atch.se
Mon Feb 20 15:06:59 CET 2017
If a compiler introduce padding between the members of struct
xa_header, the previous way of interpreting the incoming stream will
yield unexpected behavior.
These changes make sure that we interpret the data in a way that is
uniform across platforms; not relying on implementation-defined
behavior.
--
This patch is untested and is therefor marked as RFC; the only thing that is
different, other than defined parsing, is that the previous implementation did
not to any byte-swapping (to respect endianess) for p_xa.iSize before using it.
Other than that I tried keeping the changes to a minimum, even though there are
pending clean-up patches that I will submit if this one gets merged.
Thanks.
---
modules/demux/xa.c | 43 +++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/modules/demux/xa.c b/modules/demux/xa.c
index 028e3568ed..cb48113799 100644
--- a/modules/demux/xa.c
+++ b/modules/demux/xa.c
@@ -79,6 +79,7 @@ typedef struct xa_header_t
uint16_t wBitsPerSample;
} xa_header_t;
+#define HEADER_LENGTH ( 4 + 4 + 2 + 2 + 4 + 4 + 2 + 2 )
#define FRAME_LENGTH 28 /* samples per frame */
/*****************************************************************************
@@ -88,19 +89,30 @@ static int Open( vlc_object_t * p_this )
{
demux_t *p_demux = (demux_t*)p_this;
demux_sys_t *p_sys;
- xa_header_t p_xa;
+ xa_header_t header;
const uint8_t *p_buf;
/* XA file heuristic */
- if( vlc_stream_Peek( p_demux->s, &p_buf, sizeof( p_xa ) )
- < (signed)sizeof( p_xa ) )
+ if( vlc_stream_Peek( p_demux->s, &p_buf, HEADER_LENGTH ) < HEADER_LENGTH )
return VLC_EGENERIC;
- memcpy( &p_xa, p_buf, sizeof( p_xa ) );
- if( ( strncmp( p_xa.xa_id, "XAI", 4 )
- && strncmp( p_xa.xa_id, "XAJ", 4 ) )
- || ( GetWLE( &p_xa.wFormatTag ) != 0x0001)
- || ( GetWLE( &p_xa.wBitsPerSample ) != 16) )
+ memcpy( &header.xa_id, p_buf, sizeof( header.xa_id ) );
+
+ header.iSize = GetDWLE( p_buf + 4 );
+ header.wFormatTag = GetWLE( p_buf + 8 );
+ header.nChannels = GetWLE( p_buf + 10 );
+ header.nSamplesPerSec = GetDWLE( p_buf + 12 );
+ header.nAvgBytesPerSec = GetDWLE( p_buf + 16 );
+ header.nBlockAlign = GetWLE( p_buf + 20 );
+ header.wBitsPerSample = GetWLE( p_buf + 22 );
+
+ if( strncmp( header.xa_id, "XAI", 4 ) && strncmp( header.xa_id, "XAJ", 4 ) )
+ return VLC_EGENERIC;
+
+ if( header.wFormatTag != 0x0001 )
+ return VLC_EGENERIC;
+
+ if( header.wBitsPerSample != 16 )
return VLC_EGENERIC;
p_sys = malloc( sizeof( demux_sys_t ) );
@@ -112,18 +124,21 @@ static int Open( vlc_object_t * p_this )
p_demux->p_sys = p_sys;
p_sys->p_es = NULL;
- /* skip XA header -- cannot fail */
- vlc_stream_Read( p_demux->s, NULL, sizeof( p_xa ) );
+ if( vlc_stream_Read( p_demux->s, NULL, HEADER_LENGTH ) != HEADER_LENGTH )
+ {
+ free( p_sys );
+ return VLC_EGENERIC;
+ }
es_format_t fmt;
es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC('X','A','J',0) );
msg_Dbg( p_demux, "assuming EA ADPCM audio codec" );
- fmt.audio.i_rate = GetDWLE( &p_xa.nSamplesPerSec );
- fmt.audio.i_bytes_per_frame = 15 * GetWLE( &p_xa.nChannels );
+ fmt.audio.i_rate = header.nSamplesPerSec;
+ fmt.audio.i_bytes_per_frame = 15 * header.nChannels;
fmt.audio.i_frame_length = FRAME_LENGTH;
- fmt.audio.i_channels = GetWLE ( &p_xa.nChannels );
+ fmt.audio.i_channels = header.nChannels;
fmt.audio.i_blockalign = fmt.audio.i_bytes_per_frame;
fmt.audio.i_bitspersample = 16;
fmt.i_bitrate = (fmt.audio.i_rate * fmt.audio.i_bytes_per_frame * 8)
@@ -131,7 +146,7 @@ static int Open( vlc_object_t * p_this )
p_sys->i_data_offset = vlc_stream_Tell( p_demux->s );
/* FIXME: better computation */
- p_sys->i_data_size = p_xa.iSize * 15 / 56;
+ p_sys->i_data_size = header.iSize * 15 / 56;
/* How many frames per block (1:1 is too CPU intensive) */
p_sys->i_block_frames = fmt.audio.i_rate / (FRAME_LENGTH * 20) + 1;
p_sys->i_frame_size = fmt.audio.i_bytes_per_frame;
--
2.11.1
More information about the vlc-devel
mailing list