Fix another off-by-1 bug in wxMBConv::ToWChar().

When converting a fixed number of characters we need to take any NULs inside
the buffer being converted into account for our return value -- but this
wasn't done and converting 2 characters 'x' and '\0' returned only 1, even if
the length 2 was explicitly specified.

Fix this bug and add a unit test checking for it.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62141 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2009-09-26 13:31:27 +00:00
parent 4bc9acbe16
commit bbb0ff36db
2 changed files with 31 additions and 23 deletions

View File

@@ -216,7 +216,7 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen,
// all the complication come from the fact that this function, for // all the complication come from the fact that this function, for
// historical reasons, must behave in 2 subtly different ways when it's // historical reasons, must behave in 2 subtly different ways when it's
// called with a fixed number of characters and when it's called for the // called with a fixed number of characters and when it's called for the
// entire NUL-terminated string: in the former case (srcEnd == NULL) we // entire NUL-terminated string: in the former case (srcEnd != NULL) we
// must count all characters we convert, NUL or not; but in the latter we // must count all characters we convert, NUL or not; but in the latter we
// do not count the trailing NUL -- but still count all the NULs inside the // do not count the trailing NUL -- but still count all the NULs inside the
// string // string
@@ -258,11 +258,13 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen,
if ( !srcEnd ) if ( !srcEnd )
{ {
// we convert just one chunk in this case as this is the entire // we convert just one chunk in this case as this is the entire
// string anyhow // string anyhow (and we don't count the trailing NUL in this case)
break; break;
} }
// advance the input pointer past the end of this chunk // advance the input pointer past the end of this chunk: notice that we
// will always stop before srcEnd because we know that the chunk is
// always properly NUL-terminated
while ( NotAllNULs(src, nulLen) ) while ( NotAllNULs(src, nulLen) )
{ {
// notice that we must skip over multiple bytes here as we suppose // notice that we must skip over multiple bytes here as we suppose
@@ -272,23 +274,20 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen,
src += nulLen; src += nulLen;
} }
src += nulLen; // skipping over its terminator as well // if the buffer ends before this NUL, we shouldn't count it in our
// output so skip the code below
// note that ">=" (and not just "==") is needed here as the terminator if ( src == srcEnd )
// we skipped just above could be inside or just after the buffer
// delimited by srcEnd
if ( src >= srcEnd )
break; break;
// if we got here then this wasn't the last chunk in this string and // do count this terminator as it's inside the buffer we convert
// hence we must count an extra char for L'\0' even when converting a
// fixed number of characters
if ( srcEnd )
{
dstWritten++; dstWritten++;
if ( dst ) if ( dst )
dst++; dst++;
}
src += nulLen; // skip the terminator itself
if ( src >= srcEnd )
break;
} }
return dstWritten; return dstWritten;

View File

@@ -139,7 +139,7 @@ private:
CPPUNIT_TEST_SUITE( UnicodeTestCase ); CPPUNIT_TEST_SUITE( UnicodeTestCase );
CPPUNIT_TEST( ToFromAscii ); CPPUNIT_TEST( ToFromAscii );
CPPUNIT_TEST( ConstructorsWithConversion ); CPPUNIT_TEST( ConstructorsWithConversion );
CPPUNIT_TEST( ConversionEmpty ); CPPUNIT_TEST( ConversionFixed );
CPPUNIT_TEST( ConversionWithNULs ); CPPUNIT_TEST( ConversionWithNULs );
CPPUNIT_TEST( ConversionUTF7 ); CPPUNIT_TEST( ConversionUTF7 );
CPPUNIT_TEST( ConversionUTF8 ); CPPUNIT_TEST( ConversionUTF8 );
@@ -153,7 +153,7 @@ private:
void ToFromAscii(); void ToFromAscii();
void ConstructorsWithConversion(); void ConstructorsWithConversion();
void ConversionEmpty(); void ConversionFixed();
void ConversionWithNULs(); void ConversionWithNULs();
void ConversionUTF7(); void ConversionUTF7();
void ConversionUTF8(); void ConversionUTF8();
@@ -238,7 +238,7 @@ void UnicodeTestCase::ConstructorsWithConversion()
CPPUNIT_ASSERT( s5 != "SomethingElse" ); CPPUNIT_ASSERT( s5 != "SomethingElse" );
} }
void UnicodeTestCase::ConversionEmpty() void UnicodeTestCase::ConversionFixed()
{ {
size_t len; size_t len;
@@ -249,6 +249,15 @@ void UnicodeTestCase::ConversionEmpty()
#endif // wxUSE_UNICODE/!wxUSE_UNICODE #endif // wxUSE_UNICODE/!wxUSE_UNICODE
CPPUNIT_ASSERT_EQUAL( 0, len ); CPPUNIT_ASSERT_EQUAL( 0, len );
#if wxUSE_UNICODE
// check that when we convert a fixed number of characters we obtain the
// expected return value
CPPUNIT_ASSERT_EQUAL( 0, wxConvLibc.ToWChar(NULL, 0, "", 0) );
CPPUNIT_ASSERT_EQUAL( 1, wxConvLibc.ToWChar(NULL, 0, "x", 1) );
CPPUNIT_ASSERT_EQUAL( 2, wxConvLibc.ToWChar(NULL, 0, "x", 2) );
CPPUNIT_ASSERT_EQUAL( 2, wxConvLibc.ToWChar(NULL, 0, "xy", 2) );
#endif // wxUSE_UNICODE
} }
void UnicodeTestCase::ConversionWithNULs() void UnicodeTestCase::ConversionWithNULs()