From 11c29f74c94871fc0136306d663622eb69da3dfe Mon Sep 17 00:00:00 2001 From: Nigel Stewart Date: Sat, 11 Dec 2021 08:31:15 +1000 Subject: [PATCH] BitpackIntegerDecoder sometimes reads past end of input buffer (#87) --- src/Decoder.cpp | 22 ++++++++++++++-------- src/Decoder.h | 1 + 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Decoder.cpp b/src/Decoder.cpp index 7824f60..c8bdb3a 100644 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -731,7 +731,19 @@ size_t BitpackIntegerDecoder::inputProcessAligned( const char *inbuf, #endif RegisterT w; - if ( bitOffset > 0 ) + if ( bitOffset == 0 ) + { + /// The left shift (used below) is not defined if shift is >= size of + /// word + w = low; + } + // Avoid reading the next word, unless it is needed + // If the last record finishes on the last bit of input, avoid UMR + else if ( bitOffset + bitsPerRecord_ <= RegisterBits ) + { + w = low >> bitOffset; + } + else { /// Get upper word (may or may not contain interesting bits), RegisterT high = inp[wordPosition + 1]; @@ -743,13 +755,7 @@ size_t BitpackIntegerDecoder::inputProcessAligned( const char *inbuf, /// Shift high to just above the lower bits, shift low LSBit to bit0, /// OR together. Note shifts are logical (not arithmetic) because using /// unsigned variables. - w = ( high << ( 8 * sizeof( RegisterT ) - bitOffset ) ) | ( low >> bitOffset ); - } - else - { - /// The left shift (used above) is not defined if shift is >= size of - /// word - w = low; + w = ( high << ( RegisterBits - bitOffset ) ) | ( low >> bitOffset ); } #ifdef E57_MAX_VERBOSE diff --git a/src/Decoder.h b/src/Decoder.h index 7d9496c..f602f54 100644 --- a/src/Decoder.h +++ b/src/Decoder.h @@ -149,6 +149,7 @@ namespace e57 double offset_; unsigned bitsPerRecord_; RegisterT destBitMask_; + static constexpr size_t RegisterBits = sizeof( RegisterT ) * 8; }; class ConstantIntegerDecoder : public Decoder