Skip to content

Commit a087d67

Browse files
SONARJAVA-5153: S1989 should not raise issue if exception is caught by try/catch block (#5314)
1 parent 46c6abf commit a087d67

File tree

2 files changed

+194
-6
lines changed

2 files changed

+194
-6
lines changed

java-checks-test-sources/default/src/main/java/checks/ServletMethodsExceptionsThrownCheckSample.java

Lines changed: 192 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
package checks;
22

3-
import play.Logger;
4-
3+
import io.vavr.control.Try;
4+
import java.io.ByteArrayOutputStream;
55
import java.io.IOException;
6+
import java.io.OutputStream;
7+
import java.io.Writer;
68
import java.net.InetAddress;
9+
import java.util.function.Consumer;
710
import javax.naming.NamingException;
811
import javax.servlet.ServletException;
912
import javax.servlet.annotation.WebServlet;
1013
import javax.servlet.http.HttpServlet;
1114
import javax.servlet.http.HttpServletRequest;
1215
import javax.servlet.http.HttpServletResponse;
13-
import java.util.function.Consumer;
14-
import io.vavr.control.Try;
16+
import play.Logger;
17+
18+
// @formatter:off
1519

1620
// http://localhost:9090/securityapp/s1989/noncompliantvavr
1721
@WebServlet(urlPatterns = "/s1989/noncompliantvavr")
@@ -146,3 +150,187 @@ protected void doPut(jakarta.servlet.http.HttpServletRequest request, jakarta.se
146150
}
147151
}
148152
}
153+
154+
// @formatter:on
155+
156+
class ShouldNotRaiseIfOuterTryCatchesException extends HttpServlet {
157+
@Override
158+
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
159+
try (Writer writer = response.getWriter()) {
160+
try {
161+
} catch (ArrayIndexOutOfBoundsException e) {
162+
}
163+
164+
// This is a regression test:
165+
// There used to be an FP here because the handling of the inner catch erased the information about the outer one.
166+
// There is no issue here, because the IOException thrown by the method below is caught by the outer try-catch
167+
writer.write("Just writing stuff."); // Compliant
168+
} catch (IOException e) {
169+
}
170+
}
171+
}
172+
173+
class ShouldHandleNestedTryCatchConstructs {
174+
static class ShouldDetectUncaughtExceptionInDoublyNestedTryCatch extends HttpServlet {
175+
@Override
176+
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
177+
try {
178+
try {
179+
throwIOException(); // Noncompliant {{Handle the following exception that could be thrown by "throwIOException": IOException.}}
180+
} catch (ArrayIndexOutOfBoundsException e) {
181+
}
182+
} catch (IllegalArgumentException e) {
183+
}
184+
}
185+
}
186+
187+
static class ShouldNotRaiseForCaughtExceptionInDoublyNestedTryCatch extends HttpServlet {
188+
@Override
189+
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
190+
try {
191+
try {
192+
throwIOException(); // Compliant
193+
} catch (ArrayIndexOutOfBoundsException e) {
194+
}
195+
} catch (IOException e) {
196+
}
197+
}
198+
199+
@Override
200+
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
201+
try {
202+
try {
203+
throwIOException(); // Compliant
204+
} catch (IOException e) {
205+
}
206+
} catch (ArrayIndexOutOfBoundsException e) {
207+
}
208+
}
209+
}
210+
211+
static class ShouldDetectUncaughtExceptionIfTryCatchIsOnLowerLevel extends HttpServlet {
212+
@Override
213+
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
214+
try {
215+
throwIOException(); // Compliant
216+
} catch (IOException e) {
217+
}
218+
219+
throwIOException(); // Noncompliant {{Handle the following exception that could be thrown by "throwIOException": IOException.}}
220+
}
221+
222+
@Override
223+
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
224+
throwIOException(); // Noncompliant {{Handle the following exception that could be thrown by "throwIOException": IOException.}}
225+
226+
try {
227+
throwIOException(); // Compliant
228+
} catch (IOException e) {
229+
}
230+
}
231+
232+
@Override
233+
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
234+
try {
235+
throwIOException(); // Noncompliant {{Handle the following exception that could be thrown by "throwIOException": IOException.}}
236+
237+
try {
238+
throwIOException(); // Compliant
239+
} catch (IOException e) {
240+
}
241+
} catch (ArrayIndexOutOfBoundsException e) {
242+
243+
}
244+
}
245+
}
246+
247+
static class ShouldDetectForMixedExceptions extends HttpServlet {
248+
@Override
249+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
250+
try {
251+
try {
252+
throwIOException(); // Compliant: Caught by inner try-catch
253+
throwServletException(); // Compliant: Caught by outer try-catch
254+
} catch (IOException e) {
255+
256+
}
257+
258+
throwIOException(); // Noncompliant {{Handle the following exception that could be thrown by "throwIOException": IOException.}}
259+
} catch (ServletException e) {
260+
261+
}
262+
}
263+
}
264+
265+
static class ShouldDetectAcrossTryWithResources extends HttpServlet {
266+
@Override
267+
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
268+
try {
269+
throwServletException();
270+
try (OutputStream stream = new ByteArrayOutputStream()) {
271+
stream.write(42); // Noncompliant {{Handle the following exception that could be thrown by "write": IOException.}}
272+
}
273+
} catch (ServletException e) {
274+
275+
}
276+
}
277+
278+
@Override
279+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
280+
try {
281+
try (OutputStream stream = new ByteArrayOutputStream()) {
282+
stream.write(42); // Compliant: Caught by outer try-catch
283+
}
284+
} catch (IOException e) {
285+
286+
}
287+
}
288+
289+
@Override
290+
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException {
291+
try (OutputStream stream = new ByteArrayOutputStream()) {
292+
try {
293+
stream.write(42); // Compliant
294+
} catch (IOException e) {
295+
296+
}
297+
}
298+
}
299+
}
300+
301+
private static void throwIOException() throws IOException {
302+
throw new IOException();
303+
}
304+
305+
private static void throwServletException() throws ServletException {
306+
throw new ServletException();
307+
}
308+
}
309+
310+
class ShouldHandleMultipleCatchBlocksInSeries extends HttpServlet {
311+
@Override
312+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
313+
try {
314+
throwIOException(); // Compliant: Caught by second catch block
315+
} catch (IllegalArgumentException e) {
316+
317+
} catch (IOException e) {
318+
319+
}
320+
}
321+
322+
@Override
323+
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
324+
try {
325+
throwIOException(); // Noncompliant {{Handle the following exception that could be thrown by "throwIOException": IOException.}}
326+
} catch (IllegalArgumentException e) {
327+
328+
} catch (IllegalStateException e) {
329+
330+
}
331+
}
332+
333+
private static void throwIOException() throws IOException {
334+
throw new IOException();
335+
}
336+
}

java-checks/src/main/java/org/sonar/java/checks/ServletMethodsExceptionsThrownCheck.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ public void visitNode(Tree tree) {
6060
shouldCheck.push(IS_SERVLET_DO_METHOD.matches((MethodTree) tree));
6161
} else if (shouldCheck()) {
6262
if (tree.is(Tree.Kind.TRY_STATEMENT)) {
63-
tryCatches.add(getCaughtExceptions(((TryStatementTree) tree).catches()));
63+
tryCatches.push(getCaughtExceptions(((TryStatementTree) tree).catches()));
6464
} else if (tree.is(Tree.Kind.CATCH)) {
6565
tryCatches.pop();
66-
tryCatches.add(Collections.emptyList());
66+
tryCatches.push(Collections.emptyList());
6767
} else if (tree.is(Tree.Kind.THROW_STATEMENT)) {
6868
addIssueIfNotCaught(((ThrowStatementTree) tree).expression().symbolType(), tree);
6969
} else if (tree.is(Tree.Kind.METHOD_INVOCATION)) {

0 commit comments

Comments
 (0)