Fix crash due to invalid iterators in DtoEnclosingHandlers

Unfortunately, I could not manage to isolate a self-contained
test case. The bug is quite specific to the exact memory
allocation decisions made by the standard library, as it will
not occur if the elements appended by the finally block codegen
fit into the current capacity.
This commit is contained in:
David Nadlinger 2015-08-09 19:35:37 +02:00
parent 284d5ac441
commit 553ce18a5e

View file

@ -284,17 +284,20 @@ void DtoEnclosingHandlers(Loc& loc, Statement* target)
if (lblstmt) if (lblstmt)
target = lblstmt->enclosingScopeExit; target = lblstmt->enclosingScopeExit;
// figure out up until what handler we need to emit // Figure out up until what handler we need to emit. Note that we need to
FuncGen::TargetScopeVec::reverse_iterator targetit = gIR->func()->gen->targetScopes.rbegin(); // use use indices instead of iterators in the loop where we actually emit
FuncGen::TargetScopeVec::reverse_iterator it_end = gIR->func()->gen->targetScopes.rend(); // them, as emitCode() might itself push/pop from the vector if it contains
while(targetit != it_end) { // control flow and and thus invalidate the latter.
if (targetit->s == target) { FuncGen::TargetScopeVec& scopes = gIR->func()->gen->targetScopes;
size_t remainingScopes = scopes.size();
while (remainingScopes != 0) {
if (scopes[remainingScopes - 1].s == target) {
break; break;
} }
++targetit; --remainingScopes;
} }
if (target && targetit == it_end) { if (target && !remainingScopes) {
if (lblstmt) if (lblstmt)
error(loc, "cannot goto into try, volatile or synchronized statement at %s", target->loc.toChars()); error(loc, "cannot goto into try, volatile or synchronized statement at %s", target->loc.toChars());
else else
@ -309,12 +312,12 @@ void DtoEnclosingHandlers(Loc& loc, Statement* target)
// since the labelstatements possibly inside are private // since the labelstatements possibly inside are private
// and might already exist push a label scope // and might already exist push a label scope
gIR->func()->gen->pushUniqueLabelScope("enclosing"); gIR->func()->gen->pushUniqueLabelScope("enclosing");
FuncGen::TargetScopeVec::reverse_iterator it = gIR->func()->gen->targetScopes.rbegin();
while (it != targetit) { for (size_t i = scopes.size(); i > remainingScopes; --i) {
if (it->enclosinghandler) EnclosingTryFinally *tf = scopes[i - 1].enclosinghandler;
it->enclosinghandler->emitCode(gIR); if (tf) tf->emitCode(gIR);
++it;
} }
gIR->func()->gen->popLabelScope(); gIR->func()->gen->popLabelScope();
} }