MemReadIOCallback, SafeReadIOCallback: add new classes for safe (memory) reading

squash! EbmlMemoryStream: add new class for safe memory reading
This commit is contained in:
Moritz Bunkus 2014-12-19 18:28:39 +01:00
parent ce72b9266a
commit 6ba868a49b
5 changed files with 428 additions and 0 deletions

View File

@ -1,3 +1,8 @@
2014-12-19 Moritz Bunkus <moritz@bunkus.org>
* EbmlMemoryStream: add a new class for safe memory access that
throws exception on failures.
2014-12-18 Moritz Bunkus <moritz@bunkus.org>
* EbmlMaster: Fixed read() trying to calculate the end position of

66
ebml/MemReadIOCallback.h Normal file
View File

@ -0,0 +1,66 @@
/****************************************************************************
** libebml : parse EBML files, see http://embl.sourceforge.net/
**
** <file/class description>
**
** Copyright (C) 2014 Moritz Bunkus. All rights reserved.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**
** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
**
** Contact license@matroska.org if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
/*!
\file
\author Moritz Bunkus <moritz@bunkus.org>
*/
#ifndef LIBEBML_MEMREADIOCALLBACK_H
#define LIBEBML_MEMREADIOCALLBACK_H
#include "IOCallback.h"
START_LIBEBML_NAMESPACE
class EBML_DLL_API EbmlBinary;
class EBML_DLL_API MemReadIOCallback : public IOCallback {
protected:
uint8 const *mStart, *mEnd, *mPtr;
public:
MemReadIOCallback(void const *Ptr, size_t Size);
MemReadIOCallback(EbmlBinary const &Binary);
MemReadIOCallback(MemReadIOCallback const &Mem);
virtual ~MemReadIOCallback();
uint32 read(void *Buffer, size_t Size);
void setFilePointer(int64 Offset, seek_mode Mode = seek_beginning);
size_t write(void const *, size_t) { return 0; }
virtual uint64 getFilePointer() { return mPtr - mStart; }
void close() {}
binary const *GetDataBuffer() const { return mPtr; }
uint64 GetDataBufferSize() const { return mEnd - mStart; }
protected:
void Init(void const *Ptr, size_t Size);
};
END_LIBEBML_NAMESPACE
#endif // LIBEBML_MEMREADIOCALLBACK_H

91
ebml/SafeReadIOCallback.h Normal file
View File

@ -0,0 +1,91 @@
/****************************************************************************
** libebml : parse EBML files, see http://embl.sourceforge.net/
**
** <file/class description>
**
** Copyright (C) 2002-2014 Moritz Bunkus. All rights reserved.
**
** This file is part of libebml.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**
** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
**
** Contact license@matroska.org if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
/*!
\file
\version \$Id$
\author Moritz Bunkus <moritz@bunkus.org>
*/
#ifndef LIBEBML_SAFEREADIOCALLBACK_H
#define LIBEBML_SAFEREADIOCALLBACK_H
#include "EbmlTypes.h"
START_LIBEBML_NAMESPACE
class EBML_DLL_API IOCallback;
class EBML_DLL_API EbmlBinary;
class EBML_DLL_API SafeReadIOCallback {
public:
class EndOfStreamX {
public:
size_t mMissingBytes;
EndOfStreamX(std::size_t MissingBytes);
};
private:
IOCallback *mIO;
bool mDeleteIO;
size_t mSize;
public:
SafeReadIOCallback(IOCallback *IO, bool DeleteIO);
SafeReadIOCallback(void const *Mem, size_t Size);
SafeReadIOCallback(EbmlBinary const &Binary);
~SafeReadIOCallback();
size_t GetPosition() const;
size_t GetSize() const;
size_t GetRemainingBytes() const;
bool IsEmpty() const;
uint8 GetUInt8();
uint64 GetUIntBE(size_t NumBytes);
uint16 GetUInt16BE();
uint32 GetUInt24BE();
uint32 GetUInt32BE();
uint64 GetUInt64BE();
void Read(void *Dst, size_t Count);
void Skip(size_t Count);
void Seek(size_t Position);
private:
SafeReadIOCallback(SafeReadIOCallback const &) { }
protected:
void Init(IOCallback *IO, bool DeleteIO);
};
END_LIBEBML_NAMESPACE
#endif // LIBEBML_SAFEREADIOCALLBACK_H

92
src/MemReadIOCallback.cpp Normal file
View File

