Fix OverflowFloatLiteral test in OS X 10.12.

std::stringstream has a subtle bug in OS X 10.12. Reading in a too-large
floating point value returns INFINITY but does not set failbit. This
caused SkSL to report a different error message than expected
("floating point value is infinite" instead of "floating-point value
is too large: NNNNN"). We now guard against this case in SkSL::stod by
adding an explicit `isfinite` check.

Bug: skia:12928
Change-Id: I9996e64b69512ea5710e6fc3ff00ad1ad83c247b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/505939
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2022-02-09 09:36:17 -05:00 committed by SkCQ
parent 93f8c24dc2
commit a424b619bc
5 changed files with 23 additions and 2 deletions

View File

@ -127,6 +127,7 @@ sksl_error_tests = [
"/sksl/errors/Ossfuzz40479.sksl",
"/sksl/errors/Ossfuzz40660.sksl",
"/sksl/errors/Ossfuzz44045.sksl",
"/sksl/errors/OverflowFloatLiteral.sksl",
"/sksl/errors/OverflowInlinedLiteral.sksl",
"/sksl/errors/OverflowIntLiteral.sksl",
"/sksl/errors/OverflowInt64Literal.sksl",

View File

@ -0,0 +1,7 @@
void main() {
sk_FragColor = half4(3.41e+38);
}
/*%%*
floating-point value is too large:
*%%*/

View File

@ -9,6 +9,7 @@
#include "src/sksl/SkSLUtil.h"
#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <errno.h>
#include <limits.h>
#include <locale>
@ -44,7 +45,7 @@ bool SkSL::stod(std::string_view s, SKSL_FLOAT* value) {
std::stringstream buffer(str);
buffer.imbue(std::locale::classic());
buffer >> *value;
return !buffer.fail();
return !buffer.fail() && std::isfinite(*value);
}
bool SkSL::stoi(std::string_view s, SKSL_INT* value) {

View File

@ -74,12 +74,15 @@ static void test_expect_fail(skiatest::Reporter* r, const char* testFile) {
// Verify that the SkSL compiler actually emitted the expected error messages.
// The list of expectations isn't necessarily exhaustive, though.
std::string reportedErrors = compiler.errorText();
std::string originalErrors = reportedErrors;
bool reportOriginalErrors = false;
for (const std::string& expectedError : expectedErrors) {
// If this error wasn't reported, trigger an error.
size_t pos = reportedErrors.find(expectedError.c_str());
if (pos == std::string::npos) {
ERRORF(r, "%s: Expected an error that wasn't reported.\n \"%s\"",
ERRORF(r, "%s: Expected an error that wasn't reported:\n%s\n",
SkOSPath::Basename(testFile).c_str(), expectedError.c_str());
reportOriginalErrors = true;
} else {
// We found the error that we expected to have. Remove that error from our report, and
// everything preceding it as well. This ensures that we don't match the same error
@ -87,6 +90,11 @@ static void test_expect_fail(skiatest::Reporter* r, const char* testFile) {
reportedErrors.erase(0, pos + expectedError.size());
}
}
if (reportOriginalErrors) {
ERRORF(r, "%s: The following errors were reported:\n%s\n",
SkOSPath::Basename(testFile).c_str(), originalErrors.c_str());
}
}
static void iterate_dir(const char* directory, const std::function<void(const char*)>& run) {

View File

@ -0,0 +1,4 @@
### Compilation failed:
error: 2: floating-point value is too large: 3.41e+38
1 error