-
Notifications
You must be signed in to change notification settings - Fork 160
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
fix uint_parser<T(signed)> overflow problem #297
fix uint_parser<T(signed)> overflow problem #297
Conversation
According to spirit document, "All numeric parsers check for overflow conditions based on the type T the corresponding uint_parser<> has been instantiated with. If the parsed number overflows this type the parsing fails. Please be aware that the overflow check is not based on the type of the supplied attribute but solely depends on the template parameter T." the valid input range of x3::uint_parser<T> should be 0 - std::numeric_limits<T>::max(). However, the current implementation takes values from std::numeric_limits<T>::max()+1 - std::numeric_limits<std::make_unsigned_t<T>>::max() also as valid input.
Is this for X3 or Qi? Or it seems both? |
Now for both. |
Great! |
looks good to me. |
@Kojoley Thanks! |
Thanks for the patch @wanghan02! |
@djowel I'm not positive I've just bumped into this, or a similar, kerfuffle as well in Qi. Base 10 parses negative values just fine, but has difficulty dealing with negative base 16 (hex) and base 8 (octal) integers. See example code for illustration. |
The problem in your example has nothing with the PR (it was about spirit/include/boost/spirit/home/qi/numeric/numeric_utils.hpp Lines 120 to 124 in 35c6a9a
Here is how I would done it (for two's complement; if I was needed to): template <typename T>
bool parse_int_hex(..., T& out)
{
make_unsigned_t<T> value;
if (!parse(..., value)) return false;
constexpr auto max_positive = static_cast<make_unsigned_t<T>>(std::numeric_limits<T>::max());
if (value > max_positive)
out = static_cast<T>(value - max_positive) + std::numeric_limits<T>::min() - 1;
else
out = static_cast<T>(value);
return true;
} |
@Kojoley Good to know, thank you for clarifying that. Apologies for the detour. |
@Kojoley So, just to clarify, while I can
It's a bit of work, but it is more consistent with the language specification I am dealing with at the moment. Would also need to be cautious of corner cases like "negative max-int", whose edge case could really only support no more than "negative (max-int + 1)", I think. Along these lines. Could be a corner case unless I can specify the maximum value of the "positive" side. Okay, well, enough of this tangent... Thanks again! |
According to spirit document,
"All numeric parsers check for overflow conditions based on the type T the corresponding uint_parser<> has been instantiated with. If the parsed number overflows this type the parsing fails. Please be aware that the overflow check is not based on the type of the supplied attribute but solely depends on the template parameter T."
the valid input range of
x3::uint_parser<T>
should be0
-std::numeric_limits<T>::max()
. However, the current implementation takes values fromstd::numeric_limits<T>::max()+1
-std::numeric_limits<std::make_unsigned_t<T>>::max()
also as valid input whenT
is a signed integral.Example:
x3::uint_parser<signed char>
should parse 0-127, but with current implementation 128-255 also works.Test cases are added.