Compare commits

...

18 Commits

Author SHA1 Message Date
Moritz Bunkus
41ffa10123 README: provide basic instructions for building & installing
Fixes #12.
2016-07-15 14:45:33 +02:00
Moritz Bunkus
e89b8b47bc fix Free Software Foundation's address
Fixes #15.
2016-07-15 14:05:39 +02:00
Moritz Bunkus
c39aa8d542 Bump version number, add release message 2016-07-02 15:48:51 +02:00
Moritz Bunkus
1c93d143cf EbmlVersion.cpp: always set EbmlCodeDate to "Unknown"
This is done in order to enable deterministic builds while still keeping
the library API and ABI compatible. Patch by Ed Schouten <ed@nuxi.nl>.
2015-11-21 10:54:41 +01:00
Moritz Bunkus
81e7ffd512 ChangeLog: update for recent commits 2015-11-18 18:37:46 +01:00
Moritz Bunkus
07d3436342 libebml_t.h: use C99 integer typedefs instead of the BSD ones
Patch by Ed Schouten <ed@nuxi.nl>.
2015-11-18 18:35:22 +01:00
Moritz Bunkus
bb8ad783b5 Merge pull request #13 from 0-wiz-0/master
Add cstdlib for free/malloc.
2015-10-25 10:57:28 +01:00
Thomas Klausner
a02741ef1d Add cstdlib for free/malloc.
Needed when compiling with clang/libc++.
2015-10-25 10:46:29 +01:00
Moritz Bunkus
580add661f Bump version number, add release message 2015-10-20 15:05:13 +02:00
Moritz Bunkus
88409e2a94 EbmlMaster: propagate upper level element after infinite sized one correctly
When the parser encountered a deeply nested element with an infinite
size then a following element of an upper level was not propagated
correctly. Instead the element with the infinite size was added into the
EBML element tree a second time resulting in memory access after freeing
it and multiple attempts to free the same memory address during
destruction.

Fixes the issue reported as Cisco TALOS-CAN-0037.
2015-10-20 14:54:55 +02:00
Moritz Bunkus
24e5cd7c66 EbmlElement: don't read beyond end of buffer when reading variable length integers 2015-10-20 14:54:55 +02:00
Moritz Bunkus
12b560adc2 EbmlMaster.cpp: unwrap huge if; fix indentation 2015-10-20 14:54:55 +02:00
Moritz Bunkus
ababb64e0c EbmlUnicodeString: don't read beyond end of string
The conversion from an UTF-8 encoded string into a wchar_t one was
reading from beyond the end of the source buffer if the length indicated
by a UTF-8 character's first byte exceeds the number of bytes actually
present afterwards.

Fixes the issue reported as Cisco TALOS-CAN-0036.
2015-10-20 14:54:55 +02:00
Moritz Bunkus
c161e600b3 Bump version number, add release message 2015-10-17 15:47:22 +02:00
Moritz Bunkus
04b34b0dbd Merge pull request #11 from Matroska-Org/eof-in-sizes
detect EOF when reading the element size
2015-08-21 21:01:15 +02:00
Moritz Bunkus
267b24fb9e Merge pull request #9 from Matroska-Org/winstore
code for Windows App Store do not have access to the ANSI calls used in Debug.cpp
2015-08-21 21:00:44 +02:00
Steve Lhomme
642c3c4e27 detect EOF when reading the element size, similar to when reading the element id 2015-08-21 15:42:12 +02:00
Steve Lhomme
a858efec74 code for Windows App Store do not have access to the ANSI calls used in Debug.cpp
so we disable debug for these targets
2015-06-15 09:45:17 +02:00
15 changed files with 283 additions and 140 deletions

View File

