Skip to content

Conversation

@dantraMSFT
Copy link
Contributor

@dantraMSFT dantraMSFT commented Dec 4, 2017

Various SAL annotations were either incorrect or not backed up by code. This PR address these issues.

NOTE: By default, Start-BuildNativeWindowsBinaries does not enable code analysis and issues detected by SAL annotations are not reported. To identify these issues, run Start-BuildNativeWindowsBinaries to generate the solution and vcxproj files. Launch a Visual Studio developer prompt, cd to src\powershell-native and run msbuild manually.

msbuild PowerShellNative.sln /p:RunCodeAnalysis=true /p:Configuration=RelWithDebInfo /p:Platform=x64

The following changes address all code analysis warnings:

  • GetRegistryInfo in NativeMsh had incorrect out annotations, remove __opt
  • Fix handling of various out parameters - check for non-null and initialize
  • Update and Align SAL annotations for GetFormattedErrorMessage overloads
  • Allow PluginException to accept NULL message.

GetRegistryInfo in NativeMsh had incorrect out annotations, remove __opt
Fix handling of various out parameters - check for non-null and initialize
Udpate and Align  SAL annotations for GetFormattedErrorMessage overloads
Allow PluginException to accept NULL message.
@daxian-dbw
Copy link
Member

Note that the psrp.windows nuget package needs to be regenerated. Make sure that the binaries are signed before using them to create the nuget package.

@TravisEz13
Copy link
Member

@dantraMSFT Can you please investigate test failures?

@dantraMSFT
Copy link
Contributor Author

@TravisEz13: The failures in these two runs are unrelated to the change; they are timing issues. I've created #5627 to track the issue.

@TravisEz13
Copy link
Member

I've restarted windows and mac CI.

@dantraMSFT
Copy link
Contributor Author

@daxian-dbw: I don't expect to be able to get the nuget package signed and published before I leave for vacation (EOD today).

@daxian-dbw
Copy link
Member

@SteveL-MSFT @TravisEz13 Can you please reivew this PR to see if it's needed for RC2 or GA?


