- Notifications
You must be signed in to change notification settings - Fork 15.3k
[clang-tidy] Add recursion protection in ExceptionSpecAnalyzer #66810
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
[clang-tidy] Add recursion protection in ExceptionSpecAnalyzer #66810
Conversation
| @llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy ChangesNormally endless recursion should not happen in ExceptionSpecAnalyzer, but if AST would be malformed (missing include), this could cause crash. I run into this issue when due to missing include constructor argument were parsed as FieldDecl. Full diff: https://github.com/llvm/llvm-project/pull/66810.diff 1 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp index 4dd4a95f880aca0..5ffa4a92f574e0b 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp @@ -14,13 +14,14 @@ namespace clang::tidy::utils { ExceptionSpecAnalyzer::State ExceptionSpecAnalyzer::analyze(const FunctionDecl *FuncDecl) { - // Check if the function has already been analyzed and reuse that result. - const auto CacheEntry = FunctionCache.find(FuncDecl); - if (CacheEntry == FunctionCache.end()) { + // Check if function exist in cache or add temporary value to cache to protect + // against endless recursion. + const auto [CacheEntry, NotFound] = + FunctionCache.try_emplace(FuncDecl, State::NotThrowing); + if (NotFound) { ExceptionSpecAnalyzer::State State = analyzeImpl(FuncDecl); - - // Cache the result of the analysis. - FunctionCache.try_emplace(FuncDecl, State); + // Update result with calculated value + FunctionCache[FuncDecl] = State; return State; } |
| Being totally unfamiliar with the code, I have a feeling that we shouldn't be fixing in the However, the real problem is that In that sense I believe it would make sense to ensure no recursion happens somewhere in the chain I described above, not in |
| I put it into |
| To clarify, I'm not concerned about performance, but with code readability and maintainability. I realize the chain that I wrote above should not lead to recursion due to |
| I think this is a very reasonable change and something I didn't think about when implementing it originally. |
| There is a minimal repro in #111436 available |
| @PiotrZSL What are the chances of landing this as-is ? Does this require the changes mentioned by @carlosgalvezp ? |
1c76d3c to c808abe Compare | Actually only thing that were missing were example. |
5chmidti left a 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.
Being totally unfamiliar with the code, I have a feeling that we shouldn't be fixing in the analyze function. analyze has 1 single responsibility: wrap
analyzeImplin order to add cacheability for performance reasons, it does so simply and well, and it does exactly what one would expect - no more no less.
This class could maintain a stack-like SmallVector to check for an infinite recursion., so instead of checking the function cache (which might be large), only a few functions have to be compared this way.
Actually this change does not impact performance. Before we had 2 lookups, and now we still got 2 lookups. |
5chmidti left a 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.
LGTM, but please add a release note about fixing the infinite recursion
| And maybe @carlosgalvezp wants to comment |
clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor-crash.cpp Outdated Show resolved Hide resolved
| LGTM, had a small comment. Not sure it's worth mentioning this in the releases notes, it's just a crash fix. But it doesn't hurt I guess. |
Normally endless recursion should not happen in ExceptionSpecAnalyzer, but if AST would be malformed (missing include), this could cause crash. Fixes: llvm#111436
c808abe to 4c4234a Compare …66810) Normally endless recursion should not happen in ExceptionSpecAnalyzer, but if AST would be malformed (missing include), this could cause crash. I run into this issue when due to missing include constructor argument were parsed as FieldDecl. As checking for recursion cost nothing, why not to do this in check just in case. Fixes llvm#111436
…66810) Normally endless recursion should not happen in ExceptionSpecAnalyzer, but if AST would be malformed (missing include), this could cause crash. I run into this issue when due to missing include constructor argument were parsed as FieldDecl. As checking for recursion cost nothing, why not to do this in check just in case. Fixes llvm#111436
Normally endless recursion should not happen in ExceptionSpecAnalyzer, but if AST would be malformed (missing include), this could cause crash.
I run into this issue when due to missing include constructor argument were parsed as FieldDecl.
As checking for recursion cost nothing, why not to do this in check just in case.
Fixes #111436