Skip to content

Commit d2d8d00

Browse files
committed
Sync Bound between C# and Java
1 parent 40a7f5a commit d2d8d00

File tree

6 files changed

+134
-6
lines changed

6 files changed

+134
-6
lines changed

config/identical-files.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
"java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll",
6363
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll"
6464
],
65+
"Bound Java/C#": [
66+
"java/ql/src/semmle/code/java/dataflow/Bound.qll",
67+
"csharp/ql/src/semmle/code/csharp/dataflow/Bound.qll"
68+
],
6569
"C++ SubBasicBlocks": [
6670
"cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll",
6771
"cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* Provides classes for representing abstract bounds for use in, for example, range analysis.
3+
*/
4+
5+
private import internal.rangeanalysis.BoundSpecific
6+
7+
private newtype TBound =
8+
TBoundZero() or
9+
TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or
10+
TBoundExpr(Expr e) {
11+
interestingExprBound(e) and
12+
not exists(SsaVariable v | e = v.getAUse())
13+
}
14+
15+
/**
16+
* A bound that may be inferred for an expression plus/minus an integer delta.
17+
*/
18+
abstract class Bound extends TBound {
19+
/** Gets a textual representation of this bound. */
20+
abstract string toString();
21+
22+
/** Gets an expression that equals this bound plus `delta`. */
23+
abstract Expr getExpr(int delta);
24+
25+
/** Gets an expression that equals this bound. */
26+
Expr getExpr() { result = getExpr(0) }
27+
28+
/**
29+
* Holds if this element is at the specified location.
30+
* The location spans column `sc` of line `sl` to
31+
* column `ec` of line `el` in file `path`.
32+
* For more information, see
33+
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
34+
*/
35+
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
36+
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
37+
}
38+
}
39+
40+
/**
41+
* The bound that corresponds to the integer 0. This is used to represent all
42+
* integer bounds as bounds are always accompanied by an added integer delta.
43+
*/
44+
class ZeroBound extends Bound, TBoundZero {
45+
override string toString() { result = "0" }
46+
47+
override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta }
48+
}
49+
50+
/**
51+
* A bound corresponding to the value of an SSA variable.
52+
*/
53+
class SsaBound extends Bound, TBoundSsa {
54+
/** Gets the SSA variable that equals this bound. */
55+
SsaVariable getSsa() { this = TBoundSsa(result) }
56+
57+
override string toString() { result = getSsa().toString() }
58+
59+
override Expr getExpr(int delta) { result = getSsa().getAUse() and delta = 0 }
60+
61+
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
62+
getSsa().getLocation().hasLocationInfo(path, sl, sc, el, ec)
63+
}
64+
}
65+
66+
/**
67+
* A bound that corresponds to the value of a specific expression that might be
68+
* interesting, but isn't otherwise represented by the value of an SSA variable.
69+
*/
70+
class ExprBound extends Bound, TBoundExpr {
71+
override string toString() { result = getExpr().toString() }
72+
73+
override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 }
74+
75+
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
76+
getExpr().getLocation().hasLocationInfo(path, sl, sc, el, ec)
77+
}
78+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Provides C#-specific definitions for bounds.
3+
*/
4+
5+
private import csharp as CS
6+
private import semmle.code.csharp.dataflow.SSA::Ssa as Ssa
7+
private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU
8+
9+
class SsaVariable extends Ssa::Definition {
10+
/** Gets a read of the source variable underlying this SSA definition. */
11+
Expr getAUse() { result = getARead() }
12+
}
13+
14+
class Expr = CS::Expr;
15+
16+
class IntegralType = CS::IntegralType;
17+
18+
class ConstantIntegerExpr = CU::ConstantIntegerExpr;
19+
20+
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
21+
predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.(CS::PropertyRead)) }

csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ConstantUtils.qll

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ predicate propertyOverrides(Property p, string baseClass, string property) {
1717
)
1818
}
1919

20+
/**
21+
* Holds if `pa` is an access to the `Length` property of an array.
22+
*/
23+
predicate systemArrayLengthAccess(PropertyAccess pa) {
24+
propertyOverrides(pa.getTarget(), "System.Array", "Length")
25+
}
26+
2027
/**
2128
* Holds if expression `e` is either
2229
* - a compile time constant with integer value `val`, or
@@ -47,7 +54,7 @@ private int getArrayLengthRec(ArrayCreation arrCreation, int index) {
4754
}
4855

4956
private predicate isArrayLengthAccess(PropertyAccess pa, int length) {
50-
propertyOverrides(pa.getTarget(), "System.Array", "Length") and
57+
systemArrayLengthAccess(pa) and
5158
exists(ExplicitDefinition arr, ArrayCreation arrCreation |
5259
getArrayLengthRec(arrCreation, arrCreation.getNumberOfLengthArguments() - 1) = length and
5360
arrCreation = arr.getADefinition().getSource() and

java/ql/src/semmle/code/java/dataflow/Bound.qll

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22
* Provides classes for representing abstract bounds for use in, for example, range analysis.
33
*/
44

5-
import java
6-
private import SSA
7-
private import RangeUtils
5+
private import internal.rangeanalysis.BoundSpecific
86

97
private newtype TBound =
108
TBoundZero() or
119
TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or
1210
TBoundExpr(Expr e) {
13-
e.(FieldRead).getField() instanceof ArrayLengthField and
11+
interestingExprBound(e) and
1412
not exists(SsaVariable v | e = v.getAUse())
1513
}
1614

@@ -75,6 +73,6 @@ class ExprBound extends Bound, TBoundExpr {
7573
override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 }
7674

7775
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
78-
getExpr().hasLocationInfo(path, sl, sc, el, ec)
76+
getExpr().getLocation().hasLocationInfo(path, sl, sc, el, ec)
7977
}
8078
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Provides Java-specific definitions for bounds.
3+
*/
4+
5+
private import java as J
6+
private import semmle.code.java.dataflow.SSA as Ssa
7+
private import semmle.code.java.dataflow.RangeUtils as RU
8+
9+
class SsaVariable = Ssa::SsaVariable;
10+
11+
class Expr = J::Expr;
12+
13+
class IntegralType = J::IntegralType;
14+
15+
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
16+
17+
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
18+
predicate interestingExprBound(Expr e) {
19+
e.(J::FieldRead).getField() instanceof J::ArrayLengthField
20+
}

0 commit comments

Comments
 (0)