@@ -10,6 +10,7 @@ import semmle.code.java.frameworks.YamlBeans
1010import semmle.code.java.frameworks.HessianBurlap
1111import semmle.code.java.frameworks.Castor
1212import semmle.code.java.frameworks.apache.Lang
13+ import semmle.code.java.Reflection
1314
1415class ObjectInputStreamReadObjectMethod extends Method {
1516 ObjectInputStreamReadObjectMethod ( ) {
@@ -246,21 +247,47 @@ private class UnsafeTypeConfig extends TaintTracking2::Configuration {
246247 }
247248
248249 /**
249- * Holds if `fromNode` to `toNode` is a dataflow step that looks like resolving a class.
250- *
251- * Note any method that returns a `Class` or similar is assumed to propagate taint from all
252- * of its arguments, so methods that accept user-controlled data but sanitize it or use it for some
253- * completely different purpose before returning a `Class` could result in false positives.
250+ * Holds if `fromNode` to `toNode` is a dataflow step that resolves a class
251+ * or at least looks like resolving a class.
254252 */
255253 override predicate isAdditionalTaintStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
256- exists ( MethodAccess ma , RefType returnType | returnType = ma .getMethod ( ) .getReturnType ( ) |
257- returnType instanceof JacksonTypeDescriptorType and
258- ma .getAnArgument ( ) = fromNode .asExpr ( ) and
259- ma = toNode .asExpr ( )
260- )
254+ resolveClassStep ( fromNode , toNode ) or
255+ looksLikeResolveClassStep ( fromNode , toNode )
261256 }
262257}
263258
259+ /**
260+ * Holds if `fromNode` to `toNode` is a dataflow step that resolves a class.
261+ */
262+ private predicate resolveClassStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
263+ exists ( ReflectiveClassIdentifierMethodAccess ma |
264+ ma .getArgument ( 0 ) = fromNode .asExpr ( ) and
265+ ma = toNode .asExpr ( )
266+ )
267+ }
268+
269+ /**
270+ * Holds if `fromNode` to `toNode` is a dataflow step that looks like resolving a class.
271+ * A method probably resolves a class if it is external, takes a string, returns a type descriptor
272+ * and its name contains "resolve", "load", etc.
273+ *
274+ * Any method call that satisfies the rule above is assumed to propagate taint from its string arguments,
275+ * so methods that accept user-controlled data but sanitize it or use it for some
276+ * completely different purpose before returning a type descriptor could result in false positives.
277+ */
278+ private predicate looksLikeResolveClassStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
279+ exists ( MethodAccess ma , Method m , int i , Expr arg |
280+ m = ma .getMethod ( ) and arg = ma .getArgument ( i )
281+ |
282+ m .getReturnType ( ) instanceof JacksonTypeDescriptorType and
283+ m .getName ( ) .toLowerCase ( ) .regexpMatch ( "resolve|load|class|type" ) and
284+ m .fromSource ( ) and
285+ arg .getType ( ) instanceof TypeString and
286+ arg = fromNode .asExpr ( ) and
287+ ma = toNode .asExpr ( )
288+ )
289+ }
290+
264291/**
265292 * Holds if `fromNode` to `toNode` is a dataflow step that creates a Jackson parser.
266293 *
0 commit comments