Any integer value is accepted to deserialize enums which is imo a risky default behavior since it means enum values absolutely need to be checked after deserialization by reflect-cpp.
Reproduction of the behavior:
// Minimal repro: reflect-cpp accepts an out-of-range enum value when it is
// supplied as a numeric string during the default (name-based) deserialization.
//
// Root cause: rfl::string_to_enum (include/rfl/enums.hpp) falls back to
// static_cast<EnumType>(std::stoi(name))
// whenever the string is not a known enumerator name but IS parseable as an
// integer, with no check that the result is a defined enumerator.
#include <iostream>
#include <rfl.hpp>
#include <rfl/json.hpp>
enum class Color { red, green, blue }; // valid underlying values: 0, 1, 2
struct Config {
Color color;
};
static void try_read(const char* json) {
const auto res = rfl::json::read<Config>(json);
if (res) {
std::cout << " " << json << " -> ACCEPTED, color = "
<< static_cast<int>(res->color)
<< (static_cast<int>(res->color) > 2 ? " <-- OUT OF RANGE, no error!" : "")
<< "\n";
} else {
std::cout << " " << json << " -> rejected: " << res.error().what() << "\n";
}
}
int main() {
try_read(R"({"color":"green"})"); // valid name -> accepted (1)
try_read(R"({"color":"purple"})"); // invalid name -> rejected (correct)
try_read(R"({"color":"5"})"); // numeric string, OOR -> WRONGLY accepted (5)
try_read(R"({"color":"-1"})"); // numeric string, OOR -> WRONGLY accepted (-1)
return 0;
}
Outputs:
{"color":"green"} -> ACCEPTED, color = 1
{"color":"purple"} -> rejected: Failed to parse field 'color': stoi
{"color":"5"} -> ACCEPTED, color = 5 <-- OUT OF RANGE, no error!
{"color":"-1"} -> ACCEPTED, color = -1
I think ideally, the default behavior should change to not allow number or at least not out of range numbers.
If this can't be done because it would be a breaking change, a preprocessor would be a nice addition.
Any integer value is accepted to deserialize enums which is imo a risky default behavior since it means enum values absolutely need to be checked after deserialization by reflect-cpp.
Reproduction of the behavior:
Outputs:
I think ideally, the default behavior should change to not allow number or at least not out of range numbers.
If this can't be done because it would be a breaking change, a preprocessor would be a nice addition.