From: Vadim Zeitlin Date: Thu, 30 Aug 2012 20:22:17 +0000 (+0000) Subject: Fix bugs in parsing wxLongLong values starting with zeroes. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/8421cb3c7cab3017fd991ee628126813ee2d794a Fix bugs in parsing wxLongLong values starting with zeroes. wxCRT_StrtoullBase(), used by wxString::To[U]LongLong(), didn't handle leading zeroes nor leading 0x correctly: it never auto-detected base 8; didn't ignore the leading 0 even if base 8 was specified explicitly; didn't recognize "0X" prefix at all (only "0x"). Fix all these bugs and add test cases for parsing numbers in other bases to the unit tests. Closes #14596. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72408 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/src/common/wxcrt.cpp b/src/common/wxcrt.cpp index de9012b6d5..f58ac30fd0 100644 --- a/src/common/wxcrt.cpp +++ b/src/common/wxcrt.cpp @@ -975,23 +975,35 @@ wxCRT_StrtoullBase(const T* nptr, T** endptr, int base, T* sign) } } - // Starts with 0x? + // Starts with octal or hexadecimal prefix? if ( i != end && *i == wxT('0') ) { ++i; if ( i != end ) { - if ( *i == wxT('x') && (base == 16 || base == 0) ) + if ( (*i == wxT('x')) || (*i == wxT('X')) ) { - base = 16; - ++i; + // Hexadecimal prefix: use base 16 if auto-detecting. + if ( base == 0 ) + base = 16; + + // If we do use base 16, just skip "x" as well. + if ( base == 16 ) + { + ++i; + } + else // Not using base 16 + { + // Then it's an error. + if ( endptr ) + *endptr = (T*) nptr; + wxSET_ERRNO(EINVAL); + return sum; + } } - else + else if ( base == 0 ) { - if ( endptr ) - *endptr = (T*) nptr; - wxSET_ERRNO(EINVAL); - return sum; + base = 8; } } else diff --git a/tests/strings/strings.cpp b/tests/strings/strings.cpp index e1d7262bb9..a0485c9007 100644 --- a/tests/strings/strings.cpp +++ b/tests/strings/strings.cpp @@ -599,6 +599,7 @@ static const struct ToLongData long value; #endif // wxLongLong_t int flags; + int base; long LValue() const { return value; } unsigned long ULValue() const { return value; } @@ -629,6 +630,22 @@ static const struct ToLongData { wxT("9223372036854775808"), wxULL(9223372036854775808), Number_LongLong | Number_Unsigned }, #endif // wxLongLong_t + + // Base tests. + { wxT("010"), 10, Number_Ok, 10 }, + { wxT("010"), 8, Number_Ok, 0 }, + { wxT("010"), 8, Number_Ok, 8 }, + { wxT("010"), 16, Number_Ok, 16 }, + + { wxT("0010"), 10, Number_Ok, 10 }, + { wxT("0010"), 8, Number_Ok, 0 }, + { wxT("0010"), 8, Number_Ok, 8 }, + { wxT("0010"), 16, Number_Ok, 16 }, + + { wxT("0x11"), 0, Number_Invalid, 10 }, + { wxT("0x11"), 17, Number_Ok, 0 }, + { wxT("0x11"), 0, Number_Invalid, 8 }, + { wxT("0x11"), 17, Number_Ok, 16 }, }; void StringTestCase::ToLong() @@ -644,11 +661,13 @@ void StringTestCase::ToLong() // NOTE: unless you're using some exotic locale, ToCLong and ToLong // should behave the same for our test data set: - CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToCLong(&l) ); + CPPUNIT_ASSERT_EQUAL( ld.IsOk(), + wxString(ld.str).ToCLong(&l, ld.base) ); if ( ld.IsOk() ) CPPUNIT_ASSERT_EQUAL( ld.LValue(), l ); - CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToLong(&l) ); + CPPUNIT_ASSERT_EQUAL( ld.IsOk(), + wxString(ld.str).ToLong(&l, ld.base) ); if ( ld.IsOk() ) CPPUNIT_ASSERT_EQUAL( ld.LValue(), l ); } @@ -678,11 +697,13 @@ void StringTestCase::ToULong() // NOTE: unless you're using some exotic locale, ToCLong and ToLong // should behave the same for our test data set: - CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToCULong(&ul) ); + CPPUNIT_ASSERT_EQUAL( ld.IsOk(), + wxString(ld.str).ToCULong(&ul, ld.base) ); if ( ld.IsOk() ) CPPUNIT_ASSERT_EQUAL( ld.ULValue(), ul ); - CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToULong(&ul) ); + CPPUNIT_ASSERT_EQUAL( ld.IsOk(), + wxString(ld.str).ToULong(&ul, ld.base) ); if ( ld.IsOk() ) CPPUNIT_ASSERT_EQUAL( ld.ULValue(), ul ); } @@ -700,7 +721,8 @@ void StringTestCase::ToLongLong() if ( ld.flags & (Number_Long | Number_Unsigned) ) continue; - CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToLongLong(&l) ); + CPPUNIT_ASSERT_EQUAL( ld.IsOk(), + wxString(ld.str).ToLongLong(&l, ld.base) ); if ( ld.IsOk() ) CPPUNIT_ASSERT_EQUAL( ld.LLValue(), l ); } @@ -716,7 +738,8 @@ void StringTestCase::ToULongLong() if ( ld.flags & (Number_Long | Number_Signed) ) continue; - CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToULongLong(&ul) ); + CPPUNIT_ASSERT_EQUAL( ld.IsOk(), + wxString(ld.str).ToULongLong(&ul, ld.base) ); if ( ld.IsOk() ) CPPUNIT_ASSERT_EQUAL( ld.ULLValue(), ul ); }