Yesterday I was a bit distracted by loop pragma parsing (D64471), but still am a bit today too (this patch).
Details
Diff Detail
Event Timeline
clang/lib/Parse/ParsePragma.cpp | ||
---|---|---|
1015 | I guess this does behave slightly different, i.e. the assert in a release build. Before, in a release build, "unroll" was returned for an unexpected pragma, but now we return the empty string "". |
clang/lib/Parse/ParsePragma.cpp | ||
---|---|---|
1009–1017 | getName() returns StringRef. No need to use a std::string yet. | |
1011–1014 | This unconditionally creates (at least) 5 std::string objects. | |
1041–1046 | [style] We don't use const for local variables. Could also use auto here since the type is already explicit on the RHS. [suggestion] IsLoopHint would indicate the meaning of the boolean variable. |
lib/Parse/ParsePragma.cpp | ||
---|---|---|
1011 ↗ | (On Diff #209299) | [serious] I know I already accepted the patch, but I just noticed something: |
lib/Parse/ParsePragma.cpp | ||
---|---|---|
1011 ↗ | (On Diff #209299) | Oopsy, thanks for spotting this! Will fix this! |
clang/lib/Parse/ParsePragma.cpp | ||
---|---|---|
1010 | [serious] Use-after-free here again. This line will do the following: StringRef ClangLoopStr; { std::string tmp = "clang loop " + Str.str() ClangLoopStr = tmp; // tmp.~string() } // Any use of ClangLoopStr will use memory released by tmp.~string() Let me suggest a solution: std::string ClangLoopStr = (Twine("clang loop ") + Str).str(); std::string Result = llvm::StringSwitch<StringRef>(Str) .Case("loop", ClangLoopStr) .Case("unroll_and_jam", Str) .Case("unroll", Str) .Default(""); return Result; // NRVO, ClangLoopStr will be released here, but if it was chosen by the StringSwitch, Result will hold a copy, so ClangLoopStr is not referenced anymore. Note that this will alloc one more std::string in the non-ClangLoopStr cases than before the patch, but I don't think it's important. |
Sorry, should have done my std::string, StringRef, and Twine homework a lot better!
Thanks for your help and suggestions, will fix this.
clang/lib/Parse/ParsePragma.cpp | ||
---|---|---|
1010 | [nit] I am surprised it works without llvm:: qualifier for llvm::Twine. Maybe add it for consistency? | |
1016 | [nit] One could just return llvm::StringSwitch... without a Result variable. I used it in the suggestion so I could comment on what happens when returning. Personally, there is nothing that I could care less about, so use what you prefer. |
[serious] Use-after-free here again. This line will do the following:
Let me suggest a solution:
Note that this will alloc one more std::string in the non-ClangLoopStr cases than before the patch, but I don't think it's important.