diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2014-05-22 18:31:07 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2014-05-22 18:31:07 +0200 |
commit | b5cb4935c268f12e63b61e035b455b0a59e67aa2 (patch) | |
tree | 5710fd654618a971c03f268d68d8a52af409fc5c | |
parent | 4330085f141327ee494bb541d4f2f291dd1c590b (diff) |
Work around undef conversion of large double to float
...as flagged by -fsanitize=undefined. But is it really undefined?
[conv.double] "If the source value is between two adjacent destination values,
the result of the conversion is an implementation-defined choice of either of
those values." So if the double is between std::numeric_limits<float>::max()
and std::numeric_limits<float>::infinity()...
Change-Id: I6389c8ac4a922991e240638d231dd2a39e173882
-rw-r--r-- | sal/qa/rtl/oustring/rtl_OUString2.cxx | 20 | ||||
-rw-r--r-- | sal/rtl/ustring.cxx | 19 |
2 files changed, 35 insertions, 4 deletions
diff --git a/sal/qa/rtl/oustring/rtl_OUString2.cxx b/sal/qa/rtl/oustring/rtl_OUString2.cxx index 849c5215dd16..27a06ab43464 100644 --- a/sal/qa/rtl/oustring/rtl_OUString2.cxx +++ b/sal/qa/rtl/oustring/rtl_OUString2.cxx @@ -23,6 +23,7 @@ #include <stdio.h> #include <algorithm> +#include <limits> #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> @@ -34,6 +35,21 @@ namespace rtl_OUString { +namespace { + +// Avoid -fsanitize=undefined warning e.g. "runtime error: value 1e+99 is +// outside the range of representable values of type 'float'": +float doubleToFloat(double x) { + return + x < -std::numeric_limits<float>::max() + ? -std::numeric_limits<float>::infinity() + : x > std::numeric_limits<float>::max() + ? std::numeric_limits<float>::infinity() + : static_cast<float>(x); +} + +} + class number : public CppUnit::TestFixture { void number_float_test_impl(float _nValue) @@ -43,7 +59,7 @@ class number : public CppUnit::TestFixture sValue <<= suValue; printf("nFloat := %.9f sValue := %s\n", _nValue, sValue.getStr()); - float nValueATOF = static_cast<float>(atof( sValue.getStr() )); + double nValueATOF = doubleToFloat(atof( sValue.getStr() )); bool bEqualResult = is_float_equal(_nValue, nValueATOF); CPPUNIT_ASSERT_MESSAGE("Values are not equal.", bEqualResult == true); @@ -439,7 +455,7 @@ sal_Int16 SAL_CALL checkPrecisionSize() void toFloat_test_impl(rtl::OString const& _sValue) { //printf("the original str is %s\n", _sValue.getStr()); - float nValueATOF = static_cast<float>(atof( _sValue.getStr() )); + float nValueATOF = doubleToFloat(atof( _sValue.getStr() )); //printf("the original str is %.10f\n", nValueATOF); rtl::OUString suValue = rtl::OUString::createFromAscii( _sValue.getStr() ); float nValueToFloat = suValue.toFloat(); diff --git a/sal/rtl/ustring.cxx b/sal/rtl/ustring.cxx index f10e755bbc7b..a79c9177a3ee 100644 --- a/sal/rtl/ustring.cxx +++ b/sal/rtl/ustring.cxx @@ -148,11 +148,26 @@ sal_Int32 SAL_CALL rtl_ustr_valueOfDouble(sal_Unicode * pStr, double d) return nLen; } +namespace { + +// Avoid -fsanitize=undefined warning e.g. "runtime error: value 1e+99 is +// outside the range of representable values of type 'float'": +float doubleToFloat(double x) { + return + x < -std::numeric_limits<float>::max() + ? -std::numeric_limits<float>::infinity() + : x > std::numeric_limits<float>::max() + ? std::numeric_limits<float>::infinity() + : static_cast<float>(x); +} + +} + float SAL_CALL rtl_ustr_toFloat(sal_Unicode const * pStr) SAL_THROW_EXTERN_C() { - return (float) rtl_math_uStringToDouble(pStr, + return doubleToFloat(rtl_math_uStringToDouble(pStr, pStr + rtl_ustr_getLength(pStr), - '.', 0, 0, 0); + '.', 0, 0, 0)); } double SAL_CALL rtl_ustr_toDouble(sal_Unicode const * pStr) SAL_THROW_EXTERN_C() |