unotools/source/i18n/localedatawrapper.cxx |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

New commits:
commit e15c04f16fa28aa70de7de1e10d57fd03ab0b2d4
Author:     Stephan Bergmann <sberg...@redhat.com>
AuthorDate: Sun Feb 6 11:48:56 2022 +0100
Commit:     Stephan Bergmann <sberg...@redhat.com>
CommitDate: Sun Feb 6 15:09:23 2022 +0100

    Avoid signed-integer-overflow
    
    ...as seen during e.g. UITest_calc_tests9 now,
    
    > unotools/source/i18n/localedatawrapper.cxx:1017:17: runtime error: signed 
integer overflow: -9223372036854775808 * -1 cannot be represented in type 'long'
    >  #0 in LocaleDataWrapper::ImplAddFormatNum(rtl::OUStringBuffer&, long, 
unsigned short, bool, bool) const at 
unotools/source/i18n/localedatawrapper.cxx:1017:17
    >  #1 in LocaleDataWrapper::getNum(long, unsigned short, bool, bool) const 
at unotools/source/i18n/localedatawrapper.cxx:1217:5
    >  #2 in weld::MetricSpinButton::format_number(long) const at 
vcl/source/window/builder.cxx:306:32
    >  #3 in weld::MetricSpinButton::update_width_chars() at 
vcl/source/window/builder.cxx:259:61
    >  #4 in weld::MetricSpinButton::set_range(long, long, FieldUnit) at 
include/vcl/weld.hxx:1991:9
    >  #5 in weld::MetricSpinButton::set_min(long, FieldUnit) at 
include/vcl/weld.hxx:2005:9
    
    Change-Id: I940e2f1e2e4d42db84d4bb0e7b68086204dc77ac
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129570
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>

diff --git a/unotools/source/i18n/localedatawrapper.cxx 
b/unotools/source/i18n/localedatawrapper.cxx
index 42b8027b3239..96ad86d4b76a 100644
--- a/unotools/source/i18n/localedatawrapper.cxx
+++ b/unotools/source/i18n/localedatawrapper.cxx
@@ -17,6 +17,7 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <limits>
 #include <stdio.h>
 #include <string>
 
@@ -1012,14 +1013,21 @@ void LocaleDataWrapper::ImplAddFormatNum( 
OUStringBuffer& rBuf,
     sal_uInt16  nNumLen;
 
     // negative number
+    sal_uInt64 abs;
     if ( nNumber < 0 )
     {
-        nNumber *= -1;
+        // Avoid overflow, map -2^63 -> 2^63 explicitly:
+        abs = nNumber == std::numeric_limits<sal_Int64>::min()
+            ? static_cast<sal_uInt64>(std::numeric_limits<sal_Int64>::min()) : 
nNumber * -1;
         rBuf.append('-');
     }
+    else
+    {
+        abs = nNumber;
+    }
 
     // convert number
-    ImplAddUNum( aNumBuf, static_cast<sal_uInt64>(nNumber) );
+    ImplAddUNum( aNumBuf, abs );
     nNumLen = static_cast<sal_uInt16>(aNumBuf.getLength());
 
     if ( nNumLen <= nDecimals )

Reply via email to