mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-21 22:30:57 +00:00
fix: Reject oversized validator manifest before decoding
This commit is contained in:
@@ -41,6 +41,35 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
namespace base64 {
|
||||
|
||||
/**
|
||||
* Returns the maximum number of characters needed to base64-encode @p nBytes bytes.
|
||||
*
|
||||
* @param nBytes Number of input bytes.
|
||||
* @return Size of the encoded string, including padding.
|
||||
*/
|
||||
constexpr std::size_t
|
||||
encodedSize(std::size_t const nBytes)
|
||||
{
|
||||
return 4 * ((nBytes + 2) / 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of bytes a base64 string of @p nChars characters
|
||||
* decodes to.
|
||||
*
|
||||
* @param nChars Number of base64 characters.
|
||||
* @return Upper bound on the number of decoded bytes.
|
||||
*/
|
||||
constexpr std::size_t
|
||||
decodedSize(std::size_t const nChars)
|
||||
{
|
||||
return ((nChars / 4) * 3) + 2;
|
||||
}
|
||||
|
||||
} // namespace base64
|
||||
|
||||
std::string
|
||||
base64Encode(std::uint8_t const* data, std::size_t len);
|
||||
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/UnorderedContainers.h>
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
#include <xrpl/protocol/SecretKey.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -164,6 +166,37 @@ struct Manifest
|
||||
std::string
|
||||
to_string(Manifest const& m);
|
||||
|
||||
/**
|
||||
*Largest a valid manifest can be, in decoded bytes.
|
||||
*
|
||||
* A manifest has a fixed set of fields. Each is serialized as a field header
|
||||
* (1-2 bytes), an optional length prefix (1 byte for these sizes), and the
|
||||
* field body. Taking every field at its largest gives the maximum below, so
|
||||
* anything larger cannot be a valid manifest.
|
||||
*
|
||||
* Field header + length + body = bytes
|
||||
* sfVersion (U16) 2 0 2 4
|
||||
* sfSequence (U32) 1 0 4 5
|
||||
* sfPublicKey (33) 1 1 33 35
|
||||
* sfSigningPubKey (33) 1 1 33 35
|
||||
* sfSignature (72) 1 1 72 74
|
||||
* sfMasterSignature (72) 2 1 72 75
|
||||
* sfDomain (128) 1 1 128 130
|
||||
* -----
|
||||
* 358
|
||||
*/
|
||||
constexpr std::size_t kMaxManifestBytes = 358;
|
||||
|
||||
/**
|
||||
* Largest a valid manifest can be, in base64 characters.
|
||||
*
|
||||
* base64 encodes 3 bytes as 4 characters, so this is the encoded form of
|
||||
* @ref kMaxManifestBytes. Callers that receive a base64 manifest should
|
||||
* reject anything longer than this before decoding, to avoid allocating
|
||||
* memory for an oversized input.
|
||||
*/
|
||||
constexpr std::size_t kMaxManifestBase64 = base64::encodedSize(kMaxManifestBytes);
|
||||
|
||||
/**
|
||||
* Constructs Manifest from serialized string
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user