Parse large floats as infinity

Signed-off-by: liubo <liubo1@xfusion.com>
(cherry picked from commit 55f74ba159d3255e4816e9a41fc2b4244c1b6bdf)
(cherry picked from commit fff476206668dd4fe5d343205b81a31ee3584af6)
This commit is contained in:
liubo 2023-10-18 11:27:37 +08:00 committed by openeuler-sync-bot
parent bc9783d535
commit fe21d770fb
2 changed files with 108 additions and 1 deletions

View File

@ -0,0 +1,102 @@
From 2d55c7445ffedf30db62231f223137ef02e611a9 Mon Sep 17 00:00:00 2001
From: Tero Kinnunen <tero.kinnunen@gmail.com>
Date: Wed, 15 Dec 2021 04:00:28 +0200
Subject: [PATCH] Parse large floats as infinity (#1349) (#1353)
Return 1.9.1 functionality where values too large to fit in
double are converted to positive or negative infinity.
Commit 645cd04 changed functionality so that large floats cause
parse error, while version 1.9.1 accepted them as infinite.
This is problematic because writer outputs infinity values
as `1e+9999`, which could no longer be parsed back.
Fixed also legacy Reader even though it did not parse large values
even before breaking change, due to problematic output/parse asymmetry.
`>>` operator sets value to numeric_limits::max/lowest value if
representation is too large to fit to double. [1][2] In macos
value appears to be parsed to infinity.
> | value in *val* | description |
> |--------------------------|-------------|
> | numeric_limits::max() | The sequence represents a value too large for the type of val |
> | numeric_limits::lowest() | The sequence represents a value too large negative for the type of val |
[1] https://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
[2] https://www.cplusplus.com/reference/locale/num_get/get/
Signed-off-by: Tero Kinnunen <tero.kinnunen@vaisala.com>
Co-authored-by: Tero Kinnunen <tero.kinnunen@vaisala.com>
---
src/lib_json/json_reader.cpp | 18 +++++++++++++++---
test/data/legacy_test_real_13.expected | 3 +++
test/data/legacy_test_real_13.json | 1 +
3 files changed, 19 insertions(+), 3 deletions(-)
create mode 100644 test/data/legacy_test_real_13.expected
create mode 100644 test/data/legacy_test_real_13.json
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index a6a3f4e..896bf1b 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -12,6 +12,7 @@
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert>
+#include <cmath>
#include <cstring>
#include <iostream>
#include <istream>
@@ -600,9 +601,15 @@ bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
String buffer(token.start_, token.end_);
IStringStream is(buffer);
- if (!(is >> value))
- return addError(
+ 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;
}
@@ -1647,7 +1654,12 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
const String buffer(token.start_, token.end_);
IStringStream is(buffer);
if (!(is >> value)) {
- return addError(
+ 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;
diff --git a/test/data/legacy_test_real_13.expected b/test/data/legacy_test_real_13.expected
new file mode 100644
index 0000000..8d3f03f
--- /dev/null
+++ b/test/data/legacy_test_real_13.expected
@@ -0,0 +1,3 @@
+.=[]
+.[0]=-inf
+.[1]=inf
diff --git a/test/data/legacy_test_real_13.json b/test/data/legacy_test_real_13.json
new file mode 100644
index 0000000..287258a
--- /dev/null
+++ b/test/data/legacy_test_real_13.json
@@ -0,0 +1 @@
+[-1e+9999, 1e+9999]
--
2.42.0.windows.2

View File

@ -1,12 +1,14 @@
Name: jsoncpp
Version: 1.9.5
Release: 3
Release: 4
Summary: JSON C++ library
License: Public Domain or MIT
URL: https://github.com/open-source-parsers/jsoncpp
Source0: https://github.com/open-source-parsers/jsoncpp/archive/%{version}/%{name}-%{version}.tar.gz
BuildRequires: gcc-c++ cmake >= 3.1 python3-devel
Patch0001: 0001-Parse-large-floats-as-infinity-1349-1353.patch
%description
JsonCpp is a C++ library that allows manipulating JSON values,
including serialization and deserialization to and from strings.
@ -91,6 +93,9 @@ hardlink -cfv %{buildroot}%{_docdir}/%{name}
%changelog
* Wed Oct 18 2023 liubo <liubo1@xfusion.com> - 1.9.5-4
- Parse large floats as infinity
* Mon Jan 10 2022 shixuantong <shixuantong@huawei.com> - 1.9.5-3
- Delete so files of lower versions