Change the query to only catch the common exception rethrown case

This commit is contained in:
luchua-bc
2020-11-09 12:07:43 +00:00
parent 3f0cdb6a1a
commit a83f9ced96
4 changed files with 12 additions and 63 deletions

View File

@@ -9,48 +9,11 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.DataFlow2
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.Servlets
import semmle.code.xml.WebXML
import DataFlow::PathGraph
/** DataFlow configuration for detecting the case of rethrowing unprocessed exceptions */
class ThrowExConfiguration extends DataFlow2::Configuration {
ThrowExConfiguration() { this = "Throwing Unprocessed Exception Configuration" }
/** Source of `LocalVariableDeclExpr` */
override predicate isSource(DataFlow::Node source) {
exists(LocalVariableDeclExpr v | source.asExpr() = v.getAnAccess())
}
/** Sink of `ThrowStmt` */
override predicate isSink(DataFlow::Node sink) {
exists(ThrowStmt ts | sink.asExpr() = ts.getExpr()) // e.g. the uhex exception thrown in `catch (UnknownHostException uhex) {throw uhex;}`
}
/**
* Holds if there are additional flow steps below:
* new IOException(uhex);
* IOException ioException = new IOException(); ioException.initCause(e); throw ioException;
* IOException ioException = new IOException(); ioException.addSuppressed(e); throw ioException;
*/
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(ClassInstanceExpr cie | node1.asExpr() = cie.getAnArgument() and node2.asExpr() = cie) // catch (UnknownHostException uhex) {throw new IOException(uhex);}
or
exists(
MethodAccess ma // e.g. IOException ioException = new IOException(); ioException.addSuppressed(e); throw ioException;
|
ma.getMethod().getName() in ["initCause", "addSuppressed"] and
node1.asExpr() = ma.getAnArgument() and
(
node2.asExpr() = ma.getQualifier() or
node2.asExpr() = ma
)
)
}
}
/** Holds if a given exception type is caught. */
private predicate exceptionIsCaught(TryStmt t, RefType exType) {
exists(CatchClause cc, LocalVariableDeclExpr v |
@@ -61,9 +24,7 @@ private predicate exceptionIsCaught(TryStmt t, RefType exType) {
ThrowStmt ts // Detect the edge case that exception is caught then rethrown without processing in a catch clause
|
ts.getEnclosingStmt() = cc.getBlock() and
exists(ThrowExConfiguration tec |
tec.hasFlow(DataFlow::exprNode(v.getAnAccess()), DataFlow::exprNode(ts.getExpr()))
)
ts.getExpr() = v.getAnAccess()
)
)
}

View File

