Skip to content

Commit 280382e

Browse files
committed
JS: whitelist if array access at another index is seen
1 parent 5040d3e commit 280382e

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

javascript/ql/src/Statements/MissingIndexAdjustmentAfterConcurrentModification.ql

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,21 @@ class ArrayIterationLoop extends ForStmt {
126126
hasPathTo(cfg.getAPredecessor()) and
127127
getLoopEntry().dominates(cfg.getBasicBlock()) and
128128
not hasIndexingManipulation(cfg) and
129+
129130
// Ignore splice calls guarded by an index equality check.
130131
// This indicates that the index of an element is the basis for removal, not its value,
131132
// which means it may be okay to skip over elements.
132133
not exists (ConditionGuardNode guard, EqualityTest test | cfg = guard |
133134
test = guard.getTest() and
134135
test.getAnOperand() = getIndexVariable().getAnAccess() and
135-
guard.getOutcome() = test.getPolarity())
136+
guard.getOutcome() = test.getPolarity()) and
137+
138+
// Block flow after inspecting an array element other than that at the current index.
139+
// For example, if the splice happens after inspecting `array[i + 1]`, then the next
140+
// element has already been "looked at" and so it doesn't matter if we skip it.
141+
not exists (IndexExpr index | cfg = index |
142+
array.flowsToExpr(index.getBase()) and
143+
not index.getIndex() = getIndexVariable().getAnAccess())
136144
}
137145

138146
/**

javascript/ql/test/query-tests/Statements/MissingIndexAdjustmentAfterConcurrentModification/tst.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,13 @@ function removeFirstAndLast(string) {
111111
}
112112
return parts.join('/');
113113
}
114+
115+
function inspectNextElement(string) {
116+
let parts = string.split('/');
117+
for (let i = 0; i < parts.length; ++i) {
118+
if (i < parts.length - 1 && parts[i] === parts[i + 1]) {
119+
parts.splice(i, 1); // OK - next element has been looked at
120+
}
121+
}
122+
return parts.join('/');
123+
}

0 commit comments

Comments
 (0)