@ -1,3 +1,76 @@
2016-07-15 Moritz Bunkus <moritz@bunkus.org>
* Replaced the outdated address of the Free Software Foundation
with their current one. Fixes #15.
2016-07-02 Moritz Bunkus <moritz@bunkus.org>
* Released v1.3.4.
2015-11-21 Moritz Bunkus <moritz@bunkus.org>
* EbmlVersion.cpp: in order to enable deterministic builds the
EbmlCodeDate variable has been set to "Unknown" instead of the
date and time of compilation. Patch by Ed Schouten <ed@nuxi.nl>.
2015-11-18 Moritz Bunkus <moritz@bunkus.org>
* libebml_t.h: use C99-style integer typedefs instead of BSD-style
ones. Patch by Ed Schouten <ed@nuxi.nl>.
2015-10-24 Moritz Bunkus <moritz@bunkus.org>
* EbmlBinary.h: add #include <cstdlib> for compilation with clang
and libc++. Patch by Thomas Klausner <wiz@NetBSD.org>.
2015-10-20 Moritz Bunkus <moritz@bunkus.org>
* Released v1.3.3.
* EbmlMaster::Read(): When the parser encountered a deeply nested
element with an infinite size then a following element of an upper
level was not propagated correctly. Instead the element with the
infinite size was added into the EBML element tree a second time
resulting in memory access after freeing it and multiple attempts
to free the same memory address during destruction. Fixes the
issue reported as Cisco TALOS-CAN-0037.
* EbmlElement::ReadCodedSizeValue(): Fixed an invalid memory
access. When reading a EBML variable length integer value a read
access beyond the end of the available buffer was possible if
fewer bytes were available than indicated by the first byte
resulting in a heap information leak.
* EbmlUnicodeString::UpdateFromUTF8(): Fixed an invalid memory
access. When reading from a UTF-8 string in which the length
indicated by a UTF-8 character's first byte exceeds the string's
actual number of bytes the parser would access beyond the end of
the string resulting in a heap information leak. Fixes the issue
reported as Cisco TALOS-CAN-0036.
2015-10-17 Moritz Bunkus <moritz@bunkus.org>
* Released v1.3.2.
2015-08-21 Steve Lhomme <robUx4@gmail.com>
* EbmlElement::FindNextElement(): Handle EOF when reading the
element size properly.
2015-06-15 Steve Lhomme <robUx4@gmail.com
* Disable debug code for builds for the Windows App Store.
2015-06-12 Cristian Morales Vega <reddwarf@opensuse.org>
* Update the license information: use latest official text for the
LGPL.
2015-02-23 Steve Lhomme <robux4@gmail.com>
* EbmlString::ValidateSize(): only allow the same maximum size as
EbmlBinary.
2015-01-04 Moritz Bunkus <moritz@bunkus.org>
* Released v1.3.1.

View File

@ -2,3 +2,27 @@
a C++ libary to parse EBML files
Specifications may be rendered at http://matroska-org.github.io/libebml/
# Building and installing
## Building a released version
libebml is based on autoconf and automake and requires only a C++
compiler. This means that the normal build process consists of the
usual three steps:
1. Configuration: `./configure`
2. Building: `make`
3. Installation (run this as root): `make install`
## Building from git
If you're building from git you must have the GNU autotools
(`autoconf`, `automake`, `libtoolize`) installed. Then run the
following two commands:
1. `libtoolize`
2. `autoreconf -vi`
Afterwards continue with the steps listed for building a released
version.

View File

