encoding: Block::fromStream TLV-LENGTH bugfix
This commit fixes decoding errors when TLV-LENGTH is ASCII whitespace,
and when TLV-LENGTH is zero.
refs #2728 #2729
Change-Id: Ie1b3e9ee7068dd0a4f14fd51e97ceab1dd4d898b
diff --git a/src/encoding/block.cpp b/src/encoding/block.cpp
index 4353c96..e17fe9a 100644
--- a/src/encoding/block.cpp
+++ b/src/encoding/block.cpp
@@ -199,11 +199,15 @@
Block
Block::fromStream(std::istream& is)
{
- std::istream_iterator<uint8_t> tmp_begin(is);
- std::istream_iterator<uint8_t> tmp_end;
+ std::istream_iterator<uint8_t> begin(is >> std::noskipws);
+ std::istream_iterator<uint8_t> end;
- uint32_t type = tlv::readType(tmp_begin, tmp_end);
- uint64_t length = tlv::readVarNumber(tmp_begin, tmp_end);
+ uint32_t type = tlv::readType(begin, end);
+ uint64_t length = tlv::readVarNumber(begin, end);
+
+ if (length == 0) {
+ return dataBlock(type, static_cast<uint8_t*>(nullptr), length);
+ }
if (length > MAX_SIZE_OF_BLOCK_FROM_STREAM)
throw tlv::Error("Length of block from stream is too large");
@@ -212,8 +216,8 @@
// we may completely lose all the bytes extracted from the stream.
char buf[MAX_SIZE_OF_BLOCK_FROM_STREAM];
- buf[0] = *tmp_begin;
- is.read(buf+1, length-1);
+ buf[0] = *begin;
+ is.read(buf + 1, length - 1);
if (length != static_cast<uint64_t>(is.gcount()) + 1) {
throw tlv::Error("Not enough data in the buffer to fully parse TLV");
diff --git a/tests/unit-tests/encoding/block.t.cpp b/tests/unit-tests/encoding/block.t.cpp
index ac7ff51..62de9aa 100644
--- a/tests/unit-tests/encoding/block.t.cpp
+++ b/tests/unit-tests/encoding/block.t.cpp
@@ -272,7 +272,7 @@
BOOST_CHECK(!isOk);
}
-BOOST_AUTO_TEST_CASE(BlockFromStream)
+BOOST_AUTO_TEST_CASE(FromStream)
{
const uint8_t TEST_BUFFER[] = {0x00, 0x01, 0xfa, // ok
0x01, 0x01, 0xfb, // ok
@@ -300,6 +300,45 @@
BOOST_CHECK_THROW(Block::fromStream(stream), tlv::Error);
}
+BOOST_AUTO_TEST_CASE(FromStreamWhitespace) // Bug 2728
+{
+ uint8_t PACKET[] = {
+ 0x06, 0x20, // Data
+ 0x07, 0x11, // Name
+ 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // NameComponent 'hello'
+ 0x08, 0x01, 0x31, // NameComponent '1'
+ 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // NameComponent 'world'
+ 0x14, 0x00, // MetaInfo empty
+ 0x15, 0x00, // Content empty
+ 0x16, 0x05, // SignatureInfo
+ 0x1b, 0x01, 0x01, // SignatureType RSA
+ 0x1c, 0x00, // KeyLocator empty
+ 0x17, 0x00 // SignatureValue empty
+ };
+ // TLV-LENGTH of <Data> is 0x20 which happens to be ASCII whitespace
+
+ std::stringstream stream;
+ stream.write(reinterpret_cast<const char*>(PACKET), sizeof(PACKET));
+ stream.seekg(0);
+
+ Block block = Block::fromStream(stream);
+ BOOST_CHECK_NO_THROW(block.parse());
+}
+
+BOOST_AUTO_TEST_CASE(FromStreamZeroLength) // Bug 2729
+{
+ uint8_t BUFFER[] = { 0x07, 0x00 }; // TLV-LENGTH is zero
+
+ std::stringstream stream;
+ stream.write(reinterpret_cast<const char*>(BUFFER), sizeof(BUFFER));
+ stream.seekg(0);
+
+ Block block;
+ BOOST_CHECK_NO_THROW(block = Block::fromStream(stream));
+ BOOST_CHECK_EQUAL(block.type(), 0x07);
+ BOOST_CHECK_EQUAL(block.value_size(), 0);
+}
+
BOOST_AUTO_TEST_CASE(Equality)
{
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Block>));