Commit 49a6fd4
Fix unhandled exception in /getItem and /getTargetResult for items with illegal path characters (#12841)
### Context
`/getItem` and `/getTargetResult` throw an unhandled
`InvalidOperationException` when serializing items whose item specs
contain illegal path characters (e.g., compiler command line flags from
ClangTidy's `GetCompileCommands` target).
The JSON output formatter iterates over all metadata names including
built-in metadata like `FullPath`, `Directory`, etc. When
`GetMetadata()` is called on these, it attempts path computation which
fails for non-path item specs.
### Changes Made
- Wrapped metadata retrieval in `JsonOutputFormatter.cs` with try-catch
for `InvalidOperationException`
- Added `TryGetMetadata` and `TryGetMetadataValue` helper methods that
return empty string on failure
- Applied fix to all three affected methods:
`AddTargetResultsInJsonFormat`, `AddItemInstancesInJsonFormat`,
`AddItemsInJsonFormat`
- Exception handling catches all `InvalidOperationException` instances
to ensure compatibility across all locales (error messages are
localized)
### Testing
Added `GetTargetResultWithIllegalPathCharacters` test that verifies both
`/getTargetResult` and `/getItem` succeed with items containing compiler
flags as item specs.
### Notes
On Linux, the test shows the path-like metadata is still computed (since
`/` is valid in paths). On Windows, these would return empty strings.
The key fix is preventing the unhandled exception crash.
The exception handling is intentionally broad (catching all
`InvalidOperationException` without message filtering) to ensure the fix
works correctly in all locales, as error messages from MSBuild are
localized and checking for specific English text would fail in
non-English environments.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
----
*This section details on the original issue you should resolve*
<issue_title>[Unhandled Exception]: /getItem and /getTargetResult fail
for target GetCompileCommands</issue_title>
<issue_description>### Issue Description
There is an uncaught exception when trying to access certain information
from the GetCompileCommands target (from ClangTidy), in particular
`/getTargetResult:GetCompileCommands` and
`/getTargetResult:GetCompileCommands`
### Steps to Reproduce
[tidytest.zip](https://github.com/user-attachments/files/22645381/tidytest.zip)
Run either of the following commands (You could also run with target
`/t:ClangTidy` for the same result)
```
msbuild tidytest.vcxproj /t:GetCompileCommands /getTargetResult:GetCompileCommands
msbuild tidytest.vcxproj /t:GetCompileCommands /getItem:CompileCommands
```
I expect to get a json formatted target result or item.
### Actual Behavior
I get the following error when building
```
C:\Users\rp0656\source\repos\tidytest>msbuild tidytest.vcxproj /t:GetCompileCommands /getTargetResult:GetCompileCommands
MSBUILD : error MSB1025: An internal failure occurred while running MSBuild.
System.InvalidOperationException: The item metadata "%(FullPath)" cannot be applied to the path "/c /nologo /W3 /WX- /diagnostics:column /Od /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /permissive- /Fa"tidytest\x64\Debug\\" /Fo"tidytest\x64\Debug\\" /Gd --target=amd64-pc-windows-msvc /TP". Illegal characters in path.
at Microsoft.Build.Shared.ErrorUtilities.ThrowInvalidOperation(String resourceName, Object[] args)
at Microsoft.Build.Shared.FileUtilities.ItemSpecModifiers.GetItemSpecModifier(String currentDirectory, String itemSpec, String definingProjectEscaped, String modifier, String& fullPath)
at Microsoft.Build.Evaluation.BuiltInMetadata.GetMetadataValueEscaped(String currentDirectory, String evaluatedIncludeBeforeWildcardExpansionEscaped, String evaluatedIncludeEscaped, String definingProjectEscaped, String name, String& fullPath)
at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetBuiltInMetadataEscaped(String name)
at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadataEscaped(String metadataName)
at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadata(String metadataName)
at Microsoft.Build.CommandLine.JsonOutputFormatter.AddTargetResultsInJsonFormat(String[] targetNames, BuildResult result)
at Microsoft.Build.CommandLine.MSBuildApp.OutputBuildInformationInJson(BuildResult result, String[] getProperty, String[] getItem, String[] getTargetResult, ILogger[] loggers, ExitType exitType, TextWriter outputStream)
at Microsoft.Build.CommandLine.MSBuildApp.Execute(String commandLine)
Unhandled Exception: System.InvalidOperationException: The item metadata "%(FullPath)" cannot be applied to the path "/c /nologo /W3 /WX- /diagnostics:column /Od /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /permissive- /Fa"tidytest\x64\Debug\\" /Fo"tidytest\x64\Debug\\" /Gd --target=amd64-pc-windows-msvc /TP". Illegal characters in path.
at Microsoft.Build.Shared.ErrorUtilities.ThrowInvalidOperation(String resourceName, Object[] args)
at Microsoft.Build.Shared.FileUtilities.ItemSpecModifiers.GetItemSpecModifier(String currentDirectory, String itemSpec, String definingProjectEscaped, String modifier, String& fullPath)
at Microsoft.Build.Evaluation.BuiltInMetadata.GetMetadataValueEscaped(String currentDirectory, String evaluatedIncludeBeforeWildcardExpansionEscaped, String evaluatedIncludeEscaped, String definingProjectEscaped, String name, String& fullPath)
at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetBuiltInMetadataEscaped(String name)
at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadataEscaped(String metadataName)
at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadata(String metadataName)
at Microsoft.Build.CommandLine.JsonOutputFormatter.AddTargetResultsInJsonFormat(String[] targetNames, BuildResult result)
at Microsoft.Build.CommandLine.MSBuildApp.OutputBuildInformationInJson(BuildResult result, String[] getProperty, String[] getItem, String[] getTargetResult, ILogger[] loggers, ExitType exitType, TextWriter outputStream)
at Microsoft.Build.CommandLine.MSBuildApp.Execute(String commandLine)
at Microsoft.Build.CommandLine.MSBuildApp.Main()
```
### Analysis
The error suggests that it is trying to interpret the flags of the
compile commands as a path, which causes an error when it can't be
resolved. The function `%(FullPath)` is used, though it is not clear to
me exactly where, but my best guess is it used on a variable that is
supposed to just be the path to `cl`, but has been extended with flags.
See the clang tidy targets file at something similar to `C:\Program
Files\Microsoft Visual
Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.Cpp.ClangTidy.targets`
### Versions & Co...
</details>
- Fixes #12589
<!-- START COPILOT CODING AGENT TIPS -->
---
✨ Let Copilot coding agent [set things up for
you](https://github.com/dotnet/msbuild/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.
---------
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: JanProvaznik <[email protected]>
Co-authored-by: Jan Provazník <[email protected]>
Co-authored-by: YuliiaKovalova <[email protected]>1 parent 3a603fc commit 49a6fd4
File tree
2 files changed
+92
-3
lines changed- src
- MSBuild.UnitTests
- MSBuild
2 files changed
+92
-3
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
888 | 888 | | |
889 | 889 | | |
890 | 890 | | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
891 | 923 | | |
892 | 924 | | |
893 | 925 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
70 | | - | |
| 70 | + | |
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
111 | | - | |
| 111 | + | |
112 | 112 | | |
113 | 113 | | |
114 | 114 | | |
| |||
147 | 147 | | |
148 | 148 | | |
149 | 149 | | |
150 | | - | |
| 150 | + | |
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
| |||
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
162 | 219 | | |
163 | 220 | | |
0 commit comments