summaryrefslogtreecommitdiff
path: root/sal
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2014-05-22 18:31:07 +0200
committerStephan Bergmann <sbergman@redhat.com>2014-05-22 18:31:07 +0200
commitb5cb4935c268f12e63b61e035b455b0a59e67aa2 (patch)
tree5710fd654618a971c03f268d68d8a52af409fc5c /sal
parent4330085f141327ee494bb541d4f2f291dd1c590b (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
Diffstat (limited to 'sal')
-rw-r--r--sal/qa/rtl/oustring/rtl_OUString2.cxx20
-rw-r--r--sal/rtl/ustring.cxx19
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()