From 27895e2f37dda98e8455e7c67e99d055d0c0ebb7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 12 Oct 2008 14:51:45 +0000 Subject: [PATCH] fix off by one bug in the buffer size (fixes #10039) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@56246 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 4 ++++ src/common/strconv.cpp | 10 ++++++--- tests/mbconv/mbconvtest.cpp | 44 +++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index be48d46bdc..ac16a6d1c9 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -91,6 +91,10 @@ Major new features in 2.8 release 2.8.10: ------- +All: + +- Fixed off by one bug in wxMBConv::MB2WC/WC2MB() functions. + All (GUI): - Fixed wxHTML's pagebreaks computation in tables (D.J.Stauffer). diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 48e293d357..43c364e94d 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -332,7 +332,9 @@ wxMBConv::FromWChar(char *dst, size_t dstLen, size_t wxMBConv::MB2WC(wchar_t *outBuff, const char *inBuff, size_t outLen) const { - size_t rc = ToWChar(outBuff, outLen, inBuff); + // add 1 to available buffer length because MB2WC() parameter counts the + // number of non-NUL characters while ToWChar() counts everything + size_t rc = ToWChar(outBuff, outLen + 1, inBuff); if ( rc != wxCONV_FAILED ) { // ToWChar() returns the buffer length, i.e. including the trailing @@ -345,10 +347,12 @@ size_t wxMBConv::MB2WC(wchar_t *outBuff, const char *inBuff, size_t outLen) cons size_t wxMBConv::WC2MB(char *outBuff, const wchar_t *inBuff, size_t outLen) const { - size_t rc = FromWChar(outBuff, outLen, inBuff); + const size_t nulLen = GetMBNulLen(); + + size_t rc = FromWChar(outBuff, outLen + nulLen, inBuff); if ( rc != wxCONV_FAILED ) { - rc -= GetMBNulLen(); + rc -= nulLen; } return rc; diff --git a/tests/mbconv/mbconvtest.cpp b/tests/mbconv/mbconvtest.cpp index d7bf61745c..d6b3cfebf9 100644 --- a/tests/mbconv/mbconvtest.cpp +++ b/tests/mbconv/mbconvtest.cpp @@ -81,6 +81,7 @@ private: CPPUNIT_TEST( LibcTests ); CPPUNIT_TEST( IconvTests ); CPPUNIT_TEST( FontmapTests ); + CPPUNIT_TEST( BufSize ); #ifdef HAVE_WCHAR_H CPPUNIT_TEST( UTF8_41 ); CPPUNIT_TEST( UTF8_7f ); @@ -114,6 +115,7 @@ private: void CP1252Tests(); void LibcTests(); void FontmapTests(); + void BufSize(); void IconvTests(); // verifies that the specified multibyte sequence decodes to the specified wchar_t sequence @@ -799,6 +801,48 @@ void MBConvTestCase::FontmapTests() #endif } +void MBConvTestCase::BufSize() +{ + wxCSConv conv1251(_T("CP1251")); + CPPUNIT_ASSERT( conv1251.IsOk() ); + const char *cp1251text = + "\313\301\326\305\324\323\321 \325\304\301\336\316\331\315"; + const size_t cp1251textLen = strlen(cp1251text); + + const size_t lenW = conv1251.MB2WC(NULL, cp1251text, cp1251textLen); + CPPUNIT_ASSERT( lenW != wxCONV_FAILED ); + wxWCharBuffer wbuf(lenW); + + // lenW-1 is not enough + CPPUNIT_ASSERT_EQUAL( + wxCONV_FAILED, conv1251.MB2WC(wbuf.data(), cp1251text, lenW - 1) ); + + // lenW is just fine + CPPUNIT_ASSERT( + conv1251.MB2WC(wbuf.data(), cp1251text, lenW) != wxCONV_FAILED ); + + // of course, greater values work too + CPPUNIT_ASSERT( + conv1251.MB2WC(wbuf.data(), cp1251text, lenW + 1) != wxCONV_FAILED ); + + + // test in the other direction too, using an encoding with multibyte NUL + wxCSConv convUTF16(_T("UTF-16")); + CPPUNIT_ASSERT( convUTF16.IsOk() ); + const wchar_t *utf16text = L"Hello"; + const size_t utf16textLen = wcslen(utf16text); + + const size_t lenMB = convUTF16.WC2MB(NULL, utf16text, utf16textLen); + CPPUNIT_ASSERT( lenMB != wxCONV_FAILED ); + wxCharBuffer buf(lenMB + 1); // it only adds 1 for NUL on its own, we need 2 + + CPPUNIT_ASSERT_EQUAL( + wxCONV_FAILED, convUTF16.WC2MB(buf.data(), utf16text, lenMB - 1) ); + CPPUNIT_ASSERT( + convUTF16.WC2MB(buf.data(), utf16text, lenMB) != wxCONV_FAILED ); + CPPUNIT_ASSERT( + convUTF16.WC2MB(buf.data(), utf16text, lenMB + 1) != wxCONV_FAILED ); +} WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_iconv( const wxChar* name );