mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-05 09:46:53 +00:00
Compare commits
3 Commits
copilot/co
...
vlntb/malf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20766dc505 | ||
|
|
532cac0446 | ||
|
|
2f3558c610 |
13
.github/workflows/check-pr-description.yml
vendored
13
.github/workflows/check-pr-description.yml
vendored
@@ -5,8 +5,17 @@ on:
|
||||
types:
|
||||
- checks_requested
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize, ready_for_review]
|
||||
branches: [develop]
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
branches:
|
||||
- develop
|
||||
- "release-*"
|
||||
- "release/*"
|
||||
- "staging/*"
|
||||
|
||||
jobs:
|
||||
check_description:
|
||||
|
||||
13
.github/workflows/check-pr-title.yml
vendored
13
.github/workflows/check-pr-title.yml
vendored
@@ -5,8 +5,17 @@ on:
|
||||
types:
|
||||
- checks_requested
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize, ready_for_review]
|
||||
branches: [develop]
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
branches:
|
||||
- develop
|
||||
- "release-*"
|
||||
- "release/*"
|
||||
- "staging/*"
|
||||
|
||||
jobs:
|
||||
check_title:
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <cctype>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace beast::rfc2616 {
|
||||
@@ -182,7 +181,7 @@ splitCommas(FwdIt first, FwdIt last)
|
||||
|
||||
template <class Result = std::vector<std::string>>
|
||||
Result
|
||||
splitCommas(std::string_view const& s)
|
||||
splitCommas(boost::beast::string_view const& s)
|
||||
{
|
||||
return splitCommas(s.begin(), s.end());
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace json {
|
||||
|
||||
class Value;
|
||||
|
||||
using Output = std::function<void(std::string_view)>;
|
||||
using Output = std::function<void(boost::beast::string_view const&)>;
|
||||
|
||||
inline Output
|
||||
stringOutput(std::string& s)
|
||||
{
|
||||
return [&](std::string_view b) { s.append(b.data(), b.size()); };
|
||||
return [&](boost::beast::string_view const& b) { s.append(b.data(), b.size()); };
|
||||
}
|
||||
|
||||
/** Writes a minimal representation of a Json value to an Output in O(n) time.
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -50,7 +49,7 @@ private:
|
||||
bool pingActive_ = false;
|
||||
boost::beast::websocket::ping_data payload_;
|
||||
error_code ec_;
|
||||
std::function<void(boost::beast::websocket::frame_type, std::string_view)>
|
||||
std::function<void(boost::beast::websocket::frame_type, boost::beast::string_view)>
|
||||
controlCallback_;
|
||||
|
||||
public:
|
||||
@@ -139,7 +138,7 @@ protected:
|
||||
onPing(error_code const& ec);
|
||||
|
||||
void
|
||||
onPingPong(boost::beast::websocket::frame_type kind, std::string_view payload);
|
||||
onPingPong(boost::beast::websocket::frame_type kind, boost::beast::string_view payload);
|
||||
|
||||
void
|
||||
onTimer(error_code ec);
|
||||
@@ -420,11 +419,11 @@ template <class Handler, class Impl>
|
||||
void
|
||||
BaseWSPeer<Handler, Impl>::onPingPong(
|
||||
boost::beast::websocket::frame_type kind,
|
||||
std::string_view payload)
|
||||
boost::beast::string_view payload)
|
||||
{
|
||||
if (kind == boost::beast::websocket::frame_type::pong)
|
||||
{
|
||||
std::string_view const p(payload_.begin(), payload_.size());
|
||||
boost::beast::string_view const p(payload_.begin());
|
||||
if (payload == p)
|
||||
{
|
||||
closeOnTimer_ = false;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <set> // IWYU pragma: keep
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -88,14 +87,14 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
output(std::string_view bytes)
|
||||
output(boost::beast::string_view const& bytes)
|
||||
{
|
||||
markStarted();
|
||||
output_(bytes);
|
||||
}
|
||||
|
||||
void
|
||||
stringOutput(std::string_view bytes)
|
||||
stringOutput(boost::beast::string_view const& bytes)
|
||||
{
|
||||
markStarted();
|
||||
std::size_t position = 0, writtenUntil = 0;
|
||||
|
||||
@@ -19,6 +19,14 @@ namespace xrpl::permissioned_dex {
|
||||
bool
|
||||
accountInDomain(ReadView const& view, AccountID const& account, Domain const& domainID)
|
||||
{
|
||||
// A zero domainID is malformed: it would build a keylet with a zero key
|
||||
// and violate Ledger::read's invariant. Defense in depth: callers should
|
||||
// reject this at preflight, but guard here too so any future caller and
|
||||
// the order-book sweep path (offerInDomain -> here) cannot trip the
|
||||
// invariant.
|
||||
if (domainID.isZero())
|
||||
return false;
|
||||
|
||||
auto const sleDomain = view.read(keylet::permissionedDomain(domainID));
|
||||
if (!sleDomain)
|
||||
return false;
|
||||
|
||||
@@ -94,6 +94,16 @@ OfferCreate::preflight(PreflightContext const& ctx)
|
||||
if (tx.isFlag(tfHybrid) && !tx.isFieldPresent(sfDomainID))
|
||||
return temINVALID_FLAG;
|
||||
|
||||
// A present but zero DomainID is malformed: it would build a keylet with
|
||||
// a zero key and violate Ledger::read's invariant. Reject at preflight
|
||||
// (temMALFORMED) instead of letting it slip to preclaim and be
|
||||
// misclassified as tecNO_PERMISSION.
|
||||
if (tx.isFieldPresent(sfDomainID) && tx.getFieldH256(sfDomainID).isZero())
|
||||
{
|
||||
JLOG(j.debug()) << "Malformed offer: zero DomainID";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
bool const bImmediateOrCancel(tx.isFlag(tfImmediateOrCancel));
|
||||
bool const bFillOrKill(tx.isFlag(tfFillOrKill));
|
||||
|
||||
|
||||
@@ -125,6 +125,16 @@ Payment::preflight(PreflightContext const& ctx)
|
||||
if (!mpTokensV2 && isDstMPT && ctx.tx.isFieldPresent(sfPaths))
|
||||
return temMALFORMED;
|
||||
|
||||
// A present but zero DomainID is malformed: it would build a keylet with
|
||||
// a zero key and violate Ledger::read's invariant. Reject at preflight
|
||||
// (temMALFORMED) instead of letting it slip to preclaim and be
|
||||
// misclassified as tecNO_PERMISSION.
|
||||
if (tx.isFieldPresent(sfDomainID) && tx.getFieldH256(sfDomainID).isZero())
|
||||
{
|
||||
JLOG(j.debug()) << "Malformed payment: zero DomainID";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
bool const partialPaymentAllowed = tx.isFlag(tfPartialPayment);
|
||||
bool const limitQuality = tx.isFlag(tfLimitQuality);
|
||||
bool const defaultPathsAllowed = !tx.isFlag(tfNoRippleDirect);
|
||||
|
||||
@@ -278,6 +278,17 @@ class PermissionedDEX_test : public beast::unit_test::Suite
|
||||
env.close();
|
||||
}
|
||||
|
||||
// preflight - a present but zero DomainID is malformed.
|
||||
// Regression test for "Ledger::read : zero key" assertion.
|
||||
{
|
||||
Env env(*this, features);
|
||||
auto const& [gw_, domainOwner, alice_, bob_, carol_, USD, domainID, credType] =
|
||||
PermissionedDEX(env);
|
||||
|
||||
env(offer(bob_, XRP(10), USD(10)), Domain(uint256{}), Ter(temMALFORMED));
|
||||
env.close();
|
||||
}
|
||||
|
||||
// apply - offer can be created even if takergets issuer is not in
|
||||
// domain
|
||||
{
|
||||
@@ -413,6 +424,21 @@ class PermissionedDEX_test : public beast::unit_test::Suite
|
||||
env.close();
|
||||
}
|
||||
|
||||
// preflight - a present but zero DomainID is malformed.
|
||||
// Regression test for "Ledger::read : zero key" assertion.
|
||||
{
|
||||
Env env(*this, features);
|
||||
auto const& [gw_, domainOwner, alice_, bob_, carol_, USD, domainID, credType] =
|
||||
PermissionedDEX(env);
|
||||
|
||||
env(pay(bob_, alice_, USD(10)),
|
||||
Path(~USD),
|
||||
Sendmax(XRP(10)),
|
||||
Domain(uint256{}),
|
||||
Ter(temMALFORMED));
|
||||
env.close();
|
||||
}
|
||||
|
||||
// preclaim - payment with non-domain destination fails
|
||||
{
|
||||
Env env(*this, features);
|
||||
|
||||
@@ -64,7 +64,7 @@ to_string(ProtocolVersion const& p)
|
||||
}
|
||||
|
||||
std::vector<ProtocolVersion>
|
||||
parseProtocolVersions(std::string_view value)
|
||||
parseProtocolVersions(boost::beast::string_view const& value)
|
||||
{
|
||||
static boost::regex const kRE(
|
||||
"^" // start of line
|
||||
@@ -131,7 +131,7 @@ negotiateProtocolVersion(std::vector<ProtocolVersion> const& versions)
|
||||
}
|
||||
|
||||
std::optional<ProtocolVersion>
|
||||
negotiateProtocolVersion(std::string_view versions)
|
||||
negotiateProtocolVersion(boost::beast::string_view const& versions)
|
||||
{
|
||||
auto const them = parseProtocolVersions(versions);
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -38,7 +39,7 @@ to_string(ProtocolVersion const& p);
|
||||
no duplicates and will be sorted in ascending protocol order.
|
||||
*/
|
||||
std::vector<ProtocolVersion>
|
||||
parseProtocolVersions(std::string_view s);
|
||||
parseProtocolVersions(boost::beast::string_view const& s);
|
||||
|
||||
/** Given a list of supported protocol versions, choose the one we prefer. */
|
||||
std::optional<ProtocolVersion>
|
||||
@@ -46,7 +47,7 @@ negotiateProtocolVersion(std::vector<ProtocolVersion> const& versions);
|
||||
|
||||
/** Given a list of supported protocol versions, choose the one we prefer. */
|
||||
std::optional<ProtocolVersion>
|
||||
negotiateProtocolVersion(std::string_view versions);
|
||||
negotiateProtocolVersion(boost::beast::string_view const& versions);
|
||||
|
||||
/** The list of all the protocol versions we support. */
|
||||
std::string const&
|
||||
|
||||
@@ -264,7 +264,7 @@ ServerHandler::onHandoff(
|
||||
static inline json::Output
|
||||
makeOutput(Session& session)
|
||||
{
|
||||
return [&](std::string_view b) { session.write(b.data(), b.size()); };
|
||||
return [&](boost::beast::string_view const& b) { session.write(b.data(), b.size()); };
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string>
|
||||
@@ -564,14 +564,11 @@ ServerHandler::processSession(
|
||||
makeOutput(*session),
|
||||
coro,
|
||||
forwardedFor(session->request()),
|
||||
[&]() -> std::string_view {
|
||||
[&] {
|
||||
auto const iter = session->request().find("X-User");
|
||||
if (iter != session->request().end())
|
||||
{
|
||||
auto const& val = iter->value();
|
||||
return std::string_view(val.data(), val.size());
|
||||
}
|
||||
return std::string_view{};
|
||||
return iter->value();
|
||||
return boost::beast::string_view{};
|
||||
}());
|
||||
|
||||
if (beast::rfc2616::isKeepAlive(session->request()))
|
||||
|
||||
Reference in New Issue
Block a user