Commit 93f4d05d authored by Wez Furlong's avatar Wez Furlong Committed by Facebook Github Bot

fixup decode logic for fragmented IOBufs

Summary:
D6635325 exposed a long standing issue with the way
that we were consuming Cursor::length, so let's fix it up!

More details are in the new unit test for this!

Reviewed By: spalamarchuk

Differential Revision: D6755842

fbshipit-source-id: f8b20406c32682892791e7375be577d54d52e0ad
parent 6374f552
...@@ -61,7 +61,10 @@ static std::string decodeString(Cursor& curs) { ...@@ -61,7 +61,10 @@ static std::string decodeString(Cursor& curs) {
} }
str.reserve(size_t(len)); str.reserve(size_t(len));
size_t available = curs.length(); // peekBytes will advance over any "empty" IOBuf elements until
// it reaches the next one with data, so do that to obtain the
// true remaining length.
size_t available = curs.peekBytes().size();
while (available < (size_t)len) { while (available < (size_t)len) {
if (available == 0) { if (available == 0) {
// Saw this case when we decodeHeader was returning the incorrect length // Saw this case when we decodeHeader was returning the incorrect length
...@@ -74,7 +77,7 @@ static std::string decodeString(Cursor& curs) { ...@@ -74,7 +77,7 @@ static std::string decodeString(Cursor& curs) {
str.append(reinterpret_cast<const char*>(curs.data()), available); str.append(reinterpret_cast<const char*>(curs.data()), available);
curs.skipAtMost(available); curs.skipAtMost(available);
len -= available; len -= available;
available = curs.length(); available = curs.peekBytes().size();
} }
str.append(reinterpret_cast<const char*>(curs.data()), size_t(len)); str.append(reinterpret_cast<const char*>(curs.data()), size_t(len));
......
...@@ -118,5 +118,32 @@ TEST(Bser, PduLength) { ...@@ -118,5 +118,32 @@ TEST(Bser, PduLength) {
EXPECT_EQ(len, 44) << "PduLength should be 44, got " << len; EXPECT_EQ(len, 44) << "PduLength should be 44, got " << len;
} }
TEST(Bser, CursorLength) {
folly::bser::serialization_opts opts;
std::string inputStr("hello there please break");
// This test is exercising the decode logic for pathological
// fragmentation cases. We try a few permutations with the
// BSER header being fragmented to tickle boundary conditions
auto longSerialized = folly::bser::toBser(inputStr, opts);
for (uint32_t i = 1; i < longSerialized.size(); ++i) {
folly::IOBufQueue q;
q.append(folly::IOBuf::wrapBuffer(longSerialized.data(), i));
uint32_t j = i;
while (j < longSerialized.size()) {
q.append(folly::IOBuf::wrapBuffer(&longSerialized[j], 1));
++j;
}
auto pdu_len = folly::bser::decodePduLength(q.front());
auto buf = q.split(pdu_len);
auto hello = folly::bser::parseBser(buf.get());
EXPECT_EQ(inputStr, hello.asString());
}
}
/* vim:ts=2:sw=2:et: /* vim:ts=2:sw=2:et:
*/ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment