mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Guards: Generalise wrapper guards.
This commit is contained in:
@@ -344,11 +344,8 @@ private module GuardsInput implements SharedGuards::InputSig<Location> {
|
||||
|
||||
final private class FinalMethod = Method;
|
||||
|
||||
class BooleanMethod extends FinalMethod {
|
||||
BooleanMethod() {
|
||||
super.getReturnType().(PrimitiveType).hasName("boolean") and
|
||||
not super.isOverridable()
|
||||
}
|
||||
class NonOverridableMethod extends FinalMethod {
|
||||
NonOverridableMethod() { not super.isOverridable() }
|
||||
|
||||
Parameter getParameter(ParameterPosition ppos) {
|
||||
super.getParameter(ppos) = result and
|
||||
@@ -363,14 +360,14 @@ private module GuardsInput implements SharedGuards::InputSig<Location> {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate booleanMethodCall(MethodCall call, BooleanMethod m) {
|
||||
private predicate nonOverridableMethodCall(MethodCall call, NonOverridableMethod m) {
|
||||
call.getMethod().getSourceDeclaration() = m
|
||||
}
|
||||
|
||||
class BooleanMethodCall extends GuardsInput::Expr instanceof MethodCall {
|
||||
BooleanMethodCall() { booleanMethodCall(this, _) }
|
||||
class NonOverridableMethodCall extends GuardsInput::Expr instanceof MethodCall {
|
||||
NonOverridableMethodCall() { nonOverridableMethodCall(this, _) }
|
||||
|
||||
BooleanMethod getMethod() { booleanMethodCall(this, result) }
|
||||
NonOverridableMethod getMethod() { nonOverridableMethodCall(this, result) }
|
||||
|
||||
GuardsInput::Expr getArgument(ArgumentPosition apos) { result = super.getArgument(apos) }
|
||||
}
|
||||
|
||||
@@ -143,4 +143,63 @@ public class Guards {
|
||||
chk(); // $ guarded=found:true guarded='i < a.length:false'
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean testNotNull1(String input) {
|
||||
return input != null && input.length() > 0;
|
||||
}
|
||||
|
||||
public static boolean testNotNull2(String input) {
|
||||
if (input == null) return false;
|
||||
return input.length() > 0;
|
||||
}
|
||||
|
||||
public static int getNumOrDefault(Integer number) {
|
||||
return number == null ? 0 : number;
|
||||
}
|
||||
|
||||
public static String concatNonNull(String s1, String s2) {
|
||||
if (s1 == null || s2 == null) return null;
|
||||
return s1 + s2;
|
||||
}
|
||||
|
||||
public static Status testEnumWrapper(boolean flag) {
|
||||
return flag ? Status.SUCCESS : Status.FAILURE;
|
||||
}
|
||||
|
||||
enum Status { SUCCESS, FAILURE }
|
||||
|
||||
void testWrappers(String s, Integer i) {
|
||||
if (testNotNull1(s)) {
|
||||
chk(); // $ guarded='s:not null' guarded=testNotNull1(...):true
|
||||
} else {
|
||||
chk(); // $ guarded=testNotNull1(...):false
|
||||
}
|
||||
|
||||
if (testNotNull2(s)) {
|
||||
chk(); // $ guarded='s:not null' guarded=testNotNull2(...):true
|
||||
} else {
|
||||
chk(); // $ guarded=testNotNull2(...):false
|
||||
}
|
||||
|
||||
if (0 == getNumOrDefault(i)) {
|
||||
chk(); // $ guarded='0 == getNumOrDefault(...):true' guarded='getNumOrDefault(...):0'
|
||||
} else {
|
||||
chk(); // $ guarded='0 == getNumOrDefault(...):false' guarded='getNumOrDefault(...):not 0' guarded='i:not 0' guarded='i:not null'
|
||||
}
|
||||
|
||||
if (null == concatNonNull(s, "suffix")) {
|
||||
chk(); // $ guarded='concatNonNull(...):null' guarded='null == concatNonNull(...):true'
|
||||
} else {
|
||||
chk(); // $ guarded='concatNonNull(...):not null' guarded='null == concatNonNull(...):false' guarded='s:not null'
|
||||
}
|
||||
|
||||
switch (testEnumWrapper(g(1))) {
|
||||
case SUCCESS:
|
||||
chk(); // $ guarded='testEnumWrapper(...):SUCCESS' guarded='testEnumWrapper(...):match SUCCESS' guarded=g(1):true
|
||||
break;
|
||||
case FAILURE:
|
||||
chk(); // $ guarded='testEnumWrapper(...):FAILURE' guarded='testEnumWrapper(...):match FAILURE' guarded=g(1):false
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,3 +89,26 @@
|
||||
| Guards.java:139:9:139:13 | chk(...) | found:true |
|
||||
| Guards.java:143:7:143:11 | chk(...) | 'i < a.length:false' |
|
||||
| Guards.java:143:7:143:11 | chk(...) | found:true |
|
||||
| Guards.java:173:7:173:11 | chk(...) | 's:not null' |
|
||||
| Guards.java:173:7:173:11 | chk(...) | testNotNull1(...):true |
|
||||
| Guards.java:175:7:175:11 | chk(...) | testNotNull1(...):false |
|
||||
| Guards.java:179:7:179:11 | chk(...) | 's:not null' |
|
||||
| Guards.java:179:7:179:11 | chk(...) | testNotNull2(...):true |
|
||||
| Guards.java:181:7:181:11 | chk(...) | testNotNull2(...):false |
|
||||
| Guards.java:185:7:185:11 | chk(...) | '0 == getNumOrDefault(...):true' |
|
||||
| Guards.java:185:7:185:11 | chk(...) | 'getNumOrDefault(...):0' |
|
||||
| Guards.java:187:7:187:11 | chk(...) | '0 == getNumOrDefault(...):false' |
|
||||
| Guards.java:187:7:187:11 | chk(...) | 'getNumOrDefault(...):not 0' |
|
||||
| Guards.java:187:7:187:11 | chk(...) | 'i:not 0' |
|
||||
| Guards.java:187:7:187:11 | chk(...) | 'i:not null' |
|
||||
| Guards.java:191:7:191:11 | chk(...) | 'concatNonNull(...):null' |
|
||||
| Guards.java:191:7:191:11 | chk(...) | 'null == concatNonNull(...):true' |
|
||||
| Guards.java:193:7:193:11 | chk(...) | 'concatNonNull(...):not null' |
|
||||
| Guards.java:193:7:193:11 | chk(...) | 'null == concatNonNull(...):false' |
|
||||
| Guards.java:193:7:193:11 | chk(...) | 's:not null' |
|
||||
| Guards.java:198:9:198:13 | chk(...) | 'testEnumWrapper(...):SUCCESS' |
|
||||
| Guards.java:198:9:198:13 | chk(...) | 'testEnumWrapper(...):match SUCCESS' |
|
||||
| Guards.java:198:9:198:13 | chk(...) | g(1):true |
|
||||
| Guards.java:201:9:201:13 | chk(...) | 'testEnumWrapper(...):FAILURE' |
|
||||
| Guards.java:201:9:201:13 | chk(...) | 'testEnumWrapper(...):match FAILURE' |
|
||||
| Guards.java:201:9:201:13 | chk(...) | g(1):false |
|
||||
|
||||
Reference in New Issue
Block a user