diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-09-27 05:36:16 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-09-27 05:36:16 +0000 |
commit | 49494733533dd3f0be7d0ae216b267e71ee946b4 (patch) | |
tree | f230139ea7a8977f3cd617dca37ccda062504067 | |
parent | 3fcdd25ad5566114ac3322dcbf71d3c38bfec1ed (diff) | |
download | bcm5719-llvm-49494733533dd3f0be7d0ae216b267e71ee946b4.tar.gz bcm5719-llvm-49494733533dd3f0be7d0ae216b267e71ee946b4.zip |
Fix use-after-free found in Clang's testsuite.
We need to discard all remaining cleanups if an earlier cleanup failed,
otherwise we may try to rerun the remaining cleanups later, potentially
after the scope containing the object is destroyed. (This can happen
when checking a potential constant expression.)
llvm-svn: 373042
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index a2a6168ddbf..12dc054b81e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1239,11 +1239,14 @@ namespace { // Run all cleanups for a block scope, and non-lifetime-extended cleanups // for a full-expression scope. + bool Success = true; for (unsigned I = Info.CleanupStack.size(); I > OldStackSize; --I) { if (!(IsFullExpression && Info.CleanupStack[I - 1].isLifetimeExtended())) { - if (!Info.CleanupStack[I - 1].endLifetime(Info, RunDestructors)) - return false; + if (!Info.CleanupStack[I - 1].endLifetime(Info, RunDestructors)) { + Success = false; + break; + } } } @@ -1254,7 +1257,7 @@ namespace { std::remove_if(NewEnd, Info.CleanupStack.end(), [](Cleanup &C) { return !C.isLifetimeExtended(); }); Info.CleanupStack.erase(NewEnd, Info.CleanupStack.end()); - return true; + return Success; } }; typedef ScopeRAII<false> BlockScopeRAII; |