Skip to content

Commit

Permalink
Fix #18 - Handle malformed files with incorrect chunk sizes
Browse files Browse the repository at this point in the history
Detect files that specify chunk sizes that are larger than the actual
file length. Ignore any chunks at the end of the file that are smaller
than the minimum chunk size (of 8 bytes).
  • Loading branch information
danielcasimirosonos committed Jan 17, 2015
1 parent b0ebd64 commit 32c0b17
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/WAV.jl
Original file line number Diff line number Diff line change
Expand Up @@ -640,11 +640,17 @@ function wavread(io::IO; subrange=None, format="double")
# Subtract the size of the format field from chunk_size; now it holds the size
# of all the sub-chunks
chunk_size -= 4
while chunk_size > 0
# GitHub Issue #18: Check if there is enough data to read another chunk
const subchunk_header_size = 4 + sizeof(UInt32)
while chunk_size >= subchunk_header_size
# Read subchunk ID and size
subchunk_id = read(io, UInt8, 4)
subchunk_size = read_le(io, UInt32)
chunk_size -= 8 + subchunk_size
if subchunk_size > chunk_size
chunk_size = 0
break
end
chunk_size -= subchunk_header_size + subchunk_size
# check the subchunk ID
if subchunk_id == b"fmt "
fmt = read_format(io, subchunk_size)
Expand Down
35 changes: 35 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,41 @@ let
@assert nbits == 32
end

## malformed subchunk header, GitHub Issue #18
let
# Create a malformed WAV file
samples = rand(Float32, (10, 1))
io = IOBuffer()

const compression = WAV.get_default_compression(samples)
const nbits = WAV.get_default_precision(samples, compression)
const ext = WAV.WAVFormatExtension()

fmt = WAV.WAVFormat()
fmt.compression_code = compression
fmt.nchannels = size(samples, 2)
fmt.sample_rate = 8000
fmt.nbits = ceil(Integer, nbits / 8) * 8
fmt.block_align = fmt.nbits / 8 * fmt.nchannels
fmt.bps = fmt.sample_rate * fmt.block_align
fmt.data_length = size(samples, 1) * fmt.block_align

WAV.write_header(io, fmt, 37) # 37 instead of 36 is the broken part
WAV.write_format(io, fmt)

# write the data subchunk header
WAV.write(io, b"data")
WAV.write_le(io, fmt.data_length) # UInt32
WAV.write_data(io, fmt, ext, samples)

seek(io, 0)
y, fs, nbits, extra = WAV.wavread(io, format="native")
@assert fs == 8000
@assert nbits == 32
@assert extra == None
@assert samples == y
end

let
tmp=rand(Float64,(10,2))
io = IOBuffer()
Expand Down

0 comments on commit 32c0b17

Please sign in to comment.