@@ -1,35 +1,19 @@
edges
| UncaughtServletException2.java:14:16:14:44 | getParameter(...) : String | UncaughtServletException2.java:15:45:15:46 | ip |
| UncaughtServletException2.java:26:16:26:44 | getParameter(...) : String | UncaughtServletException2.java:27:45:27:46 | ip |
| UncaughtServletException2.java:37:16:37:44 | getParameter(...) : String | UncaughtServletException2.java:38:45:38:46 | ip |
| UncaughtServletException2.java:49:16:49:44 | getParameter(...) : String | UncaughtServletException2.java:50:45:50:46 | ip |
| UncaughtServletException.java:13:15:13:43 | getParameter(...) : String | UncaughtServletException.java:14:44:14:45 | ip |
| UncaughtServletException.java:16:19:16:41 | getRemoteUser(...) : String | UncaughtServletException.java:17:20:17:25 | userId |
| UncaughtServletException.java:54:16:54:44 | getParameter(...) : String | UncaughtServletException.java:55:45:55:46 | ip |
| UncaughtServletException.java:74:21:74:43 | getRemoteUser(...) : String | UncaughtServletException.java:75:22:75:27 | userId |
| UncaughtServletException.java:75:21:75:43 | getRemoteUser(...) : String | UncaughtServletException.java:76:22:76:27 | userId |
nodes
| UncaughtServletException2.java:14:16:14:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UncaughtServletException2.java:15:45:15:46 | ip | semmle.label | ip |
| UncaughtServletException2.java:26:16:26:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UncaughtServletException2.java:27:45:27:46 | ip | semmle.label | ip |
| UncaughtServletException2.java:37:16:37:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UncaughtServletException2.java:38:45:38:46 | ip | semmle.label | ip |
| UncaughtServletException2.java:49:16:49:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UncaughtServletException2.java:50:45:50:46 | ip | semmle.label | ip |
| UncaughtServletException.java:13:15:13:43 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UncaughtServletException.java:14:44:14:45 | ip | semmle.label | ip |
| UncaughtServletException.java:16:19:16:41 | getRemoteUser(...) : String | semmle.label | getRemoteUser(...) : String |
| UncaughtServletException.java:17:20:17:25 | userId | semmle.label | userId |
| UncaughtServletException.java:54:16:54:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UncaughtServletException.java:55:45:55:46 | ip | semmle.label | ip |
| UncaughtServletException.java:74:21:74:43 | getRemoteUser(...) : String | semmle.label | getRemoteUser(...) : String |
| UncaughtServletException.java:75:22:75:27 | userId | semmle.label | userId |
| UncaughtServletException.java:75:21:75:43 | getRemoteUser(...) : String | semmle.label | getRemoteUser(...) : String |
| UncaughtServletException.java:76:22:76:27 | userId | semmle.label | userId |
#select
| UncaughtServletException2.java:15:45:15:46 | ip | UncaughtServletException2.java:14:16:14:44 | getParameter(...) : String | UncaughtServletException2.java:15:45:15:46 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException2.java:14:16:14:44 | getParameter(...) | User-provided value |
| UncaughtServletException2.java:27:45:27:46 | ip | UncaughtServletException2.java:26:16:26:44 | getParameter(...) : String | UncaughtServletException2.java:27:45:27:46 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException2.java:26:16:26:44 | getParameter(...) | User-provided value |
| UncaughtServletException2.java:38:45:38:46 | ip | UncaughtServletException2.java:37:16:37:44 | getParameter(...) : String | UncaughtServletException2.java:38:45:38:46 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException2.java:37:16:37:44 | getParameter(...) | User-provided value |
| UncaughtServletException2.java:50:45:50:46 | ip | UncaughtServletException2.java:49:16:49:44 | getParameter(...) : String | UncaughtServletException2.java:50:45:50:46 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException2.java:49:16:49:44 | getParameter(...) | User-provided value |
| UncaughtServletException.java:14:44:14:45 | ip | UncaughtServletException.java:13:15:13:43 | getParameter(...) : String | UncaughtServletException.java:14:44:14:45 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:13:15:13:43 | getParameter(...) | User-provided value |
| UncaughtServletException.java:17:20:17:25 | userId | UncaughtServletException.java:16:19:16:41 | getRemoteUser(...) : String | UncaughtServletException.java:17:20:17:25 | userId | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:16:19:16:41 | getRemoteUser(...) | User-provided value |
| UncaughtServletException.java:55:45:55:46 | ip | UncaughtServletException.java:54:16:54:44 | getParameter(...) : String | UncaughtServletException.java:55:45:55:46 | ip | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:54:16:54:44 | getParameter(...) | User-provided value |
| UncaughtServletException.java:75:22:75:27 | userId | UncaughtServletException.java:74:21:74:43 | getRemoteUser(...) : String | UncaughtServletException.java:75:22:75:27 | userId | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:74:21:74:43 | getRemoteUser(...) | User-provided value |
| UncaughtServletException.java:76:22:76:27 | userId | UncaughtServletException.java:75:21:75:43 | getRemoteUser(...) : String | UncaughtServletException.java:76:22:76:27 | userId | $@ flows to here and can throw uncaught exception. | UncaughtServletException.java:75:21:75:43 | getRemoteUser(...) | User-provided value |

View File

@@ -54,7 +54,8 @@ class UncaughtServletException extends HttpServlet {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
} catch (UnknownHostException uhex) {
throw new IOException(uhex);
uhex.printStackTrace();
throw uhex;
}
}

View File

@@ -9,6 +9,7 @@ import javax.servlet.ServletException;
class UncaughtServletException2 extends HttpServlet {
// BAD - Tests rethrowing caught exceptions with stack trace using `initCause(...)`
// Note this special case is not being handled by the query since in 99% of cases we're looking for `catch(Exception e) { ... throw e; }`
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
@@ -21,17 +22,18 @@ class UncaughtServletException2 extends HttpServlet {
}
// BAD - Tests rethrowing caught exceptions with stack trace using the same exception variable.
// Note this special case is not being handled by the query since in 99% of cases we're looking for `catch(Exception e) { ... throw e; }`
public void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
InetAddress addr = InetAddress.getByName(ip);
} catch (UnknownHostException uhex) {
uhex.printStackTrace();
throw uhex;
throw new IOException(uhex);
}
}
// BAD - Tests rethrowing caught exceptions with stack trace using `addSuppressed(...)`.
// Note this special case is not being handled by the query since in 99% of cases we're looking for `catch(Exception e) { ... throw e; }`
public void doTrace(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");
@@ -44,6 +46,7 @@ class UncaughtServletException2 extends HttpServlet {
}
// BAD - Tests rethrowing caught exceptions with stack trace using `initCause(...)`
// Note this special case is not being handled by the query since in 99% of cases we're looking for `catch(Exception e) { ... throw e; }`
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
String ip = request.getParameter("srcIP");