if (NULL != pwszMonadVersion)
{
pwszMonadVersion = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two check above are assigning NULL to *<pointer> while this one is not. Is it intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@daxian-dbw
Copy link
Member

@mirichmo Can you please review this PR?


DWORD ReportOperationComplete(WSMAN_PLUGIN_REQUEST *requestDetails, DWORD errorCode)
{
WCHAR szMessage[256] = L"\0";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you make this code change? It looks unnecessary and potentially error-prone.

It is incorrect to provide a fixed-length buffer for the error string. The string is read from pwrshplugin.dll and may be of any length. GetFormattedErrorMessage correctly handles the arbitrary length, but this change will potentially truncate it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an assignment missing, which I'll add in the next commit; szMessage is used when GetFormmatedMessage fails.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assignment does not address my comment. This change is fundamentally flawed because it will potentially truncate the string. I do not see a benefit over the original code.

result = WSManPluginOperationComplete(requestDetails, 0, errorCode, pwszErrorMessage);

if (NULL != pwszErrorMessage)
if (NULL != pwszErrorMessage && pwszErrorMessage != szMessage)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change will conditionally leak memory. If pwszErrorMessage has a value, it was allocated by GetFormattedErrorMessage and must be freed (via delete[]).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has not been resolved yet.

PWSTR msg = NULL;
exitCode = g_MANAGED_METHOD_RESOLUTION_FAILED;
GetFormattedErrorMessage(&msg, exitCode);
/* NOTE: dont' use a string literal for a fallback; PlugInException expects msg to allocated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems unnecessary. The behavior is documented in the class definition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this comment because the constructor annotations were wrong and, since the return value of GetFormmatedErrorMessage was being ignored, I added the comment to document the behavior as intentional.

{
iMajorVersion = iVPSMajorVersion;

if (NULL != wszMgdPlugInFileName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This already occurs on line 671. It seems unnecessary to do it twice. Did the scanner require it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is added because wszMgdPlugInFileName was not being set in all paths; specifically error paths.

GetFormattedErrorMessage(&msg, g_OPTION_SET_NOT_COMPLY, g_BUILD_VERSION);
(void) GetFormattedErrorMessage(&msg, g_OPTION_SET_NOT_COMPLY, g_BUILD_VERSION);
/* NOTE: Passing possible NULL msg. PlugInExpecption requires allocated
or NULL. Literal strings are not supported. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment seems unnecessary here too

@SteveL-MSFT SteveL-MSFT added this to the 6.1.0-MQ milestone Dec 7, 2017
@TravisEz13 TravisEz13 changed the title SAL annotation updates and fix warnings SAL annotation updates & fix warnings Dec 8, 2017
result = WSManPluginOperationComplete(requestDetails, 0, errorCode, pwszErrorMessage);

if (NULL != pwszErrorMessage)
if (NULL != pwszErrorMessage && pwszErrorMessage != szMessage)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has not been resolved yet.


DWORD ReportOperationComplete(WSMAN_PLUGIN_REQUEST *requestDetails, DWORD errorCode)
{
WCHAR szMessage[256] = L"\0";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assignment does not address my comment. This change is fundamentally flawed because it will potentially truncate the string. I do not see a benefit over the original code.

@dantraMSFT
Copy link
Contributor Author

dantraMSFT commented Dec 20, 2017

@mirichmo: If you take a look at the code again, you'll see that szMessage is used to populate a placeholder error when when GetFormattedErrorMessage fails. It does not truncate an arbitrary error string.

As far as a possible leak, there isn't one.

When GetFormattedErrorMessage returns zero; pwszErrorMessage is null and, szMessage is used instead; thus, the delete call only frees memory when pwszErrorMessage is non-null and not szMessage.

Are you seeing something that I have missed?


DWORD ReportOperationComplete(WSMAN_PLUGIN_REQUEST *requestDetails, DWORD errorCode)
{
WCHAR szMessage[256] = L"\0";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After talking to Dan, szMessage contains a default error message in the case where the actual error message can't be allocated. So szMessage should be called something else like szFallbackErrorMessage making this more clear. Second, the 256 bytes is arbitrary. Since we know the max length based on line 315 below, we should only allocate that much.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.
Note that I left the stack buffer at 64.

if (GetFormattedErrorMessage(&pwszErrorMessage, errorCode) == 0)
{
swprintf_s(szMessage,_countof(szMessage), L"ReportOperationComplete: %d", errorCode);
pwszErrorMessage = szMessage;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps for readability of the code, it would be better to change this to call WSManPluginOperationComplete with szMessage and else use pwszErrorMessage?

This would also remove the change on line 321 below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Update GetFormattedErrorMessage to ensure all error paths return dwLength = 0
@dantraMSFT
Copy link
Contributor Author

@mirichmo, @SteveL-MSFT
I've updated ReportOperationComplete to clarify the stack buffer usage.
After another review, I found that GetFormattedErrorMessage was still not reliably returning zero for all error paths. I've rewritten it to be explicit in each case and avoid the nested If statements by leveraging the existing do/while(false) construct and moving the localfree call for wszSystemErrorMessage to the end of the function.

@daxian-dbw daxian-dbw dismissed their stale review January 4, 2018 05:06

My comment #5617 (comment) has been addressed

@TravisEz13
Copy link
Member

@dantraMSFT Can you open an issue to publish a new package before I merge this so we don't lose the work?

@dantraMSFT
Copy link
Contributor Author

@TravisEz13 See #5802

@TravisEz13 TravisEz13 merged commit da5d897 into PowerShell:master Jan 6, 2018
@dantraMSFT dantraMSFT deleted the dantra/codeanalysis branch March 8, 2018 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants