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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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;
_______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