@ -0,0 +1,92 @@
/****************************************************************************
** libebml : parse EBML files, see http://embl.sourceforge.net/
**
** <file/class description>
**
** Copyright (C) 2002-2014 Moritz Bunkus. All rights reserved.
**
** This file is part of libebml.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**
** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
**
** Contact license@matroska.org if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
/*!
\file
\version \$Id$
\author Moritz Bunkus <moritz@bunkus.org>
*/
#include <cstring>
#include "ebml/EbmlBinary.h"
#include "ebml/MemReadIOCallback.h"
START_LIBEBML_NAMESPACE
MemReadIOCallback::MemReadIOCallback(void const *Ptr,
size_t Size) {
Init(Ptr, Size);
}
MemReadIOCallback::MemReadIOCallback(EbmlBinary const &Binary) {
Init(Binary.GetBuffer(), Binary.GetSize());
}
MemReadIOCallback::MemReadIOCallback(MemReadIOCallback const &Mem) {
Init(Mem.mPtr, Mem.mEnd - Mem.mPtr);
}
MemReadIOCallback::~MemReadIOCallback() {
}
void
MemReadIOCallback::Init(void const *Ptr,
size_t Size) {
mStart = reinterpret_cast<uint8 const *>(Ptr);
mEnd = mStart + Size;
mPtr = mStart;
}
uint32
MemReadIOCallback::read(void *Buffer,
size_t Size) {
size_t RemainingBytes = mEnd - mPtr;
if (RemainingBytes < Size)
Size = RemainingBytes;
std::memcpy(Buffer, mPtr, Size);
mPtr += Size;
return Size;
}
void
MemReadIOCallback::setFilePointer(int64 Offset,
seek_mode Mode) {
int64 NewPosition = Mode == seek_beginning ? Offset
: Mode == seek_end ? static_cast<int64>(mEnd - mStart) + Offset
: static_cast<int64>(mPtr - mStart) + Offset;
NewPosition = std::min<int64>(std::max<int64>(NewPosition, 0), mEnd - mStart);
mPtr = mStart + NewPosition;
}
END_LIBEBML_NAMESPACE

174
src/SafeReadIOCallback.cpp Normal file
View File

@ -0,0 +1,174 @@
/****************************************************************************
** libebml : parse EBML files, see http://embl.sourceforge.net/
**
** <file/class description>
**
** Copyright (C) 2002-2014 Moritz Bunkus. All rights reserved.
**
** This file is part of libebml.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**
** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
**
** Contact license@matroska.org if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
/*!
\file
\version \$Id$
\author Moritz Bunkus <moritz@bunkus.org>
*/
#include <cstring>
#include "ebml/EbmlBinary.h"
#include "ebml/MemReadIOCallback.h"
#include "ebml/SafeReadIOCallback.h"
START_LIBEBML_NAMESPACE
SafeReadIOCallback::EndOfStreamX::EndOfStreamX(size_t MissingBytes)
: mMissingBytes(MissingBytes)
{
}
// ----------------------------------------------------------------------
SafeReadIOCallback::SafeReadIOCallback(IOCallback *IO,
bool DeleteIO) {
Init(IO, DeleteIO);
}
SafeReadIOCallback::SafeReadIOCallback(void const *Mem,
size_t Size) {
Init(new MemReadIOCallback(Mem, Size), true);
}
SafeReadIOCallback::SafeReadIOCallback(EbmlBinary const &Binary) {
Init(new MemReadIOCallback(Binary), true);
}
SafeReadIOCallback::~SafeReadIOCallback() {
if (mDeleteIO)
delete mIO;
}
void
SafeReadIOCallback::Init(IOCallback *IO,
bool DeleteIO) {
mIO = IO;
mDeleteIO = DeleteIO;
int64 PrevPosition = IO->getFilePointer();
IO->setFilePointer(0, seek_end);
mSize = IO->getFilePointer();
IO->setFilePointer(PrevPosition);
}
size_t
SafeReadIOCallback::GetPosition()
const {
return mIO->getFilePointer();
}
size_t
SafeReadIOCallback::GetSize()
const {
return mSize;
}
size_t
SafeReadIOCallback::GetRemainingBytes()
const {
return GetSize() - GetPosition();
}
bool
SafeReadIOCallback::IsEmpty()
const {
return !GetRemainingBytes();
}
uint64
SafeReadIOCallback::GetUIntBE(size_t NumBytes) {
uint8 Buffer[8];
NumBytes = std::min<size_t>(std::max<size_t>(1, NumBytes), 8);
uint64 Value = 0;
uint8* Ptr = &Buffer[0];
Read(Buffer, NumBytes);
for (size_t i = 0; NumBytes > i; ++i, ++Ptr)
Value = (Value << 8) + *Ptr;
return Value;
}
uint8
SafeReadIOCallback::GetUInt8() {
return GetUIntBE(1);
}
uint16
SafeReadIOCallback::GetUInt16BE() {
return GetUIntBE(2);
}
uint32
SafeReadIOCallback::GetUInt24BE() {
return GetUIntBE(3);
}
uint32
SafeReadIOCallback::GetUInt32BE() {
return GetUIntBE(4);
}
uint64
SafeReadIOCallback::GetUInt64BE() {
return GetUIntBE(8);
}
void
SafeReadIOCallback::Skip(size_t Count) {
int64 PrevPosition = mIO->getFilePointer();
int64 ExpectedPosition = PrevPosition + Count;
mIO->setFilePointer(Count, seek_current);
int64 ActualPosition = mIO->getFilePointer();
if (ActualPosition != ExpectedPosition)
throw SafeReadIOCallback::EndOfStreamX(ExpectedPosition - ActualPosition);
}
void
SafeReadIOCallback::Seek(size_t Offset) {
mIO->setFilePointer(Offset);
uint64 ActualPosition = mIO->getFilePointer();
if (ActualPosition != Offset)
throw EndOfStreamX(ActualPosition - Offset);
}
void
SafeReadIOCallback::Read(void *Dst,
size_t Count) {
uint64 NumRead = mIO->read(Dst, Count);
if (NumRead != Count)
throw SafeReadIOCallback::EndOfStreamX(Count - NumRead);
}
END_LIBEBML_NAMESPACE