-
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
Detect whitespace in property name #5672
Conversation
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.
Thanks for these changes! Would you mind making it more general by including all invalid characters rather than just whitespace?
Looking at the error, you might need to target it more precisely when someone uses property functions. |
Thank you both for the feedback! Taken most of your remarks into account, now working on
|
I have looked around a bit in docs and code, but I could not find such a list. What would you consider invalid characters? https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-special-characters?view=vs-2019? |
@danmosemsft, is there a list somewhere of all the invalid characters? |
I think this is the check to use: msbuild/src/Shared/XmlUtilities.cs Lines 118 to 129 in 091189a
|
Hmmm
It fails on the dot |
Good point. Maybe exclude Unless you have nested properties/items, in which case also @, $, %, (, and )... And also |
Including these extra valid character checks is failing a lot of tests, and the scope of the original PR is also quite larger than initially. There is an added perf consideration as well with this as mentioned in |
I would limit the fix to just whitespace since that’s the common mistake. I haven’t looked at the code recently, but there should be a place in the parser/scanner where encountering a close paren would complete a property name; in that place, it should reject space. |
We noticed that this only runs when looking at properties inside conditions. Would you mind making it work for all properties? After that, I think it's good. |
Could you please share an example of such a property that I could use as a test case? I may be wrong, but my understanding is that the whitespace check here is done from |
This is supposed to throw an error when seeing whitespace in a property correct? I'm not seeing it (for properties inside or outside conditions), unless you have to build a specific way? I tried building a bootstrap of this PR and building this (taken from #5615):
Output when using standard
No error is being thrown. Same for building within a test:
Am I missing something? |
AdvanceToScannerError(lexer); | ||
Assert.Equal("IllFormedPropertyWhitespaceInCondition", lexer.GetErrorResource()); | ||
|
||
lexer = new Scanner("$( x)", ParserOptions.AllowProperties); |
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 it worth adding a test for "$(x yz" and "$(x y z")?
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.
do you really mean "$(x yz" and "$(x y z")
or actually "$(x yz)" and "$(x y z)"
?
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.
The latter 😊
Thanks for your message.
Yes.
Indeed, I observe the same behavior with running
For me it works when building within a unit test e624312, I can't explain yet why this test passes but
|
Interesting! So this is actually far more complicated than I'd imagined when I last commented here. Your unit test works unless you put quotes around the property, i.e.,
Noting that there are also quotes around every instance in which @benvillalobos used a malformed property, I suspect that this doesn't look inside strings, and that there are two ways MSBuild handles properties. (Why? I have no idea.) We may have to talk internally about what the best way forward is. I would say this PR is a clear improvement on what previously existed, but on the other hand, it doesn't cover all cases, and I don't know the easiest way to extend it to cover all cases. I imagine you could put something in Expander.cs to look at properties as they're expanded, but I don't think there's an easy way (or any way?) to get the position of the space in that case. |
@Forgind any updates from your internal discussions about this one? Would love to hear about what you've discovered. |
After talking it over, we think it best to take it roughly as-is. We think it should go behind a change wave (talk to @benvillalobos if you need help with that), and we should change the error code to something that isn't taken, but otherwise, this is about the best we can do. Does that sound reasonable to you, @mfkl? |
src/Build/Resources/Strings.resx
Outdated
<value>MSB4151: Unexpected whitespace at position "{1}" of condition "{0}". Did you forget to remove a whitespace?</value> | ||
<comment>{StrBegin="MSB4151: "}</comment> |
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.
<value>MSB4151: Unexpected whitespace at position "{1}" of condition "{0}". Did you forget to remove a whitespace?</value> | |
<comment>{StrBegin="MSB4151: "}</comment> | |
<value>MSB4259: Unexpected whitespace at position "{1}" of condition "{0}". Did you forget to remove a whitespace?</value> | |
<comment>{StrBegin="MSB4259: "}</comment> |
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.
(4151 was deprecated, but we should still avoid reusing error codes so people can search for them effectively online.)
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.
Ok
On change waves, here's a dev doc: https://github.com/dotnet/msbuild/blob/master/documentation/wiki/ChangeWaves-Dev.md any feedback on it would be appreciated! |
Thanks! I guess the doc is clear, though my initial reaction when reading it was "why was the opt-out strategy chosen over opt-in?". I picked |
Thanks for the feedback!
Fair question. Part of the drive for that is understanding the impact for some of these changes. If we hit a particularly hot path, it allows us to reevaluate the situation knowing that folks have a way out. It also gives us a better picture of how MSBuild is being used.
|
src/Build.UnitTests/Scanner_Tests.cs
Outdated
using TestEnvironment env = TestEnvironment.Create(); | ||
env.SetChangeWave(ChangeWaves.Wave17_0); | ||
|
||
Scanner lexer = new Scanner("$(x )", ParserOptions.AllowProperties); | ||
AdvanceToScannerError(lexer); | ||
Assert.Null(lexer.UnexpectedlyFound); | ||
|
||
lexer = new Scanner("$( x)", ParserOptions.AllowProperties); | ||
AdvanceToScannerError(lexer); | ||
Assert.Null(lexer.UnexpectedlyFound); |
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.
using TestEnvironment env = TestEnvironment.Create(); | |
env.SetChangeWave(ChangeWaves.Wave17_0); | |
Scanner lexer = new Scanner("$(x )", ParserOptions.AllowProperties); | |
AdvanceToScannerError(lexer); | |
Assert.Null(lexer.UnexpectedlyFound); | |
lexer = new Scanner("$( x)", ParserOptions.AllowProperties); | |
AdvanceToScannerError(lexer); | |
Assert.Null(lexer.UnexpectedlyFound); | |
using (TestEnvironment env = TestEnvironment.Create()) | |
{ | |
env.SetChangeWave(ChangeWaves.Wave17_0); | |
Scanner lexer = new Scanner("$(x )", ParserOptions.AllowProperties); | |
AdvanceToScannerError(lexer); | |
Assert.Null(lexer.UnexpectedlyFound); | |
lexer = new Scanner("$( x)", ParserOptions.AllowProperties); | |
AdvanceToScannerError(lexer); | |
Assert.Null(lexer.UnexpectedlyFound); | |
} |
Having TestEnvironment
call Dispose
resets state for CI builds.
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.
The previous way actually calls Dispose, too, when env goes out of scope, and I think it's technically recommended, although it isn't something we use in MSBuild particularly.
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 can change it back to the old syntax if you folks prefer.
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.
So long as dispose is called I'm okay with its current state 👍
I'd suggest moving to an earlier wave, probably 16.8 or 16.10. We don't expect this to cause a problem 99% of the time, but someone theoretically could have properties with spaces that silently return empty strings and work around that, in which case this could break their build. If it were opt-in, we wouldn't find any customers like that, and we would never know whether there actually is anyone who relies on properties with spaces being turned into empty strings. |
Oh whoops, I meant |
src/Build/Resources/Strings.resx
Outdated
@@ -490,6 +490,10 @@ | |||
<value>MSB4110: Expected a property at position {1} in condition "{0}". Did you forget the opening parenthesis after the '$'? To use a literal '$', use '%24' instead.</value> | |||
<comment>{StrBegin="MSB4110: "}</comment> | |||
</data> | |||
<data name="IllFormedPropertyWhitespaceInCondition" xml:space="preserve"> | |||
<value>MSB4259: Unexpected whitespace at position "{1}" of condition "{0}". Did you forget to remove a whitespace?</value> |
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.
Nit, I don't think we normally would say a whitespace
. Maybe a space
. Suggest just ...forget to remove whitespace?
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.
LGTM! Thanks!
I'm having trouble analyzing the CI result, I can't find what is failing exactly or why. Is it something I did? |
Doesn't look like it. I kicked off a new run. Since it was mono that failed, I'm guessing this flakiness will be fixed by #5831. |
Thanks, @mfkl! |
Thanks for the change @mfkl |
Attempt at #5615
Any feedback welcome.