Skip to content

Commit

Permalink
removing unsafe sscanf from parse function of double-double
Browse files Browse the repository at this point in the history
  • Loading branch information
Ravenwater committed Aug 5, 2024
1 parent 790f889 commit fe434b9
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 18 deletions.
39 changes: 24 additions & 15 deletions include/universal/number/dd/dd_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ class dd {
}
}

if (scientific && !isinf()) {
if (!fixed && !isinf()) {
// construct the exponent
s += uppercase ? 'E' : 'e';
append_expn(s, e);
Expand Down Expand Up @@ -1055,16 +1055,23 @@ bool parse(const std::string& number, dd& value) {
dd r{ 0.0 };
int nrDigits{ 0 };
int decimalPoint{ -1 };
int sign{ 0 };
int sign{ 0 }, eSign{ 1 };
int e{ 0 };
bool done = false;
bool done{ false }, parsingMantissa{ true };
char ch;
while (!done && (ch = *p) != '\0') {
if (std::isdigit(ch)) {
int digit = ch - '0';
r *= 10.0;
r += static_cast<double>(digit);
++nrDigits;
if (parsingMantissa) {
int digit = ch - '0';
r *= 10.0;
r += static_cast<double>(digit);
++nrDigits;
}
else { // parsing exponent section
int digit = ch - '0';
e *= 10;
e += digit;
}
}
else {
switch (ch) {
Expand All @@ -1075,26 +1082,28 @@ bool parse(const std::string& number, dd& value) {

case '-':
case '+':
if (sign != 0 || nrDigits > 0) return false;
sign = (ch == '-') ? -1 : 1;
if (parsingMantissa) {
if (sign != 0 || nrDigits > 0) return false;
sign = (ch == '-' ? -1 : 1);
}
else {
eSign = (ch == '-' ? -1 : 1);
}
break;

case 'E':
case 'e':
{
int nread = std::sscanf(p + 1, "%d", &e);
done = true;
if (nread != 1)
return false;
parsingMantissa = false;
break;
}

default:
return false;
}
}

++p;
}
e *= eSign;

if (decimalPoint >= 0) e -= (nrDigits - decimalPoint);
dd _ten(10.0, 0.0);
Expand Down
2 changes: 1 addition & 1 deletion static/dd/api/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace sw {
void Progression(Real v) {
using namespace sw::universal;

int oldPrec = std::cout.precision();
auto oldPrec = std::cout.precision();
float f{ float(v) };
std::cout << std::setprecision(7);
std::cout << to_binary(f, true) << " : " << f << '\n';
Expand Down
41 changes: 39 additions & 2 deletions static/dd/api/constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,19 @@ namespace sw {
dd _inv_sqrt2("0.707106781186547524400844362104849039"); report(_inv_sqrt2);
}

int VerifyParse(const std::string& str) {
int nrFailedTestCases{ 0 };
dd v{};
if (!parse(str, v)) {
std::cerr << "failed to parse " << str << '\n';
++nrFailedTestCases;
}
else {
ReportValue(v, str);
std::cout << "PASS\n";
}
return nrFailedTestCases;
}
}
}

Expand All @@ -87,8 +100,8 @@ int main()
try {
using namespace sw::universal;

std::string test_suite = "doubledouble conversion validation";
std::string test_tag = "doubledouble conversion";
std::string test_suite = "doubledouble constants";
std::string test_tag = "dd constants";
bool reportTestCases = false;
int nrOfFailedTestCases = 0;

Expand Down Expand Up @@ -124,6 +137,30 @@ try {
std::cout << to_pair(f) << '\n';


// parsing scientific formats
VerifyParse("12.5e-2");
VerifyParse("12.5e-1");
VerifyParse("12.5e-0");
VerifyParse("12.5e+1");
VerifyParse("12.5e2");
VerifyParse("12.5e-02");
VerifyParse("12.5e-01");
VerifyParse("12.5e00");
VerifyParse("12.5e+01");
VerifyParse("12.5e02");
VerifyParse("12.5e-002");
VerifyParse("12.5e-001");
VerifyParse("12.5e000");
VerifyParse("12.5e+001");
VerifyParse("12.5e002");
VerifyParse("12.5e-200");
VerifyParse("12.5e-100");
VerifyParse("12.5e000");
VerifyParse("12.5e+100");
VerifyParse("12.5e200");

d = 12.5e200;
std::cout << d << '\n';

ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
return EXIT_SUCCESS; // ignore failures
Expand Down

0 comments on commit fe434b9

Please sign in to comment.