diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index 51c648fe9..3b263fe22 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -1886,10 +1886,13 @@ bool convert_input_param_to_utf16( _In_ zval* input_param_z, _Inout_ zval* conve return true; } - // if the parameter is an input parameter, calc the size of the necessary buffer from the length of the string #ifndef _WIN32 + // Declare wchar_size to be the largest possible number of UTF-16 characters after + // conversion, to avoid the performance penalty of calling ToUtf16 wchar_size = buffer_len; #else + // Calculate the size of the necessary buffer from the length of the string - + // no performance penalty because MultiByteToWidechar is highly optimised wchar_size = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, reinterpret_cast( buffer ), static_cast( buffer_len ), NULL, 0 ); #endif // !_WIN32 @@ -1901,15 +1904,15 @@ bool convert_input_param_to_utf16( _In_ zval* input_param_z, _Inout_ zval* conve wbuffer = reinterpret_cast( sqlsrv_malloc( (wchar_size + 1) * sizeof( SQLWCHAR ) )); // convert the utf-8 string to a wchar string in the new buffer #ifndef _WIN32 - int r = SystemLocale::ToUtf16Strict( CP_UTF8, reinterpret_cast( buffer ), static_cast( buffer_len ), wbuffer, wchar_size ); + int rc = SystemLocale::ToUtf16Strict( CP_UTF8, reinterpret_cast( buffer ), static_cast( buffer_len ), wbuffer, wchar_size ); #else - int r = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, reinterpret_cast( buffer ), static_cast( buffer_len ), wbuffer, wchar_size ); + int rc = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, reinterpret_cast( buffer ), static_cast( buffer_len ), wbuffer, wchar_size ); #endif // !_WIN32 // if there was a problem converting the string, then free the memory and return false - if( r == 0 ) { + if( rc == 0 ) { return false; } - wchar_size = r; + wchar_size = rc; // null terminate the string, set the size within the zval, and return success wbuffer[ wchar_size ] = L'\0'; diff --git a/source/shared/core_util.cpp b/source/shared/core_util.cpp index 255f335a6..4aa2b37fd 100644 --- a/source/shared/core_util.cpp +++ b/source/shared/core_util.cpp @@ -127,10 +127,13 @@ bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_( flags = WC_ERR_INVALID_CHARS; } - // calculate the number of characters needed #ifndef _WIN32 + // Allocate enough space to hold the largest possible number of bytes for UTF-8 conversion + // instead of calling FromUtf16, for performance reasons cchOutLen = 4*cchInLen; #else + // Calculate the number of output bytes required - no performance hit here because + // WideCharToMultiByte is highly optimised cchOutLen = WideCharToMultiByte( encoding, flags, inString, cchInLen, NULL, 0, NULL, NULL ); @@ -156,11 +159,10 @@ bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_( } char* newString2 = reinterpret_cast( sqlsrv_malloc( rc + 1 /* NULL char*/ )); memset(newString2, '\0', rc+1); - memcpy_s(newString2, rc+1, newString, rc+1); + memcpy_s(newString2, rc, newString, rc); sqlsrv_free( newString ); *outString = newString2; - newString2[rc] = '\0'; // null terminate the encoded string cchOutLen = rc; return true;