@ -1,4 +1,4 @@
AC_INIT([libebml], [1.3.1])
AC_INIT([libebml], [1.3.4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
@ -10,4 +10,5 @@ AC_ARG_ENABLE([debug],
[enable_debug="$withval"], [enable_debug=no])
AM_CONDITIONAL([ENABLE_DEBUG], [test "$enable_debug" = yes])
AC_CONFIG_FILES([Makefile libebml.pc])
AC_CHECK_HEADERS([winapifamily.h])
AC_OUTPUT

View File

@ -37,6 +37,7 @@
#ifndef LIBEBML_BINARY_H
#define LIBEBML_BINARY_H
#include <cstdlib>
#include <cstring>
#include "EbmlTypes.h"

View File

@ -36,6 +36,10 @@
#ifndef LIBEBML_CONFIG_H
#define LIBEBML_CONFIG_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(__linux__)
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
@ -100,9 +104,11 @@
#define LIBEBML_DEBUG
#endif
// For compilers that don't define __TIMESTAMP__ (e.g. gcc 2.95, gcc 3.2)
#ifndef __TIMESTAMP__
#define __TIMESTAMP__ __DATE__ " " __TIME__
#ifdef HAVE_WINAPIFAMILY_H
# include <winapifamily.h>
# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# undef LIBEBML_DEBUG
# endif
#endif
#ifdef __GNUC__

View File

@ -42,7 +42,7 @@
START_LIBEBML_NAMESPACE
#define LIBEBML_VERSION 0x010301
#define LIBEBML_VERSION 0x010304
extern const std::string EbmlCodeVersion;
extern const std::string EbmlCodeDate;

View File

@ -17,7 +17,7 @@
**
** 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
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
**

View File

@ -19,7 +19,7 @@
**
** 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
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
**

View File

@ -108,10 +108,10 @@ extern "C" {
typedef int16_t int16;
typedef int8_t int8;
typedef int8_t character;
typedef u_int64_t uint64;
typedef u_int32_t uint32;
typedef u_int16_t uint16;
typedef u_int8_t uint8;
typedef uint64_t uint64;
typedef uint32_t uint32;
typedef uint16_t uint16;
typedef uint8_t uint8;
#endif /* anything else */
typedef uint8 binary;

View File

@ -150,6 +150,11 @@ uint64 ReadCodedSizeValue(const binary * InBuffer, uint32 & BufferSize, uint64 &
// ID found
PossibleSizeLength = SizeIdx + 1;
SizeBitMask >>= SizeIdx;
// Guard against invalid memory accesses with incomplete IDs.
if (PossibleSizeLength > BufferSize)
break;
for (SizeIdx = 0; SizeIdx < PossibleSizeLength; SizeIdx++) {
PossibleSize[SizeIdx] = InBuffer[SizeIdx];
}
@ -417,7 +422,10 @@ EbmlElement * EbmlElement::FindNextElement(IOCallback & DataStream, const EbmlSe
bFound = false;
break;
}
ReadSize += DataStream.read(&PossibleIdNSize[SizeIdx++], 1);
if( DataStream.read( &PossibleIdNSize[SizeIdx++], 1 ) == 0 ) {
return NULL; // no more data ?
}
ReadSize++;
PossibleSizeLength++;
}

View File

@ -398,107 +398,118 @@ void EbmlMaster::Sort()
*/
void EbmlMaster::Read(EbmlStream & inDataStream, const EbmlSemanticContext & sContext, int & UpperEltFound, EbmlElement * & FoundElt, bool AllowDummyElt, ScopeMode ReadFully)
{
if (ReadFully != SCOPE_NO_DATA)
{
EbmlElement * ElementLevelA;
// remove all existing elements, including the mandatory ones...
size_t Index;
for (Index=0; Index<ElementList.size(); Index++) {
if (!(*ElementList[Index]).IsLocked()) {
delete ElementList[Index];
}
if (ReadFully == SCOPE_NO_DATA)
return;
EbmlElement * ElementLevelA;
// remove all existing elements, including the mandatory ones...
size_t Index;
for (Index=0; Index<ElementList.size(); Index++) {
if (!(*ElementList[Index]).IsLocked()) {
delete ElementList[Index];
}
ElementList.clear();
uint64 MaxSizeToRead;
if (IsFiniteSize())
MaxSizeToRead = GetSize();
else
MaxSizeToRead = 0x7FFFFFFF;
// read blocks and discard the ones we don't care about
if (MaxSizeToRead > 0)
{
inDataStream.I_O().setFilePointer(GetSizePosition() + GetSizeLength(), seek_beginning);
ElementLevelA = inDataStream.FindNextElement(sContext, UpperEltFound, MaxSizeToRead, AllowDummyElt);
while (ElementLevelA != NULL && UpperEltFound <= 0 && MaxSizeToRead > 0) {
if (IsFiniteSize() && ElementLevelA->IsFiniteSize())
MaxSizeToRead = GetEndPosition() - ElementLevelA->GetEndPosition(); // even if it's the default value
if (!AllowDummyElt && ElementLevelA->IsDummy()) {
if (ElementLevelA->IsFiniteSize()) {
ElementLevelA->SkipData(inDataStream, sContext);
delete ElementLevelA; // forget this unknown element
} else {
delete ElementLevelA; // forget this unknown element
break;
}
} else {
ElementLevelA->Read(inDataStream, EBML_CONTEXT(ElementLevelA), UpperEltFound, FoundElt, AllowDummyElt, ReadFully);
// Discard elements that couldn't be read properly if
// SCOPE_ALL_DATA has been requested. This can happen
// e.g. if block data is defective.
bool DeleteElement = true;
if (ElementLevelA->ValueIsSet() || (ReadFully != SCOPE_ALL_DATA)) {
ElementList.push_back(ElementLevelA);
DeleteElement = false;
}
// just in case
if (ElementLevelA->IsFiniteSize()) {
ElementLevelA->SkipData(inDataStream, EBML_CONTEXT(ElementLevelA));
if (DeleteElement)
delete ElementLevelA;
} else {
if (DeleteElement)
delete ElementLevelA;
break;
}
}
if (UpperEltFound > 0) {
UpperEltFound--;
if (UpperEltFound > 0 || MaxSizeToRead <= 0)
goto processCrc;
ElementLevelA = FoundElt;
continue;
}
if (UpperEltFound < 0) {
UpperEltFound++;
if (UpperEltFound < 0)
goto processCrc;
}
if (MaxSizeToRead <= 0)
goto processCrc;// this level is finished
ElementLevelA = inDataStream.FindNextElement(sContext, UpperEltFound, MaxSizeToRead, AllowDummyElt);
}
if (UpperEltFound > 0) {
FoundElt = ElementLevelA;
}
}
processCrc:
EBML_MASTER_ITERATOR Itr, CrcItr;
for (Itr = ElementList.begin(); Itr != ElementList.end();) {
if ((EbmlId)(*(*Itr)) == EBML_ID(EbmlCrc32)) {
bChecksumUsed = true;
// remove the element
Checksum = *(static_cast<EbmlCrc32*>(*Itr));
CrcItr = Itr;
break;
}
++Itr;
}
if (bChecksumUsed)
{
delete *CrcItr;
Remove(CrcItr);
}
SetValueIsSet();
}
ElementList.clear();
uint64 MaxSizeToRead;
if (IsFiniteSize())
MaxSizeToRead = GetSize();
else
MaxSizeToRead = 0x7FFFFFFF;
// read blocks and discard the ones we don't care about
if (MaxSizeToRead > 0)
{
inDataStream.I_O().setFilePointer(GetSizePosition() + GetSizeLength(), seek_beginning);
ElementLevelA = inDataStream.FindNextElement(sContext, UpperEltFound, MaxSizeToRead, AllowDummyElt);
while (ElementLevelA != NULL && UpperEltFound <= 0 && MaxSizeToRead > 0) {
if (IsFiniteSize() && ElementLevelA->IsFiniteSize())
MaxSizeToRead = GetEndPosition() - ElementLevelA->GetEndPosition(); // even if it's the default value
if (!AllowDummyElt && ElementLevelA->IsDummy()) {
if (ElementLevelA->IsFiniteSize()) {
ElementLevelA->SkipData(inDataStream, sContext);
delete ElementLevelA; // forget this unknown element
} else {
delete ElementLevelA; // forget this unknown element
break;
}
} else {
ElementLevelA->Read(inDataStream, EBML_CONTEXT(ElementLevelA), UpperEltFound, FoundElt, AllowDummyElt, ReadFully);
// Discard elements that couldn't be read properly if
// SCOPE_ALL_DATA has been requested. This can happen
// e.g. if block data is defective.
bool DeleteElement = true;
if (ElementLevelA->ValueIsSet() || (ReadFully != SCOPE_ALL_DATA)) {
ElementList.push_back(ElementLevelA);
DeleteElement = false;
}
// just in case
if (ElementLevelA->IsFiniteSize()) {
ElementLevelA->SkipData(inDataStream, EBML_CONTEXT(ElementLevelA));
if (DeleteElement)
delete ElementLevelA;
} else {
if (DeleteElement)
delete ElementLevelA;
if (UpperEltFound) {
--UpperEltFound;
if (UpperEltFound > 0 || MaxSizeToRead <= 0)
goto processCrc;
ElementLevelA = FoundElt;
}
break;
}
}
if (UpperEltFound > 0) {
UpperEltFound--;
if (UpperEltFound > 0 || MaxSizeToRead <= 0)
goto processCrc;
ElementLevelA = FoundElt;
continue;
}
if (UpperEltFound < 0) {
UpperEltFound++;
if (UpperEltFound < 0)
goto processCrc;
}
if (MaxSizeToRead <= 0)
goto processCrc;// this level is finished
ElementLevelA = inDataStream.FindNextElement(sContext, UpperEltFound, MaxSizeToRead, AllowDummyElt);
}
if (UpperEltFound > 0) {
FoundElt = ElementLevelA;
}
}
processCrc:
EBML_MASTER_ITERATOR Itr, CrcItr;
for (Itr = ElementList.begin(); Itr != ElementList.end();) {
if ((EbmlId)(*(*Itr)) == EBML_ID(EbmlCrc32)) {
bChecksumUsed = true;
// remove the element
Checksum = *(static_cast<EbmlCrc32*>(*Itr));
CrcItr = Itr;
break;
}
++Itr;
}
if (bChecksumUsed)
{
delete *CrcItr;
Remove(CrcItr);
}
SetValueIsSet();
}
void EbmlMaster::Remove(size_t Index)

View File

@ -47,6 +47,21 @@ START_LIBEBML_NAMESPACE
// ===================== UTFstring class ===================
static unsigned int UTFCharLength(uint8 lead)
{
if (lead < 0x80)
return 1;
else if ((lead >> 5) == 0x6)
return 2;
else if ((lead >> 4) == 0xe)
return 3;
else if ((lead >> 3) == 0x1e)
return 4;
else
// Invalid size?
return 0;
}
UTFstring::UTFstring()
:_Length(0)
,_Data(NULL)
@ -143,39 +158,39 @@ void UTFstring::UpdateFromUTF8()
delete [] _Data;
// find the size of the final UCS-2 string
size_t i;
for (_Length=0, i=0; i<UTF8string.length(); _Length++) {
uint8 lead = static_cast<uint8>(UTF8string[i]);
if (lead < 0x80)
i++;
else if ((lead >> 5) == 0x6)
i += 2;
else if ((lead >> 4) == 0xe)
i += 3;
else if ((lead >> 3) == 0x1e)
i += 4;
const size_t SrcLength = UTF8string.length();
for (_Length=0, i=0; i<SrcLength; _Length++) {
const unsigned int CharLength = UTFCharLength(static_cast<uint8>(UTF8string[i]));
if ((CharLength >= 1) && (CharLength <= 4))
i += CharLength;
else
// Invalid size?
break;
}
_Data = new wchar_t[_Length+1];
size_t j;
for (j=0, i=0; i<UTF8string.length(); j++) {
uint8 lead = static_cast<uint8>(UTF8string[i]);
if (lead < 0x80) {
_Data[j] = lead;
i++;
} else if ((lead >> 5) == 0x6) {
_Data[j] = ((lead & 0x1F) << 6) + (UTF8string[i+1] & 0x3F);
i += 2;
} else if ((lead >> 4) == 0xe) {
_Data[j] = ((lead & 0x0F) << 12) + ((UTF8string[i+1] & 0x3F) << 6) + (UTF8string[i+2] & 0x3F);
i += 3;
} else if ((lead >> 3) == 0x1e) {
_Data[j] = ((lead & 0x07) << 18) + ((UTF8string[i+1] & 0x3F) << 12) + ((UTF8string[i+2] & 0x3F) << 6) + (UTF8string[i+3] & 0x3F);
i += 4;
} else
for (j=0, i=0; i<SrcLength; j++) {
const uint8 lead = static_cast<uint8>(UTF8string[i]);
const unsigned int CharLength = UTFCharLength(lead);
if ((CharLength < 1) || (CharLength > 4))
// Invalid char?
break;
if ((i + CharLength) > SrcLength)
// Guard against invalid memory access beyond the end of the
// source buffer.
break;
if (CharLength == 1)
_Data[j] = lead;
else if (CharLength == 2)
_Data[j] = ((lead & 0x1F) << 6) + (UTF8string[i+1] & 0x3F);
else if (CharLength == 3)
_Data[j] = ((lead & 0x0F) << 12) + ((UTF8string[i+1] & 0x3F) << 6) + (UTF8string[i+2] & 0x3F);
else if (CharLength == 4)
_Data[j] = ((lead & 0x07) << 18) + ((UTF8string[i+1] & 0x3F) << 12) + ((UTF8string[i+2] & 0x3F) << 6) + (UTF8string[i+3] & 0x3F);
i += CharLength;
}
_Data[j] = 0;
}

View File

@ -38,7 +38,11 @@
START_LIBEBML_NAMESPACE
const std::string EbmlCodeVersion = "1.3.1";
const std::string EbmlCodeDate = __TIMESTAMP__;
const std::string EbmlCodeVersion = "1.3.4";
// Up to version 1.3.3 this library exported a build date string. As
// this made the build non-reproducible, replace it by a placeholder to
// remain API compatible.
const std::string EbmlCodeDate = "Unknown";
END_LIBEBML_NAMESPACE

View File

@ -19,7 +19,7 @@
**
** 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
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
**

View File

@ -19,7 +19,7 @@
**
** 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
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
**