diff options
author | Erik de Castro Lopo <erikd@mega-nerd.com> | 2015-02-12 18:03:10 +1100 |
---|---|---|
committer | Erik de Castro Lopo <erikd@mega-nerd.com> | 2015-02-12 14:13:12 +1100 |
commit | f6cae66853e35098ebb77d83099d7aee9b06063e (patch) | |
tree | 3a7143fff44bd4e475068dcde6facefeec89b97e | |
parent | 77cc8dcb9fc748fd175d7db86a297d62cd0ff3e6 (diff) |
src/w64.c : Refactor and add sanity checking for chunk sizes.
-rw-r--r-- | src/w64.c | 64 |
1 files changed, 29 insertions, 35 deletions
@@ -241,40 +241,40 @@ w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) psf_binheader_readf (psf, "j", 8 - (psf->headindex & 0x7)) ; /* Generate hash of 16 byte marker. */ - bytesread += psf_binheader_readf (psf, "h", &marker) ; - chunk_size = 0 ; - + marker = chunk_size = 0 ; + bytesread = psf_binheader_readf (psf, "eh8", &marker, &chunk_size) ; + if (bytesread == 0) + break ; switch (marker) { case riff_HASH16 : if (parsestage) return SFE_W64_NO_RIFF ; - bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ; - if (psf->filelength != chunk_size) psf_log_printf (psf, "riff : %D (should be %D)\n", chunk_size, psf->filelength) ; else psf_log_printf (psf, "riff : %D\n", chunk_size) ; parsestage |= HAVE_riff ; + + bytesread += psf_binheader_readf (psf, "h", &marker) ; + if (marker == wave_HASH16) + { if ((parsestage & HAVE_riff) != HAVE_riff) + return SFE_W64_NO_WAVE ; + psf_log_printf (psf, "wave\n") ; + parsestage |= HAVE_wave ; + } ; + chunk_size = 0 ; break ; case ACID_HASH16: psf_log_printf (psf, "Looks like an ACID file. Exiting.\n") ; return SFE_UNIMPLEMENTED ; - case wave_HASH16 : - if ((parsestage & HAVE_riff) != HAVE_riff) - return SFE_W64_NO_WAVE ; - psf_log_printf (psf, "wave\n") ; - parsestage |= HAVE_wave ; - break ; - case fmt_HASH16 : if ((parsestage & (HAVE_riff | HAVE_wave)) != (HAVE_riff | HAVE_wave)) return SFE_WAV_NO_FMT ; - bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, " fmt : %D\n", chunk_size) ; /* size of 16 byte marker and 8 byte chunk_size value. */ @@ -288,15 +288,17 @@ w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) format = wav_fmt->format ; parsestage |= HAVE_fmt ; + chunk_size = 0 ; break ; case fact_HASH16: { sf_count_t frames ; - psf_binheader_readf (psf, "e88", &chunk_size, &frames) ; + psf_binheader_readf (psf, "e8", &frames) ; psf_log_printf (psf, " fact : %D\n frames : %D\n", chunk_size, frames) ; } ; + chunk_size = 0 ; break ; @@ -304,8 +306,6 @@ w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) if ((parsestage & (HAVE_riff | HAVE_wave | HAVE_fmt)) != (HAVE_riff | HAVE_wave | HAVE_fmt)) return SFE_W64_NO_DATA ; - psf_binheader_readf (psf, "e8", &chunk_size) ; - psf->dataoffset = psf_ftell (psf) ; psf->datalength = SF_MIN (chunk_size - 24, psf->filelength - psf->dataoffset) ; @@ -321,52 +321,41 @@ w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) /* Seek past data and continue reading header. */ psf_fseek (psf, chunk_size, SEEK_CUR) ; + chunk_size = 0 ; break ; case levl_HASH16 : - psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, "levl : %D\n", chunk_size) ; - dword = chunk_size ; - psf_binheader_readf (psf, "j", dword - 24) ; + chunk_size -= 24 ; break ; case list_HASH16 : - psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, "list : %D\n", chunk_size) ; - dword = chunk_size ; - psf_binheader_readf (psf, "j", dword - 24) ; + chunk_size -= 24 ; break ; case junk_HASH16 : - psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, "junk : %D\n", chunk_size) ; - dword = chunk_size ; - psf_binheader_readf (psf, "j", dword - 24) ; + chunk_size -= 24 ; break ; case bext_MARKER : - psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, "bext : %D\n", chunk_size) ; - dword = chunk_size ; - psf_binheader_readf (psf, "j", dword - 24) ; + chunk_size -= 24 ; break ; case MARKER_HASH16 : - psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, "marker : %D\n", chunk_size) ; - dword = chunk_size ; - psf_binheader_readf (psf, "j", dword - 24) ; + chunk_size -= 24 ; break ; case SUMLIST_HASH16 : - psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, "summary list : %D\n", chunk_size) ; - dword = chunk_size ; - psf_binheader_readf (psf, "j", dword - 24) ; + chunk_size -= 24 ; break ; default : - psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ; + psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D with length %D. Exiting parser.\n", marker, psf_ftell (psf) - 8, chunk_size) ; done = SF_TRUE ; break ; } ; /* switch (dword) */ @@ -376,6 +365,11 @@ w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) if (psf_ftell (psf) >= (psf->filelength - (2 * SIGNED_SIZEOF (dword)))) break ; + + if (chunk_size > 0 && chunk_size < 0xffff0000) + { dword = chunk_size ; + psf_binheader_readf (psf, "j", dword - 24) ; + } ; } ; /* while (1) */ if (psf->dataoffset <= 0) |