diff options
author | Duncan Sands <baldrick@free.fr> | 2011-01-26 10:08:38 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2011-01-26 10:08:38 +0000 |
commit | 69bdb585b23ba55150844bad1a1d007c81d5fd2c (patch) | |
tree | 1d96777bab80dafc71f5d8456a92d6e9a6212f9d /llvm/lib/Transforms/Scalar/Reassociate.cpp | |
parent | 91543447a6f2a8862a50043b08b3b31550b4f0f9 (diff) | |
download | bcm5719-llvm-69bdb585b23ba55150844bad1a1d007c81d5fd2c.tar.gz bcm5719-llvm-69bdb585b23ba55150844bad1a1d007c81d5fd2c.zip |
Fix PR9039, a use-after-free in reassociate. The issue was that the
operand being factorized (and erased) could occur several times in Ops,
resulting in freed memory being used when the next occurrence in Ops was
analyzed.
llvm-svn: 124287
Diffstat (limited to 'llvm/lib/Transforms/Scalar/Reassociate.cpp')
-rw-r--r-- | llvm/lib/Transforms/Scalar/Reassociate.cpp | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp index 46b7f952581..396b3299807 100644 --- a/llvm/lib/Transforms/Scalar/Reassociate.cpp +++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -811,16 +811,23 @@ Value *Reassociate::OptimizeAdd(Instruction *I, // RemoveFactorFromExpression on successive values to behave differently. Instruction *DummyInst = BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal); SmallVector<Value*, 4> NewMulOps; - for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + for (unsigned i = 0; i != Ops.size(); ++i) { // Only try to remove factors from expressions we're allowed to. BinaryOperator *BOp = dyn_cast<BinaryOperator>(Ops[i].Op); if (BOp == 0 || BOp->getOpcode() != Instruction::Mul || !BOp->use_empty()) continue; if (Value *V = RemoveFactorFromExpression(Ops[i].Op, MaxOccVal)) { - NewMulOps.push_back(V); - Ops.erase(Ops.begin()+i); - --i; --e; + // The factorized operand may occur several times. Convert them all in + // one fell swoop. + for (unsigned j = Ops.size(); j != i;) { + --j; + if (Ops[j].Op == Ops[i].Op) { + NewMulOps.push_back(V); + Ops.erase(Ops.begin()+j); + } + } + --i; } } |