Bug in CStringT operator=
-
I think I found a bug in the MFC 7.1. There is an error during assignment of a LPWSTR to a CString in an MBCS or ANSI application. If you have something like this LPWSTR pWStr; // contains an WideString CString str; str = pWStr; // <- here is the bug In the third line the following member of CString is called: CStringT& operator=( PCYSTR pszSrc ) [cstringt.h, line 988] which calls GetBaseTypeLength [cstringt.h, line 429] This member returns the size of the pWStr (via WideCharToMultiByte) - 1. That means that the terminating NULL-character is not counted. So the reserved memory is too small to contain the whole pWStr including terminating NULL! In the following call of StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pszSrc ) in line 995 the destLengh doesn't include the NULL character. But ConvertToBaseType implicitly calls WideCharToMultiByte with the following parameters: ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSrc, -1, pszDest, nDestLength, NULL, NULL ); This function returns the error code 0, because the reserved memory in pszDest is one byte to small. To my mind this is an error in the MFCs. I only checked this in MFC 7.1. Please tell me, if you can reproduce the problem perhaps in other MFC version, too. Thanks in advance Konrad
-
I think I found a bug in the MFC 7.1. There is an error during assignment of a LPWSTR to a CString in an MBCS or ANSI application. If you have something like this LPWSTR pWStr; // contains an WideString CString str; str = pWStr; // <- here is the bug In the third line the following member of CString is called: CStringT& operator=( PCYSTR pszSrc ) [cstringt.h, line 988] which calls GetBaseTypeLength [cstringt.h, line 429] This member returns the size of the pWStr (via WideCharToMultiByte) - 1. That means that the terminating NULL-character is not counted. So the reserved memory is too small to contain the whole pWStr including terminating NULL! In the following call of StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pszSrc ) in line 995 the destLengh doesn't include the NULL character. But ConvertToBaseType implicitly calls WideCharToMultiByte with the following parameters: ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSrc, -1, pszDest, nDestLength, NULL, NULL ); This function returns the error code 0, because the reserved memory in pszDest is one byte to small. To my mind this is an error in the MFCs. I only checked this in MFC 7.1. Please tell me, if you can reproduce the problem perhaps in other MFC version, too. Thanks in advance Konrad
This isn't really a bug, just the developers leveraging how the API works. The string will come out correctly since WideCharToMultiByte will convert characters until the destination buffer fills up. This behavior is actually desired since the length passed for the source string may be shorter than the string. The developers could have resolved nSrcLength before making the call, but chose not to since the failure is quite irrelevant. The terminating null is taken care off by the GetBuffer() call, which reserves space for a terminating null. Anyone who thinks he has a better idea of what's good for people than people do is a swine. - P.J. O'Rourke
-
I think I found a bug in the MFC 7.1. There is an error during assignment of a LPWSTR to a CString in an MBCS or ANSI application. If you have something like this LPWSTR pWStr; // contains an WideString CString str; str = pWStr; // <- here is the bug In the third line the following member of CString is called: CStringT& operator=( PCYSTR pszSrc ) [cstringt.h, line 988] which calls GetBaseTypeLength [cstringt.h, line 429] This member returns the size of the pWStr (via WideCharToMultiByte) - 1. That means that the terminating NULL-character is not counted. So the reserved memory is too small to contain the whole pWStr including terminating NULL! In the following call of StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pszSrc ) in line 995 the destLengh doesn't include the NULL character. But ConvertToBaseType implicitly calls WideCharToMultiByte with the following parameters: ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSrc, -1, pszDest, nDestLength, NULL, NULL ); This function returns the error code 0, because the reserved memory in pszDest is one byte to small. To my mind this is an error in the MFCs. I only checked this in MFC 7.1. Please tell me, if you can reproduce the problem perhaps in other MFC version, too. Thanks in advance Konrad
The same code was VC6.. It causes read out of bound warning in BoundChecker & Purify, but also pretty harmless. Also note, if you change (via WideCharToMultiByte) - 1 to (via WideCharToMultiByte) you will break ATL CComBSTR, and may be some others.