-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Silently get numbers into smaller types #288
Comments
If you are grabbing smaller widths then you must know that the numbers will be small. |
@whackashoe yes, but the same rule can be apply to get number from a string, nevertheless we have an exception in that case. And, in most cases, json comes from untrusted sources, so we should check all the values from it. For numbers it can be: json j = { { "foo", 65536 } };
json v = j["foo"];
if (!v.is_number_integer())
throw;
int64_t a = v;
if ((a < std::numeric_limits<int16_t>::min()) || (a > std::numeric_limits<int16_t>::max()))
throw;
int16_t b = static_cast<int16_t>(a); |
If the data you are getting is untrusted, then you must pepper with checks anyways. May as well just read it into the largest width size number you have then check if you can cast downwards from there. Something expected to be a number but is actually "0234hnnnng111111" is I guess exceptional - it isn't a number at all- whereas rest of C++ historically thinks overflow isn't exceptional. I don't understand why you'd cast untrusted data to small size and assume a library will throw an exception if that doesn't fit. Imo would be smarter to make a nice wrapper like you have and keep that for untrusted data casts but it doesn't need to be in the main lib itself- could be a nice addition to a supplementary/utils addon tho! |
@whackashoe I understood the idea. Maybe my experience with another libs, with separate methods ( |
It's just my opinion on it, very subjective 👯 |
RFC 7159, Section 6 states:
and
That said, JSON does not require a library to support a specific range for numbers, but proposes to use doubles for floating-point numbers and some type that is able to cope with integers in the range [-(2^53)+1, (2^53)-1]. The library follows this proposal closely, as documented for integers, unsigned integers, and floating-point numbers. Casting a JSON value number to a type that can only cover a subrange is dangerous, and preventing harm is out of scope of a JSON library. It would also contradict the “not pay for what you don't use” approach of C++. If you need to find the smallest integer type for the number stored in the JSON value, you should implement your own conversion function. By the way, instead of writing int16_t v = j["foo"].get<int16_t>(); you can also write int16_t v = j["foo"]; |
@nlohmann so there is no difference between
and
right ? And if we have to always test if number (from untrusted sources) is not float, than get them into in64_t, check their range, and cast to smaller type, probably it can be subject to have an additional method for strict cast? (and still have non strict conversion to follow “not pay for what you don't use” principle). For example, well known c++ json libraries https://github.com/open-source-parsers/jsoncpp and https://github.com/miloyip/rapidjson do size checking. |
Yes, these lines are equivalent, because Numbers are parsed such that the "best" fitting type is used in the following order
If casting to double would result in NaN, a If you use the types above, you pay nothing, because no range check is necessary and no cast is executed. If you are not sure about the number type, the functions If you need to cast from a JSON number to a smaller range, you need to write a conversion function that detects overflow. With templates and |
This code:
prints
Probably, it would be better, if
get
thrown some exception (maybestd::out_of_range
).The text was updated successfully, but these errors were encountered: