Fixed SoundBuffer::loadFromStream reading past the end of the stream (fixes #214)

This commit is contained in:
Laurent Gomila 2013-05-09 10:16:50 +02:00
parent 323aa4e3e7
commit 5453d11d18
2 changed files with 50 additions and 33 deletions

View File

@ -126,9 +126,9 @@ bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
io.tell = &Memory::tell; io.tell = &Memory::tell;
// Initialize the memory data // Initialize the memory data
m_memory.DataStart = static_cast<const char*>(data); m_memory.begin = static_cast<const char*>(data);
m_memory.DataPtr = m_memory.DataStart; m_memory.current = m_memory.begin;
m_memory.TotalSize = sizeInBytes; m_memory.size = sizeInBytes;
// Open the sound file // Open the sound file
SF_INFO fileInfo; SF_INFO fileInfo;
@ -160,9 +160,13 @@ bool SoundFile::openRead(InputStream& stream)
io.seek = &Stream::seek; io.seek = &Stream::seek;
io.tell = &Stream::tell; io.tell = &Stream::tell;
// Initialize the stream data
m_stream.source = &stream;
m_stream.size = stream.getSize();
// Open the sound file // Open the sound file
SF_INFO fileInfo; SF_INFO fileInfo;
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &stream); m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
if (!m_file) if (!m_file)
{ {
err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl; err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
@ -313,7 +317,7 @@ int SoundFile::getFormatFromFilename(const std::string& filename)
sf_count_t SoundFile::Memory::getLength(void* user) sf_count_t SoundFile::Memory::getLength(void* user)
{ {
Memory* memory = static_cast<Memory*>(user); Memory* memory = static_cast<Memory*>(user);
return memory->TotalSize; return memory->size;
} }
@ -322,12 +326,12 @@ sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
{ {
Memory* memory = static_cast<Memory*>(user); Memory* memory = static_cast<Memory*>(user);
sf_count_t position = memory->DataPtr - memory->DataStart; sf_count_t position = tell(user);
if (position + count >= memory->TotalSize) if (position + count >= memory->size)
count = memory->TotalSize - position; count = memory->size - position;
std::memcpy(ptr, memory->DataPtr, static_cast<std::size_t>(count)); std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
memory->DataPtr += count; memory->current += count;
return count; return count;
} }
@ -339,18 +343,18 @@ sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
sf_count_t position = 0; sf_count_t position = 0;
switch (whence) switch (whence)
{ {
case SEEK_SET : position = offset; break; case SEEK_SET : position = offset; break;
case SEEK_CUR : position = memory->DataPtr - memory->DataStart + offset; break; case SEEK_CUR : position = memory->current - memory->begin + offset; break;
case SEEK_END : position = memory->TotalSize - offset; break; case SEEK_END : position = memory->size - offset; break;
default : position = 0; break; default : position = 0; break;
} }
if (position >= memory->TotalSize) if (position >= memory->size)
position = memory->TotalSize - 1; position = memory->size - 1;
else if (position < 0) else if (position < 0)
position = 0; position = 0;
memory->DataPtr = memory->DataStart + position; memory->current = memory->begin + position;
return position; return position;
} }
@ -359,36 +363,45 @@ sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
sf_count_t SoundFile::Memory::tell(void* user) sf_count_t SoundFile::Memory::tell(void* user)
{ {
Memory* memory = static_cast<Memory*>(user); Memory* memory = static_cast<Memory*>(user);
return memory->DataPtr - memory->DataStart; return memory->current - memory->begin;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::getLength(void* userData) sf_count_t SoundFile::Stream::getLength(void* userData)
{ {
sf::InputStream* stream = static_cast<sf::InputStream*>(userData); Stream* stream = static_cast<Stream*>(userData);
return stream->getSize(); return stream->size;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData) sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
{ {
sf::InputStream* stream = static_cast<sf::InputStream*>(userData); Stream* stream = static_cast<Stream*>(userData);
return stream->read(reinterpret_cast<char*>(ptr), count); Int64 position = stream->source->tell();
if (position != -1)
{
count = std::min(count, stream->size - position);
return stream->source->read(reinterpret_cast<char*>(ptr), count);
}
else
{
return -1;
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData) sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
{ {
sf::InputStream* stream = static_cast<sf::InputStream*>(userData); Stream* stream = static_cast<Stream*>(userData);
switch (whence) switch (whence)
{ {
case SEEK_SET : return stream->seek(offset); case SEEK_SET : return stream->source->seek(offset);
case SEEK_CUR : return stream->seek(stream->tell() + offset); case SEEK_CUR : return stream->source->seek(stream->source->tell() + offset);
case SEEK_END : return stream->seek(stream->getSize() - offset); case SEEK_END : return stream->source->seek(stream->size - offset);
default : return stream->seek(0); default : return stream->source->seek(0);
} }
} }
@ -396,8 +409,8 @@ sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::tell(void* userData) sf_count_t SoundFile::Stream::tell(void* userData)
{ {
sf::InputStream* stream = static_cast<sf::InputStream*>(userData); Stream* stream = static_cast<Stream*>(userData);
return stream->tell(); return stream->source->tell();
} }
} // namespace priv } // namespace priv

View File

@ -184,9 +184,9 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct Memory struct Memory
{ {
const char* DataStart; const char* begin;
const char* DataPtr; const char* current;
sf_count_t TotalSize; sf_count_t size;
static sf_count_t getLength(void* user); static sf_count_t getLength(void* user);
static sf_count_t read(void* ptr, sf_count_t count, void* user); static sf_count_t read(void* ptr, sf_count_t count, void* user);
@ -195,11 +195,14 @@ private :
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Callbacks for opening from stream /// \brief Data and callbacks for opening from stream
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct Stream struct Stream
{ {
InputStream* source;
Int64 size;
static sf_count_t getLength(void* user); static sf_count_t getLength(void* user);
static sf_count_t read(void* ptr, sf_count_t count, void* user); static sf_count_t read(void* ptr, sf_count_t count, void* user);
static sf_count_t seek(sf_count_t offset, int whence, void* user); static sf_count_t seek(sf_count_t offset, int whence, void* user);
@ -211,6 +214,7 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SNDFILE* m_file; ///< File descriptor SNDFILE* m_file; ///< File descriptor
Memory m_memory; ///< Memory reading info Memory m_memory; ///< Memory reading info
Stream m_stream; ///< Stream reading info
std::size_t m_sampleCount; ///< Total number of samples in the file std::size_t m_sampleCount; ///< Total number of samples in the file
unsigned int m_channelCount; ///< Number of channels used by the sound unsigned int m_channelCount; ///< Number of channels used by the sound
unsigned int m_sampleRate; ///< Number of samples per second unsigned int m_sampleRate; ///< Number of samples per second