Large floats not accepted anymore
Describe the bug
Version 1.9.2 no longer accepts 1+e9999 (or 2e+308 and anything above), regardless of allowSpecialFloats setting.
To Reproduce Steps to reproduce the behavior:
#include <iostream>
#include <json/json.h>
#include <sstream>
int main(int argc, const char* argv[])
{
Json::CharReaderBuilder reader;
reader["allowSpecialFloats"] = true; // Makes no difference
std::string s = "1e+9999";
Json::Value val;
std::string errors;
std::stringstream json(s);
if (Json::parseFromStream(reader, json, &val, &errors)) {
std::cout << s << " -> " << val.asDouble() << "\n";
} else {
std::cout << errors;
}
return 0;
}
Expected behavior
1e+9999 -> inf
Actual behavior:
* Line 1, Column 1
'1e+9999' is not a number.
Desktop (please complete the following information):
- OS: Fedora 34
- Meson version 0.59.1
- Ninja version 1.10.2
Additional context
- Version 1.9.1 accepts value
1e+9999as infinite, regardless ofallowSpecialFloatssetting. - Version 1.9.2 no longer accepts
2e+308or above, regardless ofallowSpecialFloatssetting.
Specifically breaking change seems to be commit 645cd0412c "Number fixes (#1053)".
Sorry, I don't like to change/break old behavior. This was our mistake.
But now, I wonder whether we can recover the old behavior without reverting that large PR. Somehow, we need big numbers to map to inf. However, did the old behavior map even bigger, really huge numbers to inf also? If not, would it be ok if it did?
In that case, there is probably a relatively simply way to use inf for all large numbers. Could you submit a PR for that? Otherwise, I'm not sure when we would find time for this.
I'll give it a try to fix.
Not fixed by 1.9.6
In the following code , for a token of 1e+9999 (written by jsoncpp itself), (is >> value) will let value equal to 0 and will ultimately fall in the error case
bool OurReader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
IStringStream is(String(token.start_, token.end_));
if (!(is >> value)) {
if (value == std::numeric_limits<double>::max())
value = std::numeric_limits<double>::infinity();
else if (value == std::numeric_limits<double>::lowest())
value = -std::numeric_limits<double>::infinity();
else if (!std::isinf(value))
return addError(
"'" + String(token.start_, token.end_) + "' is not a number.", token);
}
decoded = value;
return true;
}