mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Detect malformed data earlier during deserialization (RIPD-1695):
When deserializing specially crafted data, the code would ignore certain types of errors. Reserializing objects created from such data results in failures or generates a different serialization, which is not ideal. Also addresses: RIPD-1677, RIPD-1682, RIPD-1686 and RIPD-1689. Acknowledgements: Ripple thanks Guido Vranken for responsibly disclosing these issues. Bug Bounties and Responsible Disclosures: We welcome reviews of the rippled code and urge researchers to responsibly disclose any issues that they may find. For more on Ripple's Bug Bounty program, please visit: https://ripple.com/bug-bounty
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <test/jtx.h>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
@@ -631,6 +632,75 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testMalformed()
|
||||
{
|
||||
testcase ("Malformed serialized forms");
|
||||
|
||||
try
|
||||
{
|
||||
std::array<std::uint8_t, 5> const payload {{ 0xee, 0xee, 0xe1, 0xee, 0xee }};
|
||||
SerialIter sit{makeSlice(payload)};
|
||||
auto obj = std::make_shared<STArray>(sit, sfMetadata);
|
||||
BEAST_EXPECT(!obj);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
BEAST_EXPECT(strcmp(e.what(),
|
||||
"Duplicate field detected") == 0);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::array<std::uint8_t, 3> const payload {{ 0xe2, 0xe1, 0xe2 }};
|
||||
SerialIter sit{makeSlice(payload)};
|
||||
auto obj = std::make_shared<STObject>(sit, sfMetadata);
|
||||
BEAST_EXPECT(!obj);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
BEAST_EXPECT(strcmp(e.what(),
|
||||
"Duplicate field detected") == 0);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::array<std::uint8_t, 250> const payload
|
||||
{{
|
||||
0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x4f,
|
||||
0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00, 0x81, 0x14,
|
||||
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x24, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65,
|
||||
0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20,
|
||||
0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35,
|
||||
0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x1e, 0x00, 0x4f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00,
|
||||
0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x24, 0x59, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x54, 0x72, 0x61, 0x6e, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5,
|
||||
0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e,
|
||||
0x00, 0x6f, 0x00, 0x00, 0x20, 0xf6, 0x00, 0x00, 0x03, 0x1f, 0x20, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00,
|
||||
0x81, 0x14, 0x00, 0x10, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00,
|
||||
0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe
|
||||
}};
|
||||
|
||||
SerialIter sit{makeSlice(payload)};
|
||||
auto obj = std::make_shared<STTx>(sit);
|
||||
BEAST_EXPECT(!obj);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
BEAST_EXPECT(strcmp(e.what(),
|
||||
"Duplicate field detected") == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
@@ -642,6 +712,7 @@ public:
|
||||
testParseJSONArray();
|
||||
testParseJSONArrayWithInvalidChildrenObjects();
|
||||
testParseJSONEdgeCases();
|
||||
testMalformed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -35,8 +35,7 @@ class STTx_test : public beast::unit_test::suite
|
||||
public:
|
||||
void run() override
|
||||
{
|
||||
testcase ("overly nested transactions");
|
||||
testDeepNesting();
|
||||
testMalformedSerializedForm();
|
||||
|
||||
testcase ("secp256k1 signatures");
|
||||
testSTTx (KeyType::secp256k1);
|
||||
@@ -48,8 +47,10 @@ public:
|
||||
testObjectCtorErrors();
|
||||
}
|
||||
|
||||
void testDeepNesting()
|
||||
void testMalformedSerializedForm()
|
||||
{
|
||||
testcase ("Malformed serialized form");
|
||||
|
||||
constexpr unsigned char payload1[] =
|
||||
{
|
||||
0x0a, 0xff, 0xff, 0xff, 0xff, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
@@ -1217,6 +1218,31 @@ public:
|
||||
0x12, 0x12, 0x12, 0xff
|
||||
};
|
||||
|
||||
constexpr unsigned char dupField[] =
|
||||
{
|
||||
0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x4f,
|
||||
0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00, 0x81, 0x14,
|
||||
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x24, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65,
|
||||
0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20,
|
||||
0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35,
|
||||
0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x1e, 0x00, 0x4f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00,
|
||||
0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x24, 0x59, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x54, 0x72, 0x61, 0x6e, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5,
|
||||
0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e,
|
||||
0x00, 0x6f, 0x00, 0x00, 0x20, 0xf6, 0x00, 0x00, 0x03, 0x1f, 0x20, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00,
|
||||
0x81, 0x14, 0x00, 0x10, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00,
|
||||
0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
protocol::TMTransaction tx2;
|
||||
@@ -1229,7 +1255,8 @@ public:
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
BEAST_EXPECT(strcmp(e.what(), "Maximum nesting depth of STVar exceeded") == 0);
|
||||
BEAST_EXPECT(strcmp(e.what(),
|
||||
"Maximum nesting depth of STVar exceeded") == 0);
|
||||
}
|
||||
|
||||
try
|
||||
@@ -1240,7 +1267,20 @@ public:
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
BEAST_EXPECT(strcmp(e.what(), "Maximum nesting depth of STVar exceeded") == 0);
|
||||
BEAST_EXPECT(strcmp(e.what(),
|
||||
"Maximum nesting depth of STVar exceeded") == 0);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ripple::SerialIter sit (Slice{dupField, sizeof(dupField)});
|
||||
auto stx = std::make_shared<ripple::STTx const>(sit);
|
||||
fail("An exception should have been thrown");
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
BEAST_EXPECT(strcmp(e.what(),
|
||||
"Duplicate field detected") == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user