Skip to content

Commit 4e9b4f6

Browse files
committed
Return 0 if binary exponent is too small
1 parent f5e5d47 commit 4e9b4f6

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

include/rapidjson/internal/diyfp.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// Tencent is pleased to support the open source community by making RapidJSON available.
2-
//
2+
//
33
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
44
//
55
// Licensed under the MIT License (the "License"); you may not use this file except
66
// in compliance with the License. You may obtain a copy of the License at
77
//
88
// http://opensource.org/licenses/MIT
99
//
10-
// Unless required by applicable law or agreed to in writing, software distributed
11-
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12-
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
// Unless required by applicable law or agreed to in writing, software distributed
11+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
1313
// specific language governing permissions and limitations under the License.
1414

1515
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
@@ -56,7 +56,7 @@ struct DiyFp {
5656
if (biased_e != 0) {
5757
f = significand + kDpHiddenBit;
5858
e = biased_e - kDpExponentBias;
59-
}
59+
}
6060
else {
6161
f = significand;
6262
e = kDpMinExponent + 1;
@@ -142,9 +142,12 @@ struct DiyFp {
142142
uint64_t u64;
143143
}u;
144144
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
145-
RAPIDJSON_ASSERT(e >= kDpDenormalExponent);
145+
if (e < kDpDenormalExponent) {
146+
// Underflow.
147+
return 0.0;
148+
}
146149
RAPIDJSON_ASSERT(e < kDpMaxExponent);
147-
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
150+
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
148151
static_cast<uint64_t>(e + kDpExponentBias);
149152
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
150153
return u.d;
@@ -226,7 +229,7 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
226229
RAPIDJSON_ASSERT(index < 87);
227230
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
228231
}
229-
232+
230233
inline DiyFp GetCachedPower(int e, int* K) {
231234

232235
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;

test/unittest/readertest.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,15 @@ static void TestParseDouble() {
392392
"83723677529752585477247372368372368547354737253685475529752",
393393
6223372036854775808.0);
394394

395+
396+
TEST_DOUBLE(fullPrecision, "1e-325", 0.0);
397+
TEST_DOUBLE(fullPrecision, "1e-324", 0.0);
398+
TEST_DOUBLE(fullPrecision, "2e-324", 0.0);
399+
TEST_DOUBLE(fullPrecision, "2.4703282292062327e-324", 0.0);
400+
TEST_DOUBLE(fullPrecision, "2.4703282292062328e-324", 2.4703282292062328e-324);
401+
TEST_DOUBLE(fullPrecision, "2.48e-324", 2.48e-324);
402+
TEST_DOUBLE(fullPrecision, "2.5e-324", 2.5e-324);
403+
395404
#undef TEST_DOUBLE
396405
}
397406

@@ -1346,20 +1355,20 @@ TEST(Reader, IterativePullParsing_General) {
13461355
handler.LOG_DOUBLE,
13471356
handler.LOG_ENDARRAY | 7
13481357
};
1349-
1358+
13501359
StringStream is("[1, {\"k\": [1, 2]}, null, false, true, \"string\", 1.2]");
13511360
Reader reader;
1352-
1361+
13531362
reader.IterativeParseInit();
13541363
while (!reader.IterativeParseComplete()) {
13551364
size_t oldLogCount = handler.LogCount;
13561365
EXPECT_TRUE(oldLogCount < sizeof(e) / sizeof(int)) << "overrun";
1357-
1366+
13581367
EXPECT_TRUE(reader.IterativeParseNext<kParseDefaultFlags>(is, handler)) << "parse fail";
13591368
EXPECT_EQ(handler.LogCount, oldLogCount + 1) << "handler should be invoked exactly once each time";
13601369
EXPECT_EQ(e[oldLogCount], handler.Logs[oldLogCount]) << "wrong event returned";
13611370
}
1362-
1371+
13631372
EXPECT_FALSE(reader.HasParseError());
13641373
EXPECT_EQ(sizeof(e) / sizeof(int), handler.LogCount) << "handler invoked wrong number of times";
13651374

0 commit comments

Comments
 (0)