summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik de Castro Lopo <erikd@mega-nerd.com>2015-02-10 06:36:53 +1100
committerErik de Castro Lopo <erikd@mega-nerd.com>2015-02-09 20:17:51 +1100
commitb562efc87e6292fc591b7a3a4187969d5001c157 (patch)
tree8fbd6fec80ffb9e6bbcf7c9728555da2af5337de
parentf4d42d73cd61e7dfb549280699a2c3ef592fcd28 (diff)
ALAC : Improve input validation and error reporting.
-rw-r--r--src/ALAC/ALACAudioTypes.h8
-rw-r--r--src/ALAC/alac_decoder.c14
-rw-r--r--src/alac.c41
3 files changed, 53 insertions, 10 deletions
diff --git a/src/ALAC/ALACAudioTypes.h b/src/ALAC/ALACAudioTypes.h
index 7ac19b7..52d3f44 100644
--- a/src/ALAC/ALACAudioTypes.h
+++ b/src/ALAC/ALACAudioTypes.h
@@ -60,6 +60,14 @@ enum
kALAC_ParamError = -50,
kALAC_MemFullError = -108,
fALAC_FrameLengthError = -666,
+
+ /* Add for libsndfile */
+ kALAC_BadBitWidth = -0x100000,
+ kALAC_IncompatibleVersion = -0x100001,
+ kALAC_BadSpecificConfigSize = -0x100002,
+ kALAC_ZeroChannelCount = -0x100003,
+ kALAC_NumSamplesTooBig = -0x100004,
+ kALAC_UnsupportedElement = -0x100005,
} ;
enum
diff --git a/src/ALAC/alac_decoder.c b/src/ALAC/alac_decoder.c
index cfd981c..6c124e6 100644
--- a/src/ALAC/alac_decoder.c
+++ b/src/ALAC/alac_decoder.c
@@ -108,14 +108,14 @@ alac_decoder_init (ALAC_DECODER *p, void * inMagicCookie, uint32_t inMagicCookie
p->mConfig = theConfig ;
p->mNumChannels = theConfig.numChannels ;
- RequireAction (p->mConfig.compatibleVersion <= kALACVersion, return kALAC_ParamError ;) ;
-
+ RequireAction (p->mConfig.compatibleVersion <= kALACVersion, return kALAC_IncompatibleVersion ;) ;
+ RequireAction ((p->mConfig.bitDepth >= 8 && p->mConfig.bitDepth <= 32), return kALAC_BadBitWidth ;) ;
RequireAction ((p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->mPredictor != NULL),
status = kALAC_MemFullError ; goto Exit ;) ;
}
else
{
- status = kALAC_ParamError ;
+ status = kALAC_BadSpecificConfigSize ;
}
// skip to Channel Layout Info
@@ -166,7 +166,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
uint32_t numChannels = p->mNumChannels ;
RequireAction ((bits != NULL) && (sampleBuffer != NULL) && (outNumSamples != NULL), return kALAC_ParamError ;) ;
- RequireAction (p->mNumChannels > 0, return kALAC_ParamError ;) ;
+ RequireAction (p->mNumChannels > 0, return kALAC_ZeroChannelCount ;) ;
p->mActiveElements = 0 ;
channelIndex = 0 ;
@@ -217,7 +217,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
numSamples = BitBufferRead (bits, 16) << 16 ;
numSamples |= BitBufferRead (bits, 16) ;
- RequireAction (numSamples < kALACDefaultFramesPerPacket, return kALAC_ParamError ;) ;
+ RequireAction (numSamples < kALACDefaultFramesPerPacket, return kALAC_NumSamplesTooBig ;) ;
}
if (escapeFlag == 0)
@@ -370,7 +370,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
numSamples = BitBufferRead (bits, 16) << 16 ;
numSamples |= BitBufferRead (bits, 16) ;
- RequireAction (numSamples < kALACDefaultFramesPerPacket, return kALAC_ParamError ;) ;
+ RequireAction (numSamples < kALACDefaultFramesPerPacket, return kALAC_NumSamplesTooBig ;) ;
}
if (escapeFlag == 0)
@@ -527,7 +527,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
{
// unsupported element, bail
//AssertNoErr (tag) ;
- status = kALAC_ParamError ;
+ status = kALAC_UnsupportedElement ;
break ;
}
diff --git a/src/alac.c b/src/alac.c
index 33c9c3d..970783a 100644
--- a/src/alac.c
+++ b/src/alac.c
@@ -99,6 +99,8 @@ static PAKT_INFO * alac_pakt_append (PAKT_INFO * info, uint32_t value) ;
static uint8_t * alac_pakt_encode (const SF_PRIVATE *psf, uint32_t * pakt_size) ;
static sf_count_t alac_pakt_block_offset (const PAKT_INFO *info, uint32_t block) ;
+static const char * alac_error_string (int error) ;
+
/*============================================================================================
** ALAC Reader initialisation function.
*/
@@ -233,6 +235,7 @@ static int
alac_reader_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info)
{ ALAC_PRIVATE *plac ;
uint32_t kuki_size ;
+ int error ;
union { uint8_t kuki [512] ; uint32_t alignment ; } u ;
if (info == NULL)
@@ -264,7 +267,11 @@ alac_reader_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info)
/* Read in the ALAC cookie data and pass it to the init function. */
kuki_size = alac_kuki_read (psf, info->kuki_offset, u.kuki, sizeof (u.kuki)) ;
- alac_decoder_init (&plac->decoder, u.kuki, kuki_size) ;
+ if ((error = alac_decoder_init (&plac->decoder, u.kuki, kuki_size)) != ALAC_noErr)
+ { psf_log_printf (psf, "*** alac_decoder_init() returned %s. ***\n", alac_error_string (error)) ;
+ return SFE_INTERNAL ;
+ } ;
+
if (plac->decoder.mNumChannels != (unsigned) psf->sf.channels)
{ psf_log_printf (psf, "*** Initialized decoder has %u channels, but it should be %d. ***\n", plac->decoder.mNumChannels, psf->sf.channels) ;
@@ -395,7 +402,7 @@ alac_reader_calc_frames (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
static int
alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
{ ALAC_DECODER *pdec = &plac->decoder ;
- uint8_t byte_buffer [ALAC_BYTE_BUFFER_SIZE] ;
+ uint8_t byte_buffer [psf->sf.channels * ALAC_BYTE_BUFFER_SIZE] ;
uint32_t packet_size ;
BitBuffer bit_buffer ;
@@ -408,7 +415,7 @@ alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
psf_fseek (psf, plac->input_data_pos, SEEK_SET) ;
- if (packet_size > SIGNED_SIZEOF (byte_buffer))
+ if (packet_size > sizeof (byte_buffer))
{ psf_log_printf (psf, "%s : bad packet_size (%u)\n", __func__, packet_size) ;
return 0 ;
} ;
@@ -958,3 +965,31 @@ alac_kuki_read (SF_PRIVATE * psf, uint32_t kuki_offset, uint8_t * kuki, size_t k
return kuki_size ;
} /* alac_kuki_read */
+
+#define CASE_NAME(x) case x : return #x ; break ;
+
+static const char *
+alac_error_string (int error)
+{ static char errstr [128] ;
+ switch (error)
+ { CASE_NAME (kALAC_UnimplementedError) ;
+ CASE_NAME (kALAC_FileNotFoundError) ;
+ CASE_NAME (kALAC_ParamError) ;
+ CASE_NAME (kALAC_MemFullError) ;
+ CASE_NAME (fALAC_FrameLengthError) ;
+
+ /* Added for libsndfile */
+ CASE_NAME (kALAC_BadBitWidth) ;
+ CASE_NAME (kALAC_IncompatibleVersion) ;
+ CASE_NAME (kALAC_BadSpecificConfigSize) ;
+ CASE_NAME (kALAC_ZeroChannelCount) ;
+ CASE_NAME (kALAC_NumSamplesTooBig) ;
+ CASE_NAME (kALAC_UnsupportedElement) ;
+ default :
+ break ;
+ } ;
+
+ snprintf (errstr, sizeof (errstr), "Unknown error %d", error) ;
+ return errstr ;
+} /* alac_error_string */
+