Skip to content

Commit d5402d8

Browse files
committed
avoid out-of-range double to long long casts in MSBuild System.Math
1 parent 37a06d2 commit d5402d8

2 files changed

Lines changed: 18 additions & 11 deletions

File tree

‎lib/importproject.cpp‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,9 +1381,12 @@ std::string ImportProject::applyMSBuildStaticFunction(const std::string &classNa
13811381
// Format a double as an integer string when the value is whole,
13821382
// otherwise use std::to_string (which gives 6 decimal places).
13831383
const auto fmtDouble = [](double d) -> std::string {
1384-
const auto i = static_cast<long long>(d);
1385-
if (!(static_cast<double>(i) < d) && !(static_cast<double>(i) > d))
1386-
return std::to_string(i);
1384+
// Converting a double outside the long long range is undefined behaviour
1385+
if (d >= static_cast<double>(LLONG_MIN) && d < -static_cast<double>(LLONG_MIN)) {
1386+
const auto i = static_cast<long long>(d);
1387+
if (!(static_cast<double>(i) < d) && !(static_cast<double>(i) > d))
1388+
return std::to_string(i);
1389+
}
13871390
return std::to_string(d);
13881391
};
13891392
if (args.size() == 1) {
@@ -1400,16 +1403,14 @@ std::string ImportProject::applyMSBuildStaticFunction(const std::string &classNa
14001403
// not round-half-away-from-zero.
14011404
const double fl = std::floor(x);
14021405
const double frac = x - fl;
1403-
long long rounded;
1406+
double rounded;
14041407
if (frac < 0.5)
1405-
rounded = static_cast<long long>(fl);
1408+
rounded = fl;
14061409
else if (frac > 0.5)
1407-
rounded = static_cast<long long>(fl) + 1;
1408-
else { // exactly 0.5 -- round to nearest even integer
1409-
const auto ifl = static_cast<long long>(fl);
1410-
rounded = ((ifl % 2) == 0) ? ifl : ifl + 1;
1411-
}
1412-
return std::to_string(rounded);
1410+
rounded = fl + 1;
1411+
else // exactly 0.5 -- round to nearest even integer
1412+
rounded = (std::fabs(std::fmod(fl, 2.0)) < 1) ? fl : fl + 1;
1413+
return fmtDouble(rounded);
14131414
}
14141415
if (caseInsensitiveStringCompare(member, "Sqrt") == 0 && x >= 0)
14151416
return fmtDouble(std::sqrt(x));

‎test/testimportproject.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,12 @@ class TestImportProject : public TestFixture {
13191319
ASSERT_EQUALS("5", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Abs(5))"));
13201320
ASSERT_EQUALS("2", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Floor(2.9))"));
13211321
ASSERT_EQUALS("3", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Ceiling(2.1))"));
1322+
ASSERT_EQUALS("2", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Round(2.5))"));
1323+
ASSERT_EQUALS("4", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Round(3.5))"));
1324+
ASSERT_EQUALS("-2", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Round(-2.5))"));
1325+
ASSERT_EQUALS("1000000000000000019884624838656.000000", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Pow(10, 30))"));
1326+
ASSERT_EQUALS("1000000000000000019884624838656.000000", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Round(1e30))"));
1327+
ASSERT_EQUALS("-1000000000000000019884624838656.000000", cppcheck::testing::expandMSBuildExpression("$([System.Math]::Floor(-1e30))"));
13221328

13231329
// --- $([System.IO.Path]::...) ---
13241330
ASSERT_EQUALS("bar.cpp", cppcheck::testing::expandMSBuildExpression("$([System.IO.Path]::GetFileName('C:/foo/bar.cpp'))"));

0 commit comments

Comments
 (0)