[skjson] NaN while parsing long decimals

When parsing numbers with long decimals, the fast-path decimal factor
may collapse to zero.  Catch this condition (and defer to the slow parse
path).

Bug: skia:8499
Change-Id: I4e364402aecdcca9558d027a55ff297170e2a195
Reviewed-on: https://skia-review.googlesource.com/c/181179
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Florin Malita 2019-01-04 14:55:35 -05:00 committed by Skia Commit-Bot
parent 275eaff3be
commit 5809a4e2c3
2 changed files with 45 additions and 4 deletions

View File

@ -740,13 +740,14 @@ private:
f = f * 10.f + (*p++ - '0'); --exp;
}
if (is_numeric(*p)) {
SkASSERT(*p == '.' || *p == 'e' || *p == 'E');
// We either have malformed input, or an (unsupported) exponent.
const auto decimal_scale = pow10(exp);
if (is_numeric(*p) || !decimal_scale) {
SkASSERT((*p == '.' || *p == 'e' || *p == 'E') || !decimal_scale);
// Malformed input, or an (unsupported) exponent, or a collapsed decimal factor.
return nullptr;
}
this->pushFloat(sign * f * pow10(exp));
this->pushFloat(sign * f * decimal_scale);
return p;
}

View File

@ -414,3 +414,43 @@ DEF_TEST(JSON_DOM_build, reporter) {
"]"
"}");
}
DEF_TEST(JSON_ParseNumber, reporter) {
static constexpr struct {
const char* string;
SkScalar value,
tolerance;
} gTests[] = {
{ "0", 0, 0 },
{ "1", 1, 0 },
{ "00000000", 0, 0 },
{ "00000001", 1, 0 },
{ "0.001", 0.001f, 0 },
{ "1.001", 1.001f, 0 },
{ "0.000001" , 0.000001f, 0 },
{ "1.000001" , 1.000001f, 0 },
{ "1000.000001", 1000.000001f, 0 },
{ "0.0000000001" , 0.0000000001f, 0 },
{ "1.0000000001" , 1.0000000001f, 0 },
{ "1000.0000000001", 1000.0000000001f, 0 },
{ "20.001111814444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444473",
20.001f, 0.001f },
};
for (const auto& test : gTests) {
const auto json = SkStringPrintf("{ \"key\": %s }", test.string);
const DOM dom(json.c_str(), json.size());
const ObjectValue* jroot = dom.root();
REPORTER_ASSERT(reporter, jroot);
const NumberValue* jnumber = (*jroot)["key"];
REPORTER_ASSERT(reporter, jnumber);
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(**jnumber, test.value, test.tolerance));
}
}