Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 37fc1d6

Browse files
committed
Java, C#: cleanup sign analysis
Add missing QL doc, improve readability
1 parent 48c6f34 commit 37fc1d6

4 files changed

Lines changed: 110 additions & 59 deletions

File tree

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

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ private import SsaReadPositionCommon
1111
private import Sign
1212

1313
/** Gets the sign of `e` if this can be directly determined. */
14-
Sign certainExprSign(Expr e) {
14+
private Sign certainExprSign(Expr e) {
1515
exists(int i | e.(ConstantIntegerExpr).getIntValue() = i |
1616
i < 0 and result = TNeg()
1717
or
@@ -185,29 +185,32 @@ private predicate hasGuard(SsaVariable v, SsaReadPosition pos, Sign s) {
185185
s = TZero() and zeroBound(_, v, pos)
186186
}
187187

188+
/**
189+
* Gets a possible sign of `v` at `pos` based on its definition, where the sign
190+
* might be ruled out by a guard.
191+
*/
188192
pragma[noinline]
189193
private Sign guardedSsaSign(SsaVariable v, SsaReadPosition pos) {
190-
// SSA variable can have sign `result`
191194
result = ssaDefSign(v) and
192195
pos.hasReadOfVar(v) and
193-
// there are guards at this position on `v` that might restrict it to be sign `result`.
194-
// (So we need to check if they are satisfied)
195196
hasGuard(v, pos, result)
196197
}
197198

199+
/**
200+
* Gets a possible sign of `v` at `pos` based on its definition, where no guard
201+
* can rule it out.
202+
*/
198203
pragma[noinline]
199204
private Sign unguardedSsaSign(SsaVariable v, SsaReadPosition pos) {
200-
// SSA variable can have sign `result`
201205
result = ssaDefSign(v) and
202206
pos.hasReadOfVar(v) and
203-
// there's no guard at this position on `v` that might restrict it to be sign `result`.
204207
not hasGuard(v, pos, result)
205208
}
206209

207210
/**
208-
* Gets the sign of `v` at read position `pos`, when there's at least one guard
209-
* on `v` at position `pos`. Each bound corresponding to a given sign must be met
210-
* in order for `v` to be of that sign.
211+
* Gets a possible sign of `v` at read position `pos`, where a guard could have
212+
* ruled out the sign but does not.
213+
* This does not check that the definition of `v` also allows the sign.
211214
*/
212215
private Sign guardedSsaSignOk(SsaVariable v, SsaReadPosition pos) {
213216
result = TPos() and
@@ -221,7 +224,7 @@ private Sign guardedSsaSignOk(SsaVariable v, SsaReadPosition pos) {
221224
}
222225

223226
/** Gets a possible sign for `v` at `pos`. */
224-
Sign ssaSign(SsaVariable v, SsaReadPosition pos) {
227+
private Sign ssaSign(SsaVariable v, SsaReadPosition pos) {
225228
result = unguardedSsaSign(v, pos)
226229
or
227230
result = guardedSsaSign(v, pos) and
@@ -230,7 +233,7 @@ Sign ssaSign(SsaVariable v, SsaReadPosition pos) {
230233

231234
/** Gets a possible sign for `v`. */
232235
pragma[nomagic]
233-
Sign ssaDefSign(SsaVariable v) {
236+
private Sign ssaDefSign(SsaVariable v) {
234237
result = explicitSsaDefSign(v)
235238
or
236239
result = implicitSsaDefSign(v)
@@ -250,18 +253,23 @@ Sign exprSign(Expr e) {
250253
or
251254
not exists(certainExprSign(e)) and
252255
(
253-
unknownSign(e)
256+
anySign(s) and unknownSign(e)
254257
or
255-
exists(SsaVariable v | getARead(v) = e | s = ssaVariableSign(v, e))
258+
exists(SsaVariable v | getARead(v) = e |
259+
s = ssaSign(v, any(SsaReadPositionBlock bb | getAnExpression(bb) = e))
260+
or
261+
not exists(SsaReadPositionBlock bb | getAnExpression(bb) = e) and
262+
s = ssaDefSign(v)
263+
)
256264
or
257-
e =
258-
any(VarAccess access |
259-
not exists(SsaVariable v | getARead(v) = access) and
260-
(
261-
s = fieldSign(getField(access.(FieldAccess))) or
262-
not access instanceof FieldAccess
263-
)
265+
exists(VarAccess access | access = e |
266+
not exists(SsaVariable v | getARead(v) = access) and
267+
(
268+
s = fieldSign(getField(access.(FieldAccess)))
269+
or
270+
anySign(s) and not access instanceof FieldAccess
264271
)
272+
)
265273
or
266274
s = specificSubExprSign(e)
267275
)
@@ -272,6 +280,12 @@ Sign exprSign(Expr e) {
272280
)
273281
}
274282

283+
/**
284+
* Dummy predicate that holds for any sign. This is added to improve readability
285+
* of cases where the sign is unrestricted.
286+
*/
287+
predicate anySign(Sign s) { any() }
288+
275289
/** Holds if `e` can be positive and cannot be negative. */
276290
predicate positive(Expr e) {
277291
exprSign(e) = TPos() and

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

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ private module Impl {
4848

4949
private class BooleanValue = AbstractValues::BooleanValue;
5050

51+
/**
52+
* Gets the value of the expression if it can't be converted to integer, but
53+
* can be converted to float.
54+
*/
5155
float getNonIntegerValue(Expr e) {
5256
exists(string s |
5357
s = e.getValue() and
@@ -56,8 +60,13 @@ private module Impl {
5660
)
5761
}
5862

63+
/** Gets the character value of expression `e`. */
5964
string getCharValue(Expr e) { result = e.getValue() and e.getType() instanceof CharType }
6065

66+
/**
67+
* Holds if `e` is an access to the size of a container (`string`, `Array`,
68+
* `IEnumerable`, or `ICollection`).
69+
*/
6170
predicate containerSizeAccess(Expr e) {
6271
exists(Property p | p = e.(PropertyAccess).getTarget() |
6372
propertyOverrides(p, "System.Collections.Generic.IEnumerable<>", "Count") or
@@ -69,6 +78,7 @@ private module Impl {
6978
e instanceof CountCall
7079
}
7180

81+
/** Holds if `e` is by definition strictly positive. */
7282
predicate positiveExpression(Expr e) { e instanceof SizeofExpr }
7383

7484
abstract class NumericOrCharType extends Type { }
@@ -97,10 +107,12 @@ private module Impl {
97107
}
98108
}
99109

110+
/** Returns the sign of explicit SSA definition `v`. */
100111
Sign explicitSsaDefSign(Ssa::ExplicitDefinition v) {
101112
exists(AssignableDefinition def | def = v.getADefinition() |
102113
result = exprSign(def.getSource())
103114
or
115+
anySign(result) and
104116
not exists(def.getSource()) and
105117
not def.getElement() instanceof MutatorOperation
106118
or
@@ -110,14 +122,11 @@ private module Impl {
110122
)
111123
}
112124

125+
/** Returns the sign of implicit SSA definition `v`. */
113126
Sign implicitSsaDefSign(Ssa::ImplicitDefinition v) {
114-
result = fieldSign(v.getSourceVariable().getAssignable()) or
115-
not v.getSourceVariable().getAssignable() instanceof Field
116-
}
117-
118-
pragma[inline]
119-
Sign ssaVariableSign(Ssa::Definition v, Expr e) {
120-
result = ssaSign(v, any(SsaReadPositionBlock bb | getAnExpression(bb) = e))
127+
result = fieldSign(v.getSourceVariable().getAssignable())
128+
or
129+
anySign(result) and not v.getSourceVariable().getAssignable() instanceof Field
121130
}
122131

123132
/** Gets a possible sign for `f`. */
@@ -133,9 +142,12 @@ private module Impl {
133142
exists(AssignOperation a | a.getLValue() = f.getAnAccess() | result = exprSign(a))
134143
or
135144
not exists(f.getInitializer()) and result = TZero()
136-
else any()
145+
else anySign(result)
137146
}
138147

148+
/**
149+
* Holds if `e` has type `NumericOrCharType`, but the sign of `e` is unknown.
150+
*/
139151
predicate unknownIntegerAccess(Expr e) {
140152
e.getType() instanceof NumericOrCharType and
141153
not e = getARead(_) and
@@ -171,6 +183,7 @@ private module Impl {
171183
not e instanceof NullCoalescingExpr
172184
}
173185

186+
/** Gets a possible sign for `e` from the signs of its child nodes. */
174187
Sign specificSubExprSign(Expr e) {
175188
// The expression types that are handled here should be excluded in `unknownIntegerAccess`.
176189
// Keep them in sync.

java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ private import SsaReadPositionCommon
1111
private import Sign
1212

1313
/** Gets the sign of `e` if this can be directly determined. */
14-
Sign certainExprSign(Expr e) {
14+
private Sign certainExprSign(Expr e) {
1515
exists(int i | e.(ConstantIntegerExpr).getIntValue() = i |
1616
i < 0 and result = TNeg()
1717
or
@@ -185,29 +185,32 @@ private predicate hasGuard(SsaVariable v, SsaReadPosition pos, Sign s) {
185185
s = TZero() and zeroBound(_, v, pos)
186186
}
187187

188+
/**
189+
* Gets a possible sign of `v` at `pos` based on its definition, where the sign
190+
* might be ruled out by a guard.
191+
*/
188192
pragma[noinline]
189193
private Sign guardedSsaSign(SsaVariable v, SsaReadPosition pos) {
190-
// SSA variable can have sign `result`
191194
result = ssaDefSign(v) and
192195
pos.hasReadOfVar(v) and
193-
// there are guards at this position on `v` that might restrict it to be sign `result`.
194-
// (So we need to check if they are satisfied)
195196
hasGuard(v, pos, result)
196197
}
197198

199+
/**
200+
* Gets a possible sign of `v` at `pos` based on its definition, where no guard
201+
* can rule it out.
202+
*/
198203
pragma[noinline]
199204
private Sign unguardedSsaSign(SsaVariable v, SsaReadPosition pos) {
200-
// SSA variable can have sign `result`
201205
result = ssaDefSign(v) and
202206
pos.hasReadOfVar(v) and
203-
// there's no guard at this position on `v` that might restrict it to be sign `result`.
204207
not hasGuard(v, pos, result)
205208
}
206209

207210
/**
208-
* Gets the sign of `v` at read position `pos`, when there's at least one guard
209-
* on `v` at position `pos`. Each bound corresponding to a given sign must be met
210-
* in order for `v` to be of that sign.
211+
* Gets a possible sign of `v` at read position `pos`, where a guard could have
212+
* ruled out the sign but does not.
213+
* This does not check that the definition of `v` also allows the sign.
211214
*/
212215
private Sign guardedSsaSignOk(SsaVariable v, SsaReadPosition pos) {
213216
result = TPos() and
@@ -221,7 +224,7 @@ private Sign guardedSsaSignOk(SsaVariable v, SsaReadPosition pos) {
221224
}
222225

223226
/** Gets a possible sign for `v` at `pos`. */
224-
Sign ssaSign(SsaVariable v, SsaReadPosition pos) {
227+
private Sign ssaSign(SsaVariable v, SsaReadPosition pos) {
225228
result = unguardedSsaSign(v, pos)
226229
or
227230
result = guardedSsaSign(v, pos) and
@@ -230,7 +233,7 @@ Sign ssaSign(SsaVariable v, SsaReadPosition pos) {
230233

231234
/** Gets a possible sign for `v`. */
232235
pragma[nomagic]
233-
Sign ssaDefSign(SsaVariable v) {
236+
private Sign ssaDefSign(SsaVariable v) {
234237
result = explicitSsaDefSign(v)
235238
or
236239
result = implicitSsaDefSign(v)
@@ -250,18 +253,23 @@ Sign exprSign(Expr e) {
250253
or
251254
not exists(certainExprSign(e)) and
252255
(
253-
unknownSign(e)
256+
anySign(s) and unknownSign(e)
254257
or
255-
exists(SsaVariable v | getARead(v) = e | s = ssaVariableSign(v, e))
258+
exists(SsaVariable v | getARead(v) = e |
259+
s = ssaSign(v, any(SsaReadPositionBlock bb | getAnExpression(bb) = e))
260+
or
261+
not exists(SsaReadPositionBlock bb | getAnExpression(bb) = e) and
262+
s = ssaDefSign(v)
263+
)
256264
or
257-
e =
258-
any(VarAccess access |
259-
not exists(SsaVariable v | getARead(v) = access) and
260-
(
261-
s = fieldSign(getField(access.(FieldAccess))) or
262-
not access instanceof FieldAccess
263-
)
265+
exists(VarAccess access | access = e |
266+
not exists(SsaVariable v | getARead(v) = access) and
267+
(
268+
s = fieldSign(getField(access.(FieldAccess)))
269+
or
270+
anySign(s) and not access instanceof FieldAccess
264271
)
272+
)
265273
or
266274
s = specificSubExprSign(e)
267275
)
@@ -272,6 +280,12 @@ Sign exprSign(Expr e) {
272280
)
273281
}
274282

283+
/**
284+
* Dummy predicate that holds for any sign. This is added to improve readability
285+
* of cases where the sign is unrestricted.
286+
*/
287+
predicate anySign(Sign s) { any() }
288+
275289
/** Holds if `e` can be positive and cannot be negative. */
276290
predicate positive(Expr e) {
277291
exprSign(e) = TPos() and

0 commit comments

Comments
 (0)