Skip to content

Commit 85cca69

Browse files
authored
Merge pull request #220 from yh-semmle/java/update-tests
Java: refine `java/unreachable-catch-clause`
2 parents 6a03bd8 + c1473f5 commit 85cca69

File tree

6 files changed

+52
-6
lines changed

6 files changed

+52
-6
lines changed

change-notes/1.19/analysis-java.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Improvements to Java analysis
2+
3+
## General improvements
4+
5+
## New queries
6+
7+
| **Query** | **Tags** | **Purpose** |
8+
|-----------------------------------------------|------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
9+
10+
## Changes to existing queries
11+
12+
| **Query** | **Expected impact** | **Change** |
13+
| Unreachable catch clause (`java/unreachable-catch-clause`) | Fewer false-positive results | This rule now accounts for calls to generic methods that throw generic exceptions. |
14+
15+
## Changes to QL libraries
16+
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
FileInputStream fis = null;
1+
FileOutputStream fos = null;
22
try {
3-
fis = new FileInputStream(new File("may_not_exist.txt"));
4-
// read from input stream
3+
fos = new FileOutputStream(new File("may_not_exist.txt"));
54
} catch (FileNotFoundException e) {
65
// ask the user and try again
76
} catch (IOException e) {
87
// more serious, abort
98
} finally {
10-
if (fis!=null) { try { fis.close(); } catch (IOException e) { /*ignore*/ } }
9+
if (fos!=null) { try { fos.close(); } catch (IOException e) { /*ignore*/ } }
1110
}

java/ql/src/Likely Bugs/Statements/PartiallyMaskedCatch.qhelp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,13 @@ than one of the <code>catch</code> clauses, only the first matching clause is ex
4545
</recommendation>
4646
<example>
4747

48-
<p>In the following example, the second <code>catch</code> clause is unreachable, and can be removed.</p>
48+
<p>
49+
In the following example, the second <code>catch</code> clause is unreachable.
50+
The code is incomplete because a <code>FileOutputStream</code> is opened but
51+
no methods are called to write to the stream. Such methods typically throw
52+
<code>IOException</code>s, which would make the second <code>catch</code> clause
53+
reachable.
54+
</p>
4955

5056
<sample src="PartiallyMaskedCatch.java" />
5157

java/ql/src/Likely Bugs/Statements/PartiallyMaskedCatch.ql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ RefType getAThrownExceptionType(TryStmt t) {
4747
t.getBlock() = call.getEnclosingStmt().getParent*() or
4848
t.getAResourceDecl() = call.getEnclosingStmt()
4949
|
50-
call.getCallee().getAnException() = e and
50+
(
51+
call.getCallee().getAnException() = e or
52+
call.(GenericCall).getATypeArgument(call.getCallee().getAnException().getType()) = e.getType()
53+
) and
5154
not caughtInside(t, call.getEnclosingStmt(), e.getType()) and
5255
result = e.getType()
5356
) or

java/ql/test/.project

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>semmlecode-tests-ql</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
</buildSpec>
9+
<natures>
10+
<nature>com.semmle.plugin.qdt.core.qlnature</nature>
11+
</natures>
12+
</projectDescription>

java/ql/test/query-tests/PartiallyMaskedCatch/PartiallyMaskedCatchTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ public static void method() {
6868
} catch (IOException e) {
6969
// reachable: IOException is thrown by getClosableThing()
7070
}
71+
72+
try (ClosableThing thing = new ClosableThing()) {
73+
genericThrowingMethod(IOException.class);
74+
} catch (ExceptionA e) {
75+
// reachable: ExceptionA is thrown by implicit invocation of CloseableThing.close()
76+
} catch (IOException e) {
77+
// reachable: IOException is thrown by invocation of genericThrowingMethod(IOException.class)
78+
}
7179
}
7280

7381
public static ClosableThing getClosableThing() throws IOException {
@@ -94,4 +102,6 @@ public static void throwingMethod()
94102
throws ClassNotFoundException,
95103
NoSuchMethodException, InstantiationException, IllegalAccessException,
96104
InvocationTargetException {}
105+
106+
public static <E extends Exception> void genericThrowingMethod(Class<E> c) throws E {}
97107
}

0 commit comments

Comments
 (0)