Skip to content

Commit ff6c5c2

Browse files
Java: Start TaintTrackingUtils refactor
1 parent 551d86c commit ff6c5c2

File tree

2 files changed

+48
-57
lines changed

2 files changed

+48
-57
lines changed

java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 35 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,24 @@ abstract class TaintTransferringMethod extends Method {
100100
predicate transfersTaint(int src, int sink) { none() }
101101
}
102102

103+
private class StringTaintPreservingMethod extends TaintPreservingMethod {
104+
StringTaintPreservingMethod() {
105+
getDeclaringType() instanceof TypeString and
106+
hasName(["concat", "copyValueOf", "endsWith", "format", "formatted", "getBytes", "indent",
107+
"intern", "join", "repeat", "split", "strip", "stripIndent", "stripLeading",
108+
"stripTrailing", "substring", "toCharArray", "toLowerCase", "toString", "toUpperCase",
109+
"trim"])
110+
}
111+
112+
override predicate returnsTaint(int arg) {
113+
arg = -1
114+
or
115+
this.hasName(["concat", "copyValueOf"]) and arg = 0
116+
or
117+
this.hasName(["format", "formatted", "join"]) and arg = [0 .. getNumberOfParameters()]
118+
}
119+
}
120+
103121
/**
104122
* Holds if `node` should be a sanitizer in all global taint flow configurations
105123
* but not in local taint.
@@ -338,21 +356,6 @@ private predicate qualifierToMethodStep(Expr tracked, MethodAccess sink) {
338356
private predicate taintPreservingQualifierToMethod(Method m) {
339357
m instanceof CloneMethod
340358
or
341-
m.getDeclaringType() instanceof TypeString and
342-
(
343-
m.getName() = "concat" or
344-
m.getName() = "endsWith" or
345-
m.getName() = "formatted" or
346-
m.getName() = "getBytes" or
347-
m.getName() = "split" or
348-
m.getName() = "substring" or
349-
m.getName() = "toCharArray" or
350-
m.getName() = "toLowerCase" or
351-
m.getName() = "toString" or
352-
m.getName() = "toUpperCase" or
353-
m.getName() = "trim"
354-
)
355-
or
356359
exists(Class c | c.getQualifiedName() = "java.lang.Number" | hasSubtype*(c, m.getDeclaringType())) and
357360
(
358361
m.getName().matches("to%String") or
@@ -426,9 +429,6 @@ private predicate taintPreservingQualifierToMethod(Method m) {
426429
)
427430
)
428431
or
429-
m.getDeclaringType() instanceof TypeFormatter and
430-
m.hasName(["format", "out"])
431-
or
432432
m.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and
433433
// buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit)
434434
// buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit)
@@ -440,7 +440,7 @@ private predicate taintPreservingQualifierToMethod(Method m) {
440440
m.(TaintPreservingMethod).returnsTaint(-1)
441441
}
442442

443-
private class StringReplaceMethod extends Method {
443+
private class StringReplaceMethod extends TaintPreservingMethod {
444444
StringReplaceMethod() {
445445
getDeclaringType() instanceof TypeString and
446446
(
@@ -449,6 +449,8 @@ private class StringReplaceMethod extends Method {
449449
hasName("replaceFirst")
450450
)
451451
}
452+
453+
override predicate returnsTaint(int arg) { arg = 1 }
452454
}
453455

454456
private predicate unsafeEscape(MethodAccess ma) {
@@ -496,12 +498,6 @@ private predicate argToMethodStep(Expr tracked, MethodAccess sink) {
496498
* of its arguments are tainted.
497499
*/
498500
private predicate taintPreservingArgumentToMethod(Method method) {
499-
method.getDeclaringType() instanceof TypeString and
500-
(method.hasName("format") or method.hasName("formatted") or method.hasName("join"))
501-
or
502-
method.getDeclaringType() instanceof TypeFormatter and
503-
method.hasName("format")
504-
or
505501
method.getDeclaringType() instanceof TypeDatabaseUtils and
506502
// String[] appendSelectionArgs(String[] originalValues, String[] newValues)
507503
// String concatenateWhere(String a, String b)
@@ -519,8 +515,6 @@ private predicate taintPreservingArgumentToMethod(Method method) {
519515
* `arg`th argument is tainted.
520516
*/
521517
private predicate taintPreservingArgumentToMethod(Method method, int arg) {
522-
method instanceof StringReplaceMethod and arg = 1
523-
or
524518
exists(Class c | c.getQualifiedName() = "java.lang.Number" |
525519
hasSubtype*(c, method.getDeclaringType())
526520
) and
@@ -532,10 +526,6 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
532526
method.getName().matches("to%String") and arg = 0
533527
)
534528
or
535-
method.getDeclaringType() instanceof TypeString and
536-
method.getName() = "concat" and
537-
arg = 0
538-
or
539529
(
540530
method.getDeclaringType().hasQualifiedName("java.lang", "StringBuilder") or
541531
method.getDeclaringType().hasQualifiedName("java.lang", "StringBuffer")
@@ -617,11 +607,6 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
617607
exists(ProtobufMessageLite m | method = m.getAParseFromMethod()) and
618608
arg = 0
619609
or
620-
// Jackson serialization methods that return the serialized data
621-
method instanceof JacksonWriteValueMethod and
622-
method.getNumberOfParameters() = 1 and
623-
arg = 0
624-
or
625610
method.getDeclaringType().hasQualifiedName("java.io", "StringWriter") and
626611
method.hasName("append") and
627612
arg = 0
@@ -695,12 +680,6 @@ private predicate taintPreservingArgToArg(Method method, int input, int output)
695680
input = 0 and
696681
output = 2
697682
or
698-
// Jackson serialization methods that write data to the first argument
699-
method instanceof JacksonWriteValueMethod and
700-
method.getNumberOfParameters() > 1 and
701-
input = method.getNumberOfParameters() - 1 and
702-
output = 0
703-
or
704683
method.getDeclaringType() instanceof TypeSQLiteQueryBuilder and
705684
// static appendColumns(StringBuilder s, String[] columns)
706685
method.hasName("appendColumns") and
@@ -721,20 +700,6 @@ private predicate argToQualifierStep(Expr tracked, Expr sink) {
721700
tracked = ma.getArgument(i) and
722701
sink = ma.getQualifier()
723702
)
724-
or
725-
exists(MethodAccess ma |
726-
taintPreservingArgumentToQualifier(ma.getMethod()) and
727-
tracked = ma.getAnArgument() and
728-
sink = ma.getQualifier()
729-
)
730-
}
731-
732-
/**
733-
* Holds if `method` is a method that transfers taint from any of its arguments to its qualifier.
734-
*/
735-
private predicate taintPreservingArgumentToQualifier(Method method) {
736-
method.getDeclaringType() instanceof TypeFormatter and
737-
method.hasName("format")
738703
}
739704

740705
/**
@@ -892,6 +857,20 @@ private class TypeFormatter extends Class {
892857
TypeFormatter() { this.hasQualifiedName("java.util", "Formatter") }
893858
}
894859

860+
private class FormatterMethod extends TaintPreservingMethod, TaintTransferringMethod {
861+
FormatterMethod() {
862+
getDeclaringType() instanceof TypeFormatter and
863+
hasName(["format", "out", "toString"])
864+
}
865+
866+
override predicate returnsTaint(int arg) { arg = [-1 .. getNumberOfParameters()] }
867+
868+
override predicate transfersTaint(int src, int sink) {
869+
sink = -1 and
870+
src = [0 .. getNumberOfParameters()]
871+
}
872+
}
873+
895874
private import StringBuilderVarModule
896875

897876
module StringBuilderVarModule {

java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
import java
7+
import semmle.code.java.dataflow.TaintTracking::TaintTracking as TT
78
import semmle.code.java.Serializability
89
import semmle.code.java.Reflection
910
import semmle.code.java.dataflow.DataFlow
@@ -27,7 +28,7 @@ abstract class JacksonSerializableType extends Type { }
2728
* A method used for serializing objects using Jackson. The final parameter is the object to be
2829
* serialized.
2930
*/
30-
library class JacksonWriteValueMethod extends Method {
31+
library class JacksonWriteValueMethod extends TT::TaintPreservingMethod, TT::TaintTransferringMethod {
3132
JacksonWriteValueMethod() {
3233
(
3334
getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectWriter") or
@@ -36,6 +37,17 @@ library class JacksonWriteValueMethod extends Method {
3637
getName().matches("writeValue%") and
3738
getParameter(getNumberOfParameters() - 1).getType() instanceof TypeObject
3839
}
40+
41+
override predicate returnsTaint(int arg) {
42+
getNumberOfParameters() = 1 and
43+
arg = 0
44+
}
45+
46+
override predicate transfersTaint(int src, int sink) {
47+
getNumberOfParameters() > 1 and
48+
src = getNumberOfParameters() - 1 and
49+
sink = 0
50+
}
3951
}
4052

4153
/** A type whose values are explicitly serialized in a call to a Jackson method. */

0 commit comments

Comments
 (0)