Avoid adding to closureBusy before all ATNConfig properties are set
Setting ATNConfig properties can change the hash code of the instance, leading to cases where the closureBusy set places objects in the wrong buckets. While this has not led to known cases of stack overflow, it has led to cases where one or more buckets contains a large number of duplicate objects, and the set's add operation goes from O(1) to O(n).
This commit is contained in:
parent
c41426c87e
commit
c8805ab584
|
@ -1541,11 +1541,6 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
ATNConfig c = getEpsilonTarget(config, t, continueCollecting,
|
||||
depth == 0, fullCtx, treatEofAsEpsilon);
|
||||
if ( c!=null ) {
|
||||
if (!t.isEpsilon() && !closureBusy.add(c)) {
|
||||
// avoid infinite recursion for EOF* and EOF+
|
||||
continue;
|
||||
}
|
||||
|
||||
int newDepth = depth;
|
||||
if ( config.state instanceof RuleStopState) {
|
||||
assert !fullCtx;
|
||||
|
@ -1555,11 +1550,6 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
// come in handy and we avoid evaluating context dependent
|
||||
// preds if this is > 0.
|
||||
|
||||
if (!closureBusy.add(c)) {
|
||||
// avoid infinite recursion for right-recursive rules
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_dfa != null && _dfa.isPrecedenceDfa()) {
|
||||
int outermostPrecedenceReturn = ((EpsilonTransition)t).outermostPrecedenceReturn();
|
||||
if (outermostPrecedenceReturn == _dfa.atnStartState.ruleIndex) {
|
||||
|
@ -1568,15 +1558,28 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
}
|
||||
|
||||
c.reachesIntoOuterContext++;
|
||||
|
||||
if (!closureBusy.add(c)) {
|
||||
// avoid infinite recursion for right-recursive rules
|
||||
continue;
|
||||
}
|
||||
|
||||
configs.dipsIntoOuterContext = true; // TODO: can remove? only care when we add to set per middle of this method
|
||||
assert newDepth > Integer.MIN_VALUE;
|
||||
newDepth--;
|
||||
if ( debug ) System.out.println("dips into outer ctx: "+c);
|
||||
}
|
||||
else if (t instanceof RuleTransition) {
|
||||
// latch when newDepth goes negative - once we step out of the entry context we can't return
|
||||
if (newDepth >= 0) {
|
||||
newDepth++;
|
||||
else {
|
||||
if (!t.isEpsilon() && !closureBusy.add(c)) {
|
||||
// avoid infinite recursion for EOF* and EOF+
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t instanceof RuleTransition) {
|
||||
// latch when newDepth goes negative - once we step out of the entry context we can't return
|
||||
if (newDepth >= 0) {
|
||||
newDepth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue