[Libreoffice-commits] core.git: 3 commits - sal/CppunitTest_sal_rtl_strings.mk sal/inc sal/qa sal/rtl sal/util

Stephan Bergmann sbergman at redhat.com
Mon Mar 25 09:33:53 PDT 2013


 sal/CppunitTest_sal_rtl_strings.mk        |    1 
 sal/inc/rtl/string.h                      |   21 +++++++++
 sal/inc/rtl/string.hxx                    |   23 +++++++++-
 sal/inc/rtl/ustring.h                     |   14 +++---
 sal/inc/rtl/ustring.hxx                   |   11 +++--
 sal/qa/rtl/strings/test_strings_toint.cxx |   65 ++++++++++++++++++++++++++++++
 sal/rtl/strtmpl.cxx                       |    8 +++
 sal/util/sal.map                          |    1 
 8 files changed, 133 insertions(+), 11 deletions(-)

New commits:
commit 40dcf2d713e67ef4d8c68a6df98954f1f0b783db
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Mon Mar 25 16:24:48 2013 +0100

    Add test case for toInt overflow detection
    
    Change-Id: I1c5b66888baac8aa1bc99c06579e0ef3638a4877

diff --git a/sal/CppunitTest_sal_rtl_strings.mk b/sal/CppunitTest_sal_rtl_strings.mk
index 222cedf..1d56ecd 100644
--- a/sal/CppunitTest_sal_rtl_strings.mk
+++ b/sal/CppunitTest_sal_rtl_strings.mk
@@ -38,6 +38,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sal_rtl_strings,\
     sal/qa/rtl/strings/test_oustring_noadditional \
     sal/qa/rtl/strings/test_oustring_startswith \
     sal/qa/rtl/strings/test_oustring_stringliterals \
+    sal/qa/rtl/strings/test_strings_toint \
     sal/qa/rtl/strings/test_strings_valuex \
 ))
 
diff --git a/sal/inc/rtl/string.hxx b/sal/inc/rtl/string.hxx
index 01ee464..f6cec59 100644
--- a/sal/inc/rtl/string.hxx
+++ b/sal/inc/rtl/string.hxx
@@ -1349,7 +1349,8 @@ public:
 
       @param    radix       the radix (between 2 and 36)
       @return   the int32 represented from this string.
-                0 if this string represents no number.
+                0 if this string represents no number or one of too large
+                magnitude.
     */
     sal_Int32 toInt32( sal_Int16 radix = 10 ) const SAL_THROW(())
     {
@@ -1363,7 +1364,8 @@ public:
 
       @param    radix       the radix (between 2 and 36)
       @return   the int64 represented from this string.
-                0 if this string represents no number.
+                0 if this string represents no number or one of too large
+                magnitude.
     */
     sal_Int64 toInt64( sal_Int16 radix = 10 ) const SAL_THROW(())
     {
@@ -1377,7 +1379,8 @@ public:
 
       @param    radix       the radix (between 2 and 36)
       @return   the uint64 represented from this string.
-                0 if this string represents no number.
+                0 if this string represents no number or one of too large
+                magnitude.
 
       @since LibreOffice 4.1
     */
diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx
index 2afd95c..768f552 100644
--- a/sal/inc/rtl/ustring.hxx
+++ b/sal/inc/rtl/ustring.hxx
@@ -1828,7 +1828,8 @@ public:
 
       @param    radix       the radix (between 2 and 36)
       @return   the int32 represented from this string.
-                0 if this string represents no number.
+                0 if this string represents no number or one of too large
+                magnitude.
     */
     sal_Int32 toInt32( sal_Int16 radix = 10 ) const SAL_THROW(())
     {
@@ -1842,7 +1843,8 @@ public:
 
       @param    radix       the radix (between 2 and 36)
       @return   the int64 represented from this string.
-                0 if this string represents no number.
+                0 if this string represents no number or one of too large
+                magnitude.
     */
     sal_Int64 toInt64( sal_Int16 radix = 10 ) const SAL_THROW(())
     {
@@ -1856,7 +1858,8 @@ public:
 
       @param    radix       the radix (between 2 and 36)
       @return   the uint64 represented from this string.
-                0 if this string represents no number.
+                0 if this string represents no number or one of too large
+                magnitude.
 
       @since LibreOffice 4.1
     */
diff --git a/sal/qa/rtl/strings/test_strings_toint.cxx b/sal/qa/rtl/strings/test_strings_toint.cxx
new file mode 100644
index 0000000..4a4f549
--- /dev/null
+++ b/sal/qa/rtl/strings/test_strings_toint.cxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "sal/config.h"
+
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+namespace {
+
+template< typename T > class Test: public CppUnit::TestFixture {
+private:
+    CPPUNIT_TEST_SUITE(Test);
+    CPPUNIT_TEST(testToInt32Overflow);
+    CPPUNIT_TEST(testToInt64Overflow);
+    CPPUNIT_TEST(testToUInt64Overflow);
+    CPPUNIT_TEST_SUITE_END();
+
+    void testToInt32Overflow() {
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(0), T("-2147483649").toInt32());
+        CPPUNIT_ASSERT_EQUAL(SAL_MIN_INT32, T("-2147483648").toInt32());
+        CPPUNIT_ASSERT_EQUAL(SAL_MIN_INT32 + 1, T("-2147483647").toInt32());
+        CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT32 - 1, T("2147483646").toInt32());
+        CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT32, T("2147483647").toInt32());
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(0), T("2147483648").toInt32());
+    }
+
+    void testToInt64Overflow() {
+        CPPUNIT_ASSERT_EQUAL(sal_Int64(0), T("-9223372036854775809").toInt64());
+        CPPUNIT_ASSERT_EQUAL(
+            SAL_MIN_INT64, T("-9223372036854775808").toInt64());
+        CPPUNIT_ASSERT_EQUAL(
+            SAL_MIN_INT64 + 1, T("-9223372036854775807").toInt64());
+        CPPUNIT_ASSERT_EQUAL(
+            SAL_MAX_INT64 - 1, T("9223372036854775806").toInt64());
+        CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT64, T("9223372036854775807").toInt64());
+        CPPUNIT_ASSERT_EQUAL(sal_Int64(0), T("9223372036854775808").toInt64());
+    }
+
+    void testToUInt64Overflow() {
+        CPPUNIT_ASSERT_EQUAL(
+            SAL_MAX_UINT64 - 1, T("18446744073709551614").toUInt64());
+        CPPUNIT_ASSERT_EQUAL(
+            SAL_MAX_UINT64, T("18446744073709551615").toUInt64());
+        CPPUNIT_ASSERT_EQUAL(
+            sal_uInt64(0), T("18446744073709551616").toUInt64());
+    }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test< rtl::OString >);
+CPPUNIT_TEST_SUITE_REGISTRATION(Test< rtl::OUString >);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit bd60d41176da540b01d7583cfe00637431967f39
Author: Zolnai Tamás <zolnaitamas2000 at gmail.com>
Date:   Mon Mar 25 12:06:20 2013 +0100

    Handle oveflow in O(U)String::toInt() functions
    
    Return 0 when overflow.
    The base idea in unsigned case is checking wheather
    (Max-nDigit)/nRadix < n
    But for efficency, take out nDiv = Max/nRadix from loop
    and corrigate it with -1 if needed.
    In signed case use minimum value if the number is negativ.
    
    Change-Id: I5b77580adbf12421b6c4b785ba9bc2a080accba2
    Signed-off-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/sal/rtl/strtmpl.cxx b/sal/rtl/strtmpl.cxx
index 69bd5ee..6859af1 100644
--- a/sal/rtl/strtmpl.cxx
+++ b/sal/rtl/strtmpl.cxx
@@ -941,11 +941,15 @@ namespace {
             bNeg = sal_False;
         }
 
+        const T nDiv = bNeg ? -(std::numeric_limits<T>::min()/nRadix) : (std::numeric_limits<T>::max()/nRadix);
+        const sal_Int16 nMod = bNeg ? -(std::numeric_limits<T>::min()%nRadix) : (std::numeric_limits<T>::max()%nRadix);
         while ( *pStr )
         {
             nDigit = rtl_ImplGetDigit( IMPL_RTL_USTRCODE( *pStr ), nRadix );
             if ( nDigit < 0 )
                 break;
+            if( ( nMod < nDigit ? nDiv-1 : nDiv ) < n )
+                return 0;
 
             n *= nRadix;
             n += nDigit;
@@ -978,11 +982,15 @@ namespace {
         if ( *pStr == '+' )
             ++pStr;
 
+        const T nDiv = std::numeric_limits<T>::max()/nRadix;
+        const sal_Int16 nMod = std::numeric_limits<T>::max()%nRadix;
         while ( *pStr )
         {
             nDigit = rtl_ImplGetDigit( IMPL_RTL_USTRCODE( *pStr ), nRadix );
             if ( nDigit < 0 )
                 break;
+            if( ( nMod < nDigit ? nDiv-1 : nDiv ) < n )
+                return 0;
 
             n *= nRadix;
             n += nDigit;
commit 476081b19bd71d5c1eb7d82eee4821f099ecde78
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Mon Mar 25 16:20:31 2013 +0100

    Clean up new toUInt64
    
    Change-Id: Ic908cb5cc9169ab1baae2c1c52070adfb9afba39

diff --git a/sal/inc/rtl/string.h b/sal/inc/rtl/string.h
index a16d61e..93cffa1 100644
--- a/sal/inc/rtl/string.h
+++ b/sal/inc/rtl/string.h
@@ -762,6 +762,27 @@ SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_str_toInt32(
 SAL_DLLPUBLIC sal_Int64 SAL_CALL rtl_str_toInt64(
         const sal_Char * str, sal_Int16 radix ) SAL_THROW_EXTERN_C();
 
+/** Interpret a string as an unsigned long integer.
+
+    This function cannot be used for language-specific conversion.  The string
+    must be null-terminated.
+
+    @param str
+    a null-terminated string.
+
+    @param radix
+    the radix.  Must be between RTL_USTR_MIN_RADIX (2) and RTL_USTR_MAX_RADIX
+    (36), inclusive.
+
+    @return
+    the unsigned long integer value represented by the string, or 0 if the
+    string does not represent an unsigned long integer.
+
+    @since LibreOffice 4.1
+ */
+SAL_DLLPUBLIC sal_uInt64 SAL_CALL rtl_str_toUInt64(
+        const sal_Char * str, sal_Int16 radix ) SAL_THROW_EXTERN_C();
+
 /** Interpret a string as a float.
 
     This function cannot be used for language-specific conversion.  The string
diff --git a/sal/inc/rtl/string.hxx b/sal/inc/rtl/string.hxx
index cbb8cd5..01ee464 100644
--- a/sal/inc/rtl/string.hxx
+++ b/sal/inc/rtl/string.hxx
@@ -1371,6 +1371,22 @@ public:
     }
 
     /**
+      Returns the uint64 value from this string.
+
+      This function can't be used for language specific conversion.
+
+      @param    radix       the radix (between 2 and 36)
+      @return   the uint64 represented from this string.
+                0 if this string represents no number.
+
+      @since LibreOffice 4.1
+    */
+    sal_uInt64 toUInt64( sal_Int16 radix = 10 ) const SAL_THROW(())
+    {
+        return rtl_str_toUInt64( pData->buffer, radix );
+    }
+
+    /**
       Returns the float value from this string.
 
       This function can't be used for language specific conversion.
diff --git a/sal/inc/rtl/ustring.h b/sal/inc/rtl/ustring.h
index f6bf956..da6720b 100644
--- a/sal/inc/rtl/ustring.h
+++ b/sal/inc/rtl/ustring.h
@@ -1073,7 +1073,7 @@ SAL_DLLPUBLIC sal_Bool SAL_CALL rtl_ustr_toBoolean(
 SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_ustr_toInt32(
         const sal_Unicode * str, sal_Int16 radix ) SAL_THROW_EXTERN_C();
 
-/** Interpret a string as an unsigned long integer.
+/** Interpret a string as a long integer.
 
     This function cannot be used for language-specific conversion.  The string
     must be null-terminated.
@@ -1089,10 +1089,10 @@ SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_ustr_toInt32(
     the long integer value represented by the string, or 0 if the string does
     not represent a long integer.
  */
-SAL_DLLPUBLIC sal_uInt64 SAL_CALL rtl_ustr_toUInt64(
+SAL_DLLPUBLIC sal_Int64 SAL_CALL rtl_ustr_toInt64(
         const sal_Unicode * str, sal_Int16 radix ) SAL_THROW_EXTERN_C();
 
-/** Interpret a string as a long integer.
+/** Interpret a string as an unsigned long integer.
 
     This function cannot be used for language-specific conversion.  The string
     must be null-terminated.
@@ -1105,10 +1105,12 @@ SAL_DLLPUBLIC sal_uInt64 SAL_CALL rtl_ustr_toUInt64(
     (36), inclusive.
 
     @return
-    the long integer value represented by the string, or 0 if the string does
-    not represent a long integer.
+    the unsigned long integer value represented by the string, or 0 if the
+    string does not represent an unsigned long integer.
+
+    @since LibreOffice 4.1
  */
-SAL_DLLPUBLIC sal_Int64 SAL_CALL rtl_ustr_toInt64(
+SAL_DLLPUBLIC sal_uInt64 SAL_CALL rtl_ustr_toUInt64(
         const sal_Unicode * str, sal_Int16 radix ) SAL_THROW_EXTERN_C();
 
 /** Interpret a string as a float.
diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx
index 4d9650e..2afd95c 100644
--- a/sal/inc/rtl/ustring.hxx
+++ b/sal/inc/rtl/ustring.hxx
@@ -1857,6 +1857,8 @@ public:
       @param    radix       the radix (between 2 and 36)
       @return   the uint64 represented from this string.
                 0 if this string represents no number.
+
+      @since LibreOffice 4.1
     */
     sal_uInt64 toUInt64( sal_Int16 radix = 10 ) const SAL_THROW(())
     {
diff --git a/sal/util/sal.map b/sal/util/sal.map
index e21ff0a..f2790d5 100644
--- a/sal/util/sal.map
+++ b/sal/util/sal.map
@@ -658,6 +658,7 @@ LIBO_UDK_4.1 { # symbols available in >= LibO 4.1
         rtl_uString_ensureCapacity;
         rtl_string_alloc;
         rtl_uString_alloc;
+        rtl_str_toUInt64;
         rtl_str_valueOfUInt64;
         rtl_ustr_valueOfUInt64;
         rtl_ustr_toUInt64;


More information about the Libreoffice-commits mailing list