Skip to content

Commit fde7d01

Browse files
committed
Guards: Add support for wrappers that may throw exceptions.
1 parent e7bdfe1 commit fde7d01

File tree

4 files changed

+44
-0
lines changed

4 files changed

+44
-0
lines changed

java/ql/lib/semmle/code/java/controlflow/Guards.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ private module GuardsInput implements SharedGuards::InputSig<Location> {
146146

147147
class ControlFlowNode = J::ControlFlowNode;
148148

149+
class NormalExitNode = ControlFlow::NormalExitNode;
150+
151+
class ExceptionalExitNode = ControlFlow::ExceptionalExitNode;
152+
149153
class BasicBlock = J::BasicBlock;
150154

151155
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) { J::dominatingEdge(bb1, bb2) }

java/ql/test/library-tests/guards/Guards.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,14 @@ void testWrappers(String s, Integer i) {
202202
break;
203203
}
204204
}
205+
206+
static void ensureNotNull(Object o) throws Exception {
207+
if (o == null) throw new Exception();
208+
}
209+
210+
void testExceptionWrapper(String s) throws Exception {
211+
chk(); // nothing guards here
212+
ensureNotNull(s);
213+
chk(); // $ guarded='ensureNotNull(...):no exception' guarded='s:not null'
214+
}
205215
}

java/ql/test/library-tests/guards/GuardsInline.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,5 @@
112112
| Guards.java:201:9:201:13 | chk(...) | 'testEnumWrapper(...):FAILURE' |
113113
| Guards.java:201:9:201:13 | chk(...) | 'testEnumWrapper(...):match FAILURE' |
114114
| Guards.java:201:9:201:13 | chk(...) | g(1):false |
115+
| Guards.java:213:5:213:9 | chk(...) | 'ensureNotNull(...):no exception' |
116+
| Guards.java:213:5:213:9 | chk(...) | 's:not null' |

shared/controlflow/codeql/controlflow/Guards.qll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ signature module InputSig<LocationSig Location> {
7979
Location getLocation();
8080
}
8181

82+
/** A control flow node indicating normal termination of a callable. */
83+
class NormalExitNode extends ControlFlowNode;
84+
85+
/** A control flow node indicating exceptional termination of a callable. */
86+
class ExceptionalExitNode extends ControlFlowNode;
87+
8288
/**
8389
* A basic block, that is, a maximal straight-line sequence of control flow nodes
8490
* without branches or joins.
@@ -520,6 +526,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
520526
)
521527
}
522528

529+
private predicate normalExitBlock(BasicBlock bb) { bb.getNode(_) instanceof NormalExitNode }
530+
531+
private predicate exceptionalExitBlock(BasicBlock bb) {
532+
bb.getNode(_) instanceof ExceptionalExitNode
533+
}
534+
523535
signature module LogicInputSig {
524536
class SsaDefinition {
525537
/** Gets the basic block to which this SSA definition belongs. */
@@ -1047,6 +1059,16 @@ module Make<LocationSig Location, InputSig<Location> Input> {
10471059
)
10481060
}
10491061

1062+
private predicate guardDirectlyControlsExit(
1063+
Guard guard, GuardValue val, GuardValue exceptionVal
1064+
) {
1065+
exists(BasicBlock bb | guard.directlyValueControls(bb, val) |
1066+
normalExitBlock(bb) and exceptionVal = TException(false)
1067+
or
1068+
exceptionalExitBlock(bb) and exceptionVal = TException(true)
1069+
)
1070+
}
1071+
10501072
/**
10511073
* Gets a non-overridable method that performs a check on the `ppos`th
10521074
* parameter. A return value equal to `retval` allows us to conclude
@@ -1064,6 +1086,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
10641086
|
10651087
validReturnInCustomGuard(ret, ppos, retval, val)
10661088
)
1089+
or
1090+
exists(SsaDefinition param, Guard g0, GuardValue v0 |
1091+
parameterDefinition(result.getParameter(ppos), param) and
1092+
guardDirectlyControlsExit(g0, v0, retval) and
1093+
BranchImplies::ssaControls(param, val, g0, v0)
1094+
)
10671095
}
10681096

10691097
/**

0 commit comments

Comments
 (0)