jsoncpp icon indicating copy to clipboard operation
jsoncpp copied to clipboard

Large floats not accepted anymore

Open terokinnunen opened this issue 4 years ago • 3 comments

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+9999 as infinite, regardless of allowSpecialFloats setting.
  • Version 1.9.2 no longer accepts 2e+308 or above, regardless of allowSpecialFloats setting.

Specifically breaking change seems to be commit 645cd0412c "Number fixes (#1053)".

terokinnunen avatar Oct 28 '21 08:10 terokinnunen

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.

cdunn2001 avatar Nov 03 '21 15:11 cdunn2001

I'll give it a try to fix.

terokinnunen avatar Nov 05 '21 22:11 terokinnunen

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;
}

chacha21 avatar Nov 12 '24 13:11 chacha21