Made the isExpandedFromMacro matcher work on Stmt's, TypeLocs and Decls in line with the other macro expansion matchers.
Also tweaked it to take a std::string instead of a StringRef.
This prevents potential use-after-free bugs if the matcher is created with a string thats destroyed before the matcher finishes matching.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Time | Test | |
---|---|---|
370 ms | linux > HWAddressSanitizer-x86_64.TestCases::sizes.cpp |
Event Timeline
clang/include/clang/ASTMatchers/ASTMatchers.h | ||
---|---|---|
313 | You mentioned that the change from StringRef to std::string was to avoid lifetime issues while matching, but I'm wondering if you can expound on that situation a bit more. I would have assumed that any memoization that involves StringRef would be responsible for the lifetime issues rather than the matchers themselves, but maybe I'm thinking about a different way you can hit lifetime issues than you are. | |
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp | ||
150 | Can you also add a test for type-based matching? |
clang/include/clang/ASTMatchers/ASTMatchers.h | ||
---|---|---|
313 | Take this as contrived, however using ASAN reports a heap-use-after-free for this code when isExpandedFromMacro takes a StringRef but works fine when using std::string. TEST(IsExpandedFromMacro, IsExpandedFromMacro_MatchesDecls) { auto Matcher = isExpandedFromMacro(std::string("MY_MACRO_OVERFLOW_SMALL_STRING_SIZE"));// <-Temporary string created and destroyed here. StringRef input = R"cc( #define MY_MACRO_OVERFLOW_SMALL_STRING_SIZE(a) int i = a; void Test() { MY_MACRO_OVERFLOW_SMALL_STRING_SIZE(4); } )cc"; EXPECT_TRUE(matches(input, varDecl(Matcher))); // <- heap-use-after-free detected down the callstack from here. } Obviously this is very contrived to ensure asan detects the use-after-free and to ensure the temporary string is destroyed before the matcher. For these tests it doesn't look like a problem, but in other instances these matchers will outlive a string being passed to them void addVarFromMacro(ASTMatchFinder* Finder, std::string MacroName) { Finder->addMatcher(varDecl(isExpandedFromMacro(MacroName)), this); } |
LGTM aside from testing request.
clang/include/clang/ASTMatchers/ASTMatchers.h | ||
---|---|---|
313 | Oh, how interesting! I can see now where the lifetime issues come in to play, thanks! |
You mentioned that the change from StringRef to std::string was to avoid lifetime issues while matching, but I'm wondering if you can expound on that situation a bit more. I would have assumed that any memoization that involves StringRef would be responsible for the lifetime issues rather than the matchers themselves, but maybe I'm thinking about a different way you can hit lifetime issues than you are.