Skip to content

Exception thrown in noexcept code #673

@kone-tlammi

Description

@kone-tlammi

The below code is somewhat malformed, as DefaultIfMissing's default value does not match what the validator expects. In these cases, IMO, it is fine to throw an exception. The library seems wrap potentially throwing code in a noexcept function.

Code to reproduce the issue:

#include <rfl.hpp>
#include <rfl/json.hpp>

using namespace std::literals;

constexpr auto data = R"({"str": "asdfasdf"})"sv;

using Str = rfl::Validator<std::string, rfl::Size<rfl::Minimum<1>>,
                           rfl::Size<rfl::Maximum<100>>>;
struct Sample {
    Str str;
};

int main() {
    try {
        auto res = rfl::json::read<Sample, rfl::DefaultIfMissing>(data);
    } catch (const std::exception& e) {
        std::cerr << "ERROR: " << e.what() << '\n';
    }
}

Output:

terminate called after throwing an instance of 'std::runtime_error'
  what():  Size validation failed: Value expected to be greater than or equal to 1, but got 0.
Aborted (core dumped)

The fix seems quite trivial:

diff --git a/include/rfl/AllOf.hpp b/include/rfl/AllOf.hpp
index ca25c88..b158e30 100644
--- a/include/rfl/AllOf.hpp
+++ b/include/rfl/AllOf.hpp
@@ -15,7 +15,7 @@ struct AllOf {
   /// @param _value The value to validate
   /// @return The value if all constraints pass, otherwise an error
   template <class T>
-  static rfl::Result<T> validate(T _value) noexcept {
+  static rfl::Result<T> validate(T _value) {
     return validate_impl<T, C, Cs...>(_value);
   }

@@ -31,7 +31,7 @@ struct AllOf {

  private:
   template <class T, class Head, class... Tail>
-  static rfl::Result<T> validate_impl(T _value) noexcept {
+  static rfl::Result<T> validate_impl(T _value) {
     if constexpr (sizeof...(Tail) == 0) {
       return Head::validate(_value);
     } else {
diff --git a/include/rfl/parsing/Parser_default.hpp b/include/rfl/parsing/Parser_default.hpp
index b7de7f7..725cff7 100644
--- a/include/rfl/parsing/Parser_default.hpp
+++ b/include/rfl/parsing/Parser_default.hpp
@@ -51,7 +51,7 @@ struct Parser {
    * @param _var The input variable to read from.
    * @return A Result containing the parsed value or an error.
    */
-  static Result<T> read(const R& _r, const InputVarType& _var) noexcept {
+  static Result<T> read(const R& _r, const InputVarType& _var) {
     if constexpr (internal::has_read_reflector<T>) {
       const auto wrap_in_t = [](auto&& _named_tuple) -> Result<T> {
         try {

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions