Current test case for an observed earth-shattering kaboom

wirehair_decode() will sometimes seg fault if you give it the same frame
too many times. This is probably not intended behavior?

For now, a workaround (keep track of what we've given it)
This commit is contained in:
sz 2020-06-15 20:26:01 -05:00
parent 9cd315c54b
commit 75e88a6d72
3 changed files with 49 additions and 8 deletions

View File

@ -4,6 +4,7 @@
#include "wirehair/wirehair.h"
#include <array>
#include <optional>
#include <set>
#include <vector>
#include <iostream>
@ -46,6 +47,10 @@ public:
std::optional<std::vector<uint8_t>> decode(unsigned block_num, uint8_t* data, size_t length)
{
auto pear = _seenBlocks.insert(block_num);
if (!pear.second)
return std::nullopt;
_res = wirehair_decode(_codec, block_num, data, length);
if (_res != Wirehair_Success)
return std::nullopt;
@ -64,4 +69,5 @@ protected:
WirehairCodec _codec;
WirehairResult _res;
size_t _length;
std::set<unsigned> _seenBlocks; // giving wirehair_decode the same block too many times can make it very, very upset
};

View File

@ -92,14 +92,10 @@ TEST_CASE( "FountainSinkTest/testMultipart", "[unit]" )
stringstream input = dummyContents(20000);
fountain_encoder_stream fes = fountain_encoder_stream<626>::create(input);
string expectedName = "pog.py";
std::array<uint8_t,10> nameBuff = {0};
std::copy(expectedName.begin(), expectedName.end(), nameBuff.data());
expectedName = string(nameBuff.begin(), nameBuff.end());
string expectedName = "testMultip";
for (int i = 0; i < 4; ++i)
{
string iframe = createFrame(fes, "pog.py");
string iframe = createFrame(fes, "testMultipart");
assertEquals( 6900, iframe.size() );
FountainMetadata md(iframe.data(), iframe.size());
@ -116,3 +112,35 @@ TEST_CASE( "FountainSinkTest/testMultipart", "[unit]" )
string contents = File("/tmp/testMultip").read_all();
assertEquals( 20000, contents.size() );
}
TEST_CASE( "FountainSinkTest/testSameFrameManyTimes", "[unit]" )
{
// this is the current test case for what is either a wirehair bug or "undefined behavior"
// tl;dr -- if you give it the same frame (under certain circumstances), you get a seg fault
FountainInit::init();
fountain_decoder_sink<626> sink("/tmp");
stringstream input = dummyContents(20000);
fountain_encoder_stream fes = fountain_encoder_stream<626>::create(input);
string expectedName = "pog.py";
std::array<uint8_t,10> nameBuff = {0};
std::copy(expectedName.begin(), expectedName.end(), nameBuff.data());
expectedName = string(nameBuff.begin(), nameBuff.end());
string iframe = createFrame(fes, "pog.py");
assertEquals( 6900, iframe.size() );
FountainMetadata md(iframe.data(), iframe.size());
assertEquals( 20000, md.file_size() );
assertEquals( expectedName, md.name() );
// don't crash!
for (int i = 0; i < 40; ++i)
assertFalse( sink.decode_frame(iframe.data(), iframe.size()) );
assertEquals( 1, sink.num_streams() );
assertEquals( 0, sink.num_done() );
}

View File

@ -143,12 +143,15 @@ TEST_CASE( "FountainStreamTest/testDecode", "[unit]" )
assertMsg((bool)output, "couldn't decode :(");
}
assertEquals( 827, fds.block_size() );
assertEquals( 10000, fds.data_size() );
assertTrue( fds.good() );
assertEquals( 15, fes.block_count() );
assertEquals( 13, fes.blocks_required() );
assertTrue( fes.good() );
}
TEST_CASE( "FountainStreamTest/testDecode_BigPackets", "[unit]" )
{
FountainInit::init();
@ -182,9 +185,13 @@ TEST_CASE( "FountainStreamTest/testDecode_BigPackets", "[unit]" )
assertMsg((bool)output, "couldn't decode :(");
}
assertEquals( 827, fds.block_size() );
assertEquals( 10000, fds.data_size() );
assertTrue( fds.good() );
assertEquals( 14, fes.block_count() );
assertEquals( 13, fes.blocks_required() );
assertTrue( fes.good() );
}