Unicorn with delicious cookie
Our website uses cookies to enhance your browsing experience.
Accept
to the top
>
>
>
V745. A 'wchar_t *' type string is inco…
menu mobile close menu
Analyzer diagnostics
General Analysis (C++)
General Analysis (C#)
General Analysis (Java)
Micro-Optimizations (C++)
Diagnosis of 64-bit errors (Viva64, C++)
Customer specific requests (C++)
MISRA errors
AUTOSAR errors
OWASP errors (C++)
OWASP errors (C#)
OWASP errors (Java)
Problems related to code analyzer
Additional information
toggle menu Contents

V745. A 'wchar_t *' type string is incorrectly converted to 'BSTR' type string.

Jan 19 2016

The analyzer has detected that a string of the wchar_t * type is handled as a string of the BSTR type, which is strange, and the code is very likely to be incorrect. To figure out why such string handling is dangerous, let's first recall what the BSTR type is.

We will quote the article from MSDN. It is important to understand the danger behind errors of this type, and the V745 diagnostic rule indicates serious errors in most cases.

typedef wchar_t OLECHAR;
typedef OLECHAR * BSTR;

A BSTR (Basic string or binary string) is a string data type that is used by COM, Automation, and Interop functions. Use the BSTR data type in all interfaces that will be accessed from script.

  • A length prefix. A four-byte integer that contains the number of bytes in the following data string. It appears immediately before the first character of the data string. This value does not include the terminal null character.
  • A data string. A string of Unicode characters. May contain multiple nested null characters.
  • A terminator. Two null characters.

A BSTR is a pointer that points to the first character of the data string, not to the length prefix.

BSTRs are allocated using COM memory allocation functions, so they can be returned from methods without the need to control memory allocation.

The following code is incorrect:

BSTR MyBstr = L"I am a happy BSTR";

This code builds (compiles and links) correctly, but it will not function properly because the string does not have a length prefix. If you use a debugger to examine the memory location of this variable, you will not see a four-byte length prefix preceding the data string.

Instead, use the following code:

BSTR MyBstr = SysAllocString(L"I am a happy BSTR");

A debugger that examines the memory location of this variable now reveals a length prefix containing 34. This is the expected value for a 17-byte single-character string that is converted to a wide-character string through the inclusion of the "L" string modifier. The debugger also shows a two-byte terminal null character (0x0000) that appears after the data string.

If you pass a simple Unicode string as an argument to the COM function that is expecting a BSTR, the COM function will fail.

Note. The analyzer cannot accurately determine whether the error exists in the code. If an incorrect BSTR string is passed somewhere outside the code, it will cause a failure. However, if a BSTR string is cast back to wchar_t *, it is fine.

Here is an example of such code:

wchar_t *wstr = Foo();
BSTR tmp = wstr;
wchar_t *wstr2 = tmp;

There's no real error here, but this code still "smells" and has to be fixed. Doing so will cause less confusion for future maintainers and will prevent the analyzer from issuing a warning. The correct data types should be used:

wchar_t *wstr = Foo();
wchar_t *tmp = wstr;
wchar_t *wstr2 = tmp;

We also recommend reading the sources mentioned at the end of the article. They will help understand BSTR strings and how to cast them to other string types.

Here's another example:

wchar_t *wcharStr = L"123";
wchar_t *foo = L"12345";
int n = SysReAllocString(&wcharStr, foo);

This is the description of the SysReAllocString function:

INT SysReAllocString(BSTR *pbstr, const OLECHAR *psz);

It allocates a new BSTR and copies the given string into it. Then, it frees the BSTR to which pbstr points and places a pointer to the new BSTR at that address.

The function expects a pointer to a variable containing the address of a string in BSTR format as the first argument. Instead, it receives a pointer to an ordinary string. Since the wchar_t ** type is actually the same thing as BSTR *, the code compiles correctly. In reality, however, it doesn't make sense and causes a runtime error.

The fixed version of the code:

BSTR wcharStr = SysAllocString(L"123");
wchar_t *foo = L"12345";
int n = SysReAllocString(&wcharStr, foo);

A special case is when the auto keyword is used. The analyzer issues a warning for the following harmless code:

auto bstr = ::SysAllocStringByteLen(foo, 3);
ATL::CComBSTR value;
value.Attach(bstr);  // Warning: V745

This is a false positive, but the analyzer is technically correct when issuing the warning. The bstr variable is of the wchar_t * type. When deducing the type of the auto variable, the C++ compiler does not consider that the function returns a value of the BSTR type. When deducing auto, the BSTR type is simply a synonym of whar_t *. This means that the code above is equivalent to this:

wchar_t *bstr = ::SysAllocStringByteLen(foo, 3);
ATL::CComBSTR value;
value.Attach(bstr);

This is why the PVS-Studio analyzer issues the warning: it is not recommended to store a pointer to a BSTR string in a standard wchar_t * pointer. To eliminate the warning, explicitly specify the type instead of using auto here:

BSTR *bstr = ::SysAllocStringByteLen(foo, 3);
ATL::CComBSTR value;
value.Attach(bstr);

This is an interesting case when the auto operator does not help, but instead loses type information and makes things worse.

Another way to eliminate the warning is to use one of the false-positive suppression mechanisms described in the documentation.

References:

This diagnostic is classified as:

You can look at examples of errors detected by the V745 diagnostic.

close form

Fill out the form in 2 simple steps below:

Your contact information:

Step 1
Congratulations! This is your promo code!

Desired license type:

Step 2
Team license
Enterprise license
** By clicking this button you agree to our Privacy Policy statement
close form
Request our prices
New License
License Renewal
--Select currency--
USD
EUR
* By clicking this button you agree to our Privacy Policy statement

close form
Free PVS‑Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

close form
To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

close form
I want to join the test
* By clicking this button you agree to our Privacy Policy statement

close form
check circle
Message submitted.

Your message has been sent. We will email you at


If you do not see the email in your inbox, please check if it is filtered to one of the following folders:

  • Promotion
  • Updates
  • Spam