mirror of
https://github.com/github/codeql.git
synced 2026-04-21 15:05:56 +02:00
Java: Fix bad join
Before
```
[2024-08-06 10:37:59] Evaluated non-recursive predicate BoundingChecks::arrayReference/1#754911ba@0628dahn in 20981ms (size: 2009682526).
Evaluated relational algebra for predicate BoundingChecks::arrayReference/1#754911ba@0628dahn with tuple counts:
94480 ~0% {2} r1 = SCAN `Expr::ArrayAccess.getArray/0#dispred#b90c658a` OUTPUT In.1, In.0
32 ~0% {2} r2 = JOIN r1 WITH `Expr::MethodCall.getMethod/0#dispred#41989dc9` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
1013 ~1% {2} | JOIN WITH `Expr::MethodCall.getMethod/0#dispred#41989dc9_10#join_rhs` ON FIRST 1 OUTPUT Lhs.1, Rhs.1
92091 ~4% {2} r3 = JOIN r1 WITH variableBinding ON FIRST 1 OUTPUT Rhs.1, Lhs.1
2009681513 ~0% {2} | JOIN WITH variableBinding_10#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1
2009682526 ~0% {2} r4 = r2 UNION r3
return r4
[2024-08-06 10:38:02] Evaluated non-recursive predicate BoundingChecks::lessthanLength/1#48b5e1b7@2885308n in 0ms (size: 108).
Evaluated relational algebra for predicate BoundingChecks::lessthanLength/1#48b5e1b7@2885308n with tuple counts:
1518 ~0% {2} r1 = JOIN `Expr::ComparisonExpr.isStrict/0#dispred#fd8c6ddb` WITH `Expr::ComparisonExpr.getGreaterOperand/0#dispred#e8df4b14` ON FIRST 1 OUTPUT Rhs.1, Lhs.0
455 ~2% {2} | JOIN WITH Expr::FieldAccess#2b664c37 ON FIRST 1 OUTPUT Lhs.1, Lhs.0
455 ~1% {3} | JOIN WITH `Expr::ComparisonExpr.getLesserOperand/0#dispred#d7744bc2` ON FIRST 1 OUTPUT Lhs.1, Lhs.0, Rhs.1
455 ~0% {5} | JOIN WITH `Expr::FieldAccess.getField/0#dispred#29ef4aa0` ON FIRST 1 OUTPUT Rhs.1, _, Lhs.1, Lhs.0, Lhs.2
455 ~0% {5} | REWRITE WITH Out.1 := "length"
116 ~0% {3} | JOIN WITH `Element::Element.hasName/1#dispred#8acbbbde` ON FIRST 2 OUTPUT Lhs.4, Lhs.2, Lhs.3
93 ~0% {3} | JOIN WITH variableBinding ON FIRST 1 OUTPUT Lhs.2, Lhs.1, Rhs.1
93 ~1% {3} | JOIN WITH `Expr::VarAccess.getQualifier/0#dispred#2b0f1cd1` ON FIRST 1 OUTPUT Lhs.2, Lhs.1, Rhs.1
484 ~2% {3} | JOIN WITH variableBinding_10#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Lhs.2
277 ~3% {2} | JOIN WITH `BoundingChecks::conditionHolds/2#fa0354b9#bb` ON FIRST 2 OUTPUT Lhs.1, Lhs.2
166 ~5% {2} | JOIN WITH `Expr::ArrayAccess.getIndexExpr/0#dispred#345f6cf4_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
110 ~0% {1} | JOIN WITH `BoundingChecks::arrayReference/1#754911ba` ON FIRST 2 OUTPUT Lhs.0
return r1
```
After
```
[2024-08-06 13:29:50] Evaluated non-recursive predicate BoundingChecks::lengthAccess/2#54b10eff@719e68tb in 0ms (size: 309).
Evaluated relational algebra for predicate BoundingChecks::lengthAccess/2#54b10eff@719e68tb with tuple counts:
6241 ~0% {2} r1 = JOIN `BoundingChecks::getAnAccess/1#152ad44e_10#join_rhs` WITH `Expr::VarAccess.getQualifier/0#dispred#2b0f1cd1_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
6240 ~0% {4} | JOIN WITH `Expr::FieldAccess.getField/0#dispred#29ef4aa0` ON FIRST 1 OUTPUT Rhs.1, _, Lhs.1, Lhs.0
6240 ~0% {4} | REWRITE WITH Out.1 := "length"
309 ~2% {2} | JOIN WITH `Element::Element.hasName/1#dispred#8acbbbde` ON FIRST 2 OUTPUT Lhs.3, Lhs.2
return r1
[2024-08-06 13:29:50] Evaluated non-recursive predicate BoundingChecks::lessthanLength/1#48b5e1b7@0fcac509 in 1ms (size: 108).
Evaluated relational algebra for predicate BoundingChecks::lessthanLength/1#48b5e1b7@0fcac509 with tuple counts:
94480 ~0% {3} r1 = JOIN `Expr::ArrayAccess.getArray/0#dispred#b90c658a` WITH `Expr::ArrayAccess.getIndexExpr/0#dispred#345f6cf4` ON FIRST 1 OUTPUT Rhs.1, Lhs.0, Lhs.1
648 ~4% {4} | JOIN WITH variableBinding ON FIRST 1 OUTPUT Lhs.2, Lhs.1, Lhs.0, Rhs.1
621 ~1% {4} | JOIN WITH `BoundingChecks::getAnAccess/1#152ad44e_10#join_rhs` ON FIRST 1 OUTPUT Lhs.2, Lhs.1, Lhs.3, Rhs.1
344 ~0% {4} | JOIN WITH `BoundingChecks::conditionHolds/2#fa0354b9#bb_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3
341 ~0% {4} | JOIN WITH `Expr::ComparisonExpr.isStrict/0#dispred#fd8c6ddb` ON FIRST 1 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.3
341 ~0% {5} | JOIN WITH `Expr::ComparisonExpr.getGreaterOperand/0#dispred#e8df4b14` ON FIRST 1 OUTPUT Rhs.1, Lhs.3, Lhs.1, Lhs.2, Lhs.0
110 ~2% {3} | JOIN WITH `BoundingChecks::lengthAccess/2#54b10eff` ON FIRST 2 OUTPUT Lhs.4, Lhs.2, Lhs.3
110 ~0% {3} | JOIN WITH `Expr::ComparisonExpr.getLesserOperand/0#dispred#d7744bc2` ON FIRST 1 OUTPUT Rhs.1, Lhs.2, Lhs.1
110 ~0% {1} | JOIN WITH variableBinding ON FIRST 2 OUTPUT Lhs.2
return r1
```
This commit is contained in:
@@ -36,30 +36,32 @@ int lowerBound(VarAccess va) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an access to `e`, which is either a variable or a method. */
|
||||
pragma[nomagic]
|
||||
private Expr getAnAccess(Element e) {
|
||||
result = e.(Variable).getAnAccess()
|
||||
or
|
||||
result.(MethodCall).getMethod() = e
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate lengthAccess(FieldAccess fa, Element qualifier) {
|
||||
fa.getQualifier() = getAnAccess(qualifier) and
|
||||
fa.getField().hasName("length")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the index expression is a `VarAccess`, where the variable has been confirmed to be less
|
||||
* than the length.
|
||||
*/
|
||||
predicate lessthanLength(ArrayAccess a) {
|
||||
exists(ComparisonExpr lessThanLength, VarAccess va |
|
||||
exists(ComparisonExpr lessThanLength, VarAccess va, Element qualifier |
|
||||
va = a.getIndexExpr() and
|
||||
conditionHolds(lessThanLength, va)
|
||||
|
|
||||
lessThanLength.getGreaterOperand().(FieldAccess).getQualifier() = arrayReference(a) and
|
||||
lessThanLength.getGreaterOperand().(FieldAccess).getField().hasName("length") and
|
||||
lengthAccess(lessThanLength.getGreaterOperand(), qualifier) and
|
||||
a.getArray() = getAnAccess(qualifier) and
|
||||
lessThanLength.getLesserOperand() = va.getVariable().getAnAccess() and
|
||||
lessThanLength.isStrict()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all other references to the array accessed in the `ArrayAccess`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Expr arrayReference(ArrayAccess arrayAccess) {
|
||||
// Array is stored in a variable.
|
||||
result = arrayAccess.getArray().(VarAccess).getVariable().getAnAccess()
|
||||
or
|
||||
// Array is returned from a method.
|
||||
result.(MethodCall).getMethod() = arrayAccess.getArray().(MethodCall).getMethod()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user