wavlike.c: Fix subchunk parsing bug

The function `wavlike_subchunk_parse` was failing to parse files with
a `LIST` chunk containing an `adtl` chunk that was bigger than a
statically sized buffer.

Closes: https://github.com/erikd/libsndfile/issues/167
This commit is contained in:
Erik de Castro Lopo 2016-11-07 18:16:38 +10:00
parent 85795db0ab
commit 5c1efe1c63

View File

@ -895,12 +895,10 @@ wavlike_write_cart_chunk (SF_PRIVATE *psf)
int
wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
{ sf_count_t current_pos ;
char buffer [512] ;
uint32_t chunk_size, bytesread ;
char buffer [2048] ;
uint32_t chunk_size, bytesread = 0 ;
current_pos = psf_fseek (psf, 0, SEEK_CUR) - 4 ;
bytesread = sizeof (chunk_length) ;
current_pos = psf_fseek (psf, 0, SEEK_CUR) ;
if (chunk_length <= 8)
{ /* This case is for broken files generated by PEAK. */
@ -983,8 +981,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
chunk_size += (chunk_size & 1) ;
if (chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
{ psf_log_printf (psf, " *** %M : %u (too big)\n", chunk, chunk_size) ;
psf_binheader_readf (psf, "j", chunk_length) ;
return 0 ;
goto cleanup_subchunk_parse ;
} ;
bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ;
@ -1000,8 +997,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
chunk_size += (chunk_size & 1) ;
if (chunk_size < 1 || chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
{ psf_log_printf (psf, " *** %M : %u (too big)\n", chunk, chunk_size) ;
psf_binheader_readf (psf, "j", chunk_length) ;
break ;
goto cleanup_subchunk_parse ;
} ;
bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ;
@ -1018,13 +1014,11 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
chunk_size += (chunk_size & 1) ;
if (chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
{ psf_log_printf (psf, " *** %M : %u (too big)\n", chunk, chunk_size) ;
psf_binheader_readf (psf, "j", chunk_length) ;
return 0 ;
goto cleanup_subchunk_parse ;
} ;
bytesread += psf_binheader_readf (psf, "j", chunk_size) ;
psf_log_printf (psf, " %M : %u\n", chunk, chunk_size) ;
break ;
goto cleanup_subchunk_parse ;
default :
bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
@ -1073,10 +1067,10 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
} ;
} ;
current_pos = psf_fseek (psf, 0, SEEK_CUR) - current_pos ;
cleanup_subchunk_parse :
if (current_pos - 4 != chunk_length)
psf_log_printf (psf, "**** Bad chunk length %d sbould be %D\n", chunk_length, current_pos - 4) ;
if (chunk_length > bytesread)
bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread) ;
return 0 ;
} /* wavlike_subchunk_parse */