-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Throw exception or log warning upon drive enumeration glob anomaly detection #7029
Throw exception or log warning upon drive enumeration glob anomaly detection #7029
Conversation
|
227c2d8
to
67a278b
Compare
67a278b
to
dd3c05d
Compare
I hadn't really properly looked at what you were trying to do here before, but @ladipro made a similar PR here that prevented drive enumerations when the condition was false specifically. It would probably be easy to glom onto that to achieve what you're trying to do here—but although drive enumerations are probably not intended, this might be a bit much of a breaking change for 17.1. Might be good enough with a change wave? Not sure. |
@Forgind @ladipro Right, that PR did alleviate drive enumerations, according to #3642 (comment), but this was an attempt to improve logging and surface an exception. Is this necessary given the following that was already completed in #5669, or does the existing logging below not surface all the way to the user?
|
Users can get that information, but they have to specifically ask for it and almost always will not. I doubt anyone would find it unless they specifically looked. |
@mruxmohan-msft I'm afraid that requiring an opt-in via the We should try to come up with a solution which we can enable by default, while causing little-to-no pain to users who enumerate full drives intentionally. Perhaps a build warning would be acceptable as along as it:
|
1c53298
to
9163404
Compare
src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs
Outdated
Show resolved
Hide resolved
src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs
Outdated
Show resolved
Hide resolved
src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs
Outdated
Show resolved
Hide resolved
src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is starting to look great! I pointed out many smaller nits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not reviewed all files yet but I may not have more time today so publishing what I have. Overall I think the changes look great.
bool excludeFileSpecIsUnusable = string.IsNullOrWhiteSpace(excludeFileSpec); | ||
string fileSpec = excludeFileSpecIsUnusable ? filespecUnescaped : excludeFileSpec; | ||
|
||
switch (action) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a more optimal way to clean up the logic within these switch statements? I tried to reduce as many lines of code as possible.
Also, are the conditions correct? I want to make certain that I'm not causing any false positive/negative warnings or errors (in spite of test coverage), in addition to having the wrong attributes and elements associated with the warnings/errors (are there preferred ways to include specific metadata in tests without checking for particular messages contained in logs, as those may change over time?). This section might be more clear once I complete test cleanup and add more inline data in ProjectItem_Tests.cs
and ProjectItemInstance_Tests.cs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a more optimal way to clean up the logic within these switch statements? I tried to reduce as many lines of code as possible.
Just a few random ideas:
- You could try to flatten the code to have only one switch with pattern matching. Something like: https://dotnetfiddle.net/DUHvNn
- Or maybe it would be better to refactor the inner switches into their own helper method each.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC I started experimenting with approach 1 for this problem and didn't like where I wound up, so I think I'd lean toward approach 2, @mruxmohan4. In the general case I like 1 better though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked to see if this is viable in this case, but it can sometimes be fairly clean to have two separate switches, one to select relevant arguments and one to select a delegate to apply to them. Then you can just apply it at the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went ahead with approach 2 to make it less clunky in the inner switch statements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left a few comments inline, mostly nits.
bool excludeFileSpecIsUnusable = string.IsNullOrWhiteSpace(excludeFileSpec); | ||
string fileSpec = excludeFileSpecIsUnusable ? filespecUnescaped : excludeFileSpec; | ||
|
||
switch (action) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a more optimal way to clean up the logic within these switch statements? I tried to reduce as many lines of code as possible.
Just a few random ideas:
- You could try to flatten the code to have only one switch with pattern matching. Something like: https://dotnetfiddle.net/DUHvNn
- Or maybe it would be better to refactor the inner switches into their own helper method each.
bool excludeFileSpecIsUnusable = string.IsNullOrWhiteSpace(excludeFileSpec); | ||
string fileSpec = excludeFileSpecIsUnusable ? filespecUnescaped : excludeFileSpec; | ||
|
||
switch (action) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC I started experimenting with approach 1 for this problem and didn't like where I wound up, so I think I'd lean toward approach 2, @mruxmohan4. In the general case I like 1 better though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really more of a quick pass than a full review, but it sounded like rainersigwald gave more complete comments.
src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs
Show resolved
Hide resolved
e1dfd32
to
6d537b8
Compare
0018d75
to
ad7ab8d
Compare
ad7ab8d
to
afdbfc1
Compare
Fixes #7029 by associating a file location string with the WildcardResultsInDriveEnumeration resource name. Context For https://github.com/dotnet/project-system/blob/main/build/import/Workarounds.targets#L8, it was difficult to detect the location at which the drive enumerating wildcard pattern was occurring even though a warning was logged, since 1) there was no location string added to the warning, and 2) the Exclude rather than the Remove element was shown in the warning. To resolve 1), it would be better to associate the location string with the WildcardResultsInDriveEnumeration resource name. Changes Made Added location string to the WildcardResultsInDriveEnumeration resource name in order to view the location for drive enumerating wildcard warnings and errors. Testing Modified ProjectItem, ObjectModelHelper (for ProjectItemInstance), and CreateItem unit tests to ensure that the project file location was placed in the warning or error message. Notes Any <i Remove=<drive enumerating wildcard> /> will still be considered as an Exclude attribute in the warning or error message, since is treated as equivalent to <Foo Include=... Exclude=... />, which still makes the warning or error message slightly unclear for drive enumerating wildcard used in Remove cases. However, the wildcarded value will still be caught and logged/thrown based on whether the environment variable is set.
Context
Glob anomalies drive enumeration issue: #3642 (comment). Properties that evaluate to empty result in drive enumeration.
Changes Made
Logs an error via
ProjectFileErrorUtilities.ThrowInvalidProject(...)
with the resource name WildcardResultsInDriveEnumeration when\**
,<drive>:\**
, or<drive>:<any number of slashes>**
are detected on the leftmost side while parsing and the environment variableMSBUILDFAILONDRIVEENUMERATINGWILDCARD
is set to 1 (with the exception of one case listed in "Notes" below which simply logs an error). Note that a warning is logged (rather than an error) with the same resource name when the environment variable is set to 0.Regarding more recent changes, logging a warning/throwing an
InvalidProjectFileException
has become more unified and placed in EngineFileUtilities.cs. Logging a warning/throwing an exception with the resource name requires extra information, including aSearchAction
andExcludeFileSpec
, which are returned from FileMatcher into various codepaths (CreateItem & EngineFileUtilities), which obtain additional parameters from other codepaths, such as Evaluator, Expander, ItemGroupIntrinsicTask, LazyItemEvaluator.IncludeOperation, etc., to better identify the logging mechanism and attributes that should be passed to EngineFileUtilities.cs upon logging a warning/throwing an exception. There is no custom exception that is caught and then converted into anInvalidProjectFileException
(all of the functionality that came with a custom exception has been removed with a prior commit for these changes). When the env var is set to 1, a nearly immediate return from functions occurs, as we want the build to fail and throw upon detection of a drive enumerating wildcard.Testing
Larger integration tests with empty properties/imports were created to trigger the issue in targets. Smaller tests in FileMatcher_Tests.cs were created to check for particular wildcard patterns that should result in the custom exception being thrown.
Unit tests were added to: FileMatcher_Tests.cs, ProjectItem_Tests.cs, CreateItem_Tests.cs, and ProjectItemInstance_Tests.cs.
Notes
MSB5029
error code (see shared resx).ProjectFileErrorUtilities.ThrowInvalidProject(...)
WildcardResultsInDriveEnumeration
to pass on element locations toInvalidProjectFileException.