diff options
author | Erik de Castro Lopo <erikd@mega-nerd.com> | 2015-02-10 06:36:53 +1100 |
---|---|---|
committer | Erik de Castro Lopo <erikd@mega-nerd.com> | 2015-02-09 20:17:51 +1100 |
commit | b562efc87e6292fc591b7a3a4187969d5001c157 (patch) | |
tree | 8fbd6fec80ffb9e6bbcf7c9728555da2af5337de | |
parent | f4d42d73cd61e7dfb549280699a2c3ef592fcd28 (diff) |
ALAC : Improve input validation and error reporting.
-rw-r--r-- | src/ALAC/ALACAudioTypes.h | 8 | ||||
-rw-r--r-- | src/ALAC/alac_decoder.c | 14 | ||||
-rw-r--r-- | src/alac.c | 41 |
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 ; } @@ -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 */ + |