SAL annotation updates & fix warnings#5617
SAL annotation updates & fix warnings#5617TravisEz13 merged 3 commits intoPowerShell:masterfrom dantraMSFT:dantra/codeanalysis
Conversation
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.
|
Note that the |
|
@dantraMSFT Can you please investigate test failures? |
|
@TravisEz13: The failures in these two runs are unrelated to the change; they are timing issues. I've created #5627 to track the issue. |
|
I've restarted windows and mac CI. |
|
@daxian-dbw: I don't expect to be able to get the nuget package signed and published before I leave for vacation (EOD today). |
|
@SteveL-MSFT @TravisEz13 Can you please reivew this PR to see if it's needed for RC2 or GA? |
|
|
||
| if (NULL != pwszMonadVersion) | ||
| { | ||
| pwszMonadVersion = NULL; |
There was a problem hiding this comment.
The two check above are assigning NULL to *<pointer> while this one is not. Is it intentional?
|
@mirichmo Can you please review this PR? |
|
|
||
| DWORD ReportOperationComplete(WSMAN_PLUGIN_REQUEST *requestDetails, DWORD errorCode) | ||
| { | ||
| WCHAR szMessage[256] = L"\0"; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
There is an assignment missing, which I'll add in the next commit; szMessage is used when GetFormmatedMessage fails.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
This change will conditionally leak memory. If pwszErrorMessage has a value, it was allocated by GetFormattedErrorMessage and must be freed (via delete[]).
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
This comment seems unnecessary. The behavior is documented in the class definition.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
This already occurs on line 671. It seems unnecessary to do it twice. Did the scanner require it?
There was a problem hiding this comment.
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. */ |
There was a problem hiding this comment.
Comment seems unnecessary here too
| result = WSManPluginOperationComplete(requestDetails, 0, errorCode, pwszErrorMessage); | ||
|
|
||
| if (NULL != pwszErrorMessage) | ||
| if (NULL != pwszErrorMessage && pwszErrorMessage != szMessage) |
There was a problem hiding this comment.
This has not been resolved yet.
|
|
||
| DWORD ReportOperationComplete(WSMAN_PLUGIN_REQUEST *requestDetails, DWORD errorCode) | ||
| { | ||
| WCHAR szMessage[256] = L"\0"; |
There was a problem hiding this comment.
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.
|
@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"; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
Update GetFormattedErrorMessage to ensure all error paths return dwLength = 0
|
@mirichmo, @SteveL-MSFT |
My comment #5617 (comment) has been addressed
|
@dantraMSFT Can you open an issue to publish a new package before I merge this so we don't lose the work? |
|
@TravisEz13 See #5802 |
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.
The following changes address all code analysis warnings: