fix: Expected to return a value: (#4401)

Fix a case where `ripple::Expected` returned a json array, not a value.

The problem was that `Expected` invoked the wrong constructor for the
expected type, which resulted in a constructor that took multiple
arguments being interpreted as an array.

A proposed fix was provided by @godexsoft, which involved a minor
adjustment to three constructors that replaces the use of curly braces
with parentheses. This makes `Expected` usable for
[Clio](https://github.com/XRPLF/clio).

A unit test is also included to ensure that the issue doesn't occur
again in the future.
This commit is contained in:
Scott Schurr
2023-03-23 17:32:17 -07:00
committed by GitHub
parent d7725837f5
commit dffcdea12b
2 changed files with 16 additions and 3 deletions

View File

@@ -137,14 +137,14 @@ class [[nodiscard]] Expected
public:
template <typename U>
requires std::convertible_to<U, T> constexpr Expected(U && r)
: Base(T{std::forward<U>(r)})
: Base(T(std::forward<U>(r)))
{
}
template <typename U>
requires std::convertible_to<U, E> &&
(!std::is_reference_v<U>)constexpr Expected(Unexpected<U> e)
: Base(E{std::move(e.value())})
: Base(E(std::move(e.value())))
{
}
@@ -220,7 +220,7 @@ public:
template <typename U>
requires std::convertible_to<U, E> &&
(!std::is_reference_v<U>)constexpr Expected(Unexpected<U> e)
: Base(E{std::move(e.value())})
: Base(E(std::move(e.value())))
{
}

View File

@@ -20,6 +20,9 @@
#include <ripple/basics/Expected.h>
#include <ripple/beast/unit_test.h>
#include <ripple/protocol/TER.h>
#if BOOST_VERSION >= 107500
#include <boost/json.hpp> // Not part of boost before version 1.75
#endif // BOOST_VERSION
#include <array>
#include <cstdint>
@@ -203,6 +206,16 @@ struct Expected_test : beast::unit_test::suite
std::string const s(std::move(expected.error()));
BEAST_EXPECT(s == "Not what is expected!");
}
// Test a case that previously unintentionally returned an array.
#if BOOST_VERSION >= 107500
{
auto expected = []() -> Expected<boost::json::value, std::string> {
return boost::json::object{{"oops", "me array now"}};
}();
BEAST_EXPECT(expected);
BEAST_EXPECT(!expected.value().is_array());
}
#endif // BOOST_VERSION
}
};