1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 14:53:21 +02:00

Fixed broken bitstream parsing

+ refactoring
This commit is contained in:
Martin Tůma 2021-11-09 23:11:45 +01:00
parent 9bfc7e8b89
commit de028cd2d4
3 changed files with 37 additions and 41 deletions

View File

@ -41,16 +41,15 @@ bool BitStream4F::flush()
return true; return true;
} }
bool BitStream4F::read(int bits, quint32 &val) bool BitStream4F::read(quint32 bits, quint32 &val)
{ {
if (bits <= 32 - (int)(_used + _unused)) { if (bits <= 32 - (_used + _unused)) {
val = bits ? (_data << _used) >> (32 - bits) : 0; val = bits ? (_data << _used) >> (32 - bits) : 0;
_used += bits; _used += bits;
return true; return true;
} }
if (_unused) Q_ASSERT(_length && !_unused);
return false;
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0; quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
quint32 bytes = qMin(_length, 4U); quint32 bytes = qMin(_length, 4U);
@ -73,7 +72,7 @@ BitStream4R::BitStream4R(const SubFile &file, SubFile::Handle &hdl,
_file.seek(_hdl, _file.pos(_hdl) - 4); _file.seek(_hdl, _file.pos(_hdl) - 4);
} }
bool BitStream4R::readBytes(int bytes, quint32 &val) bool BitStream4R::readBytes(quint32 bytes, quint32 &val)
{ {
quint32 bits = _used % 8; quint32 bits = _used % 8;
quint32 b; quint32 b;
@ -85,7 +84,7 @@ bool BitStream4R::readBytes(int bytes, quint32 &val)
} }
val = 0; val = 0;
for (int i = 0; i < bytes; i++) { for (quint32 i = 0; i < bytes; i++) {
if (!read(8, b)) if (!read(8, b))
return false; return false;
val |= (b << (i * 8)); val |= (b << (i * 8));

View File

@ -10,7 +10,7 @@ public:
BitStream1(const SubFile &file, SubFile::Handle &hdl, quint32 length) BitStream1(const SubFile &file, SubFile::Handle &hdl, quint32 length)
: _file(file), _hdl(hdl), _length(length), _remaining(0) {} : _file(file), _hdl(hdl), _length(length), _remaining(0) {}
template<typename T> bool read(int bits, T &val); template<typename T> bool read(quint32 bits, T &val);
bool flush(); bool flush();
quint64 bitsAvailable() const {return (quint64)_length * 8 + _remaining;} quint64 bitsAvailable() const {return (quint64)_length * 8 + _remaining;}
@ -44,7 +44,7 @@ public:
BitStream4F(const SubFile &file, SubFile::Handle &hdl, quint32 length) BitStream4F(const SubFile &file, SubFile::Handle &hdl, quint32 length)
: BitStream4(file, hdl, length) {} : BitStream4(file, hdl, length) {}
bool read(int bits, quint32 &val); bool read(quint32 bits, quint32 &val);
bool flush(); bool flush();
}; };
@ -60,8 +60,8 @@ public:
BitStream4R(const SubFile &file, SubFile::Handle &hdl, quint32 length); BitStream4R(const SubFile &file, SubFile::Handle &hdl, quint32 length);
template<typename T> bool read(int bits, T &val); template<typename T> bool read(quint32 bits, T &val);
bool readBytes(int bytes, quint32 &val); bool readBytes(quint32 bytes, quint32 &val);
bool readVUInt32(quint32 &val); bool readVUInt32(quint32 &val);
bool readVuint32SM(quint32 &val1, quint32 &val2, quint32 &val2Bits); bool readVuint32SM(quint32 &val1, quint32 &val2, quint32 &val2Bits);
@ -73,11 +73,11 @@ public:
template<typename T> template<typename T>
bool BitStream1::read(int bits, T &val) bool BitStream1::read(quint32 bits, T &val)
{ {
val = 0; val = 0;
for (int pos = 0; pos < bits; ) { for (quint32 pos = 0; pos < bits; ) {
if (!_remaining) { if (!_remaining) {
if (!_length || !_file.readByte(_hdl, &_data)) if (!_length || !_file.readByte(_hdl, &_data))
return false; return false;
@ -103,16 +103,15 @@ bool BitStream1::read(int bits, T &val)
} }
template<typename T> template<typename T>
bool BitStream4R::read(int bits, T &val) bool BitStream4R::read(quint32 bits, T &val)
{ {
if (bits <= 32 - (int)(_used + _unused)) { if (bits <= 32 - (_used + _unused)) {
val = bits ? (_data << _used) >> (32 - bits) : 0; val = bits ? (_data << _used) >> (32 - bits) : 0;
_used += bits; _used += bits;
return true; return true;
} }
if (_unused) Q_ASSERT(_length && !_unused);
return false;
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0; quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
quint32 bytes = qMin(_length, 4U); quint32 bytes = qMin(_length, 4U);

View File

@ -12,7 +12,7 @@ public:
HuffmanStream(BitStream &bitstream, const HuffmanTable &table) HuffmanStream(BitStream &bitstream, const HuffmanTable &table)
: _symbolDataSize(0), _symbolData(0), _bs(bitstream), _table(table) {} : _symbolDataSize(0), _symbolData(0), _bs(bitstream), _table(table) {}
bool read(int bits, quint32 &val); bool read(quint32 bits, quint32 &val);
bool readSymbol(quint32 &symbol); bool readSymbol(quint32 &symbol);
bool atEnd() const bool atEnd() const
@ -24,29 +24,35 @@ protected:
quint32 _symbolData; quint32 _symbolData;
private: private:
bool fetchData();
BitStream &_bs; BitStream &_bs;
const HuffmanTable &_table; const HuffmanTable &_table;
}; };
template <class BitStream> template <class BitStream>
bool HuffmanStream<BitStream>::read(int bits, quint32 &val) bool HuffmanStream<BitStream>::fetchData()
{ {
if (_symbolDataSize < (quint32)bits) { quint32 next;
quint32 next; quint8 nextSize = qMin((quint64)(32 - _symbolDataSize), _bs.bitsAvailable());
quint8 nextSize = qMin((quint64)(32 - _symbolDataSize),
_bs.bitsAvailable());
if (!_bs.read(nextSize, next)) if (!_bs.read(nextSize, next))
return false;
_symbolData = (nextSize < 32) ? (_symbolData << nextSize) | next : next;
_symbolDataSize += nextSize;
return true;
}
template <class BitStream>
bool HuffmanStream<BitStream>::read(quint32 bits, quint32 &val)
{
if (_symbolDataSize < bits)
if (!fetchData() || _symbolDataSize < bits)
return false; return false;
_symbolData = (_symbolData << nextSize) | next; val = (_symbolData << (32 - _symbolDataSize)) >> (32 - bits);
_symbolDataSize += nextSize;
if (_symbolDataSize < (quint32)bits)
return false;
}
val = (_symbolData << (32-_symbolDataSize)) >> (32 - bits);
_symbolDataSize -= bits; _symbolDataSize -= bits;
return true; return true;
@ -57,18 +63,10 @@ bool HuffmanStream<BitStream>::readSymbol(quint32 &symbol)
{ {
quint8 size; quint8 size;
if (_symbolDataSize < _table.symBits()) { if (_symbolDataSize < _table.symBits())
quint32 next; if (!fetchData() || !_symbolDataSize)
quint8 nextSize = qMin((quint64)(32 - _symbolDataSize),
_bs.bitsAvailable());
if (!_bs.read(nextSize, next))
return false; return false;
_symbolData = (_symbolData << nextSize) | next;
_symbolDataSize += nextSize;
}
symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size); symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size);
if (size > _symbolDataSize) if (size > _symbolDataSize)
return false; return false;