Merge pull request #5637 from Marcono1234/marcono1234/toString-method

Java: Add ToStringMethod
This commit is contained in:
Anders Schack-Mulligen
2021-04-12 11:43:55 +02:00
committed by GitHub
9 changed files with 24 additions and 27 deletions

View File

@@ -79,8 +79,7 @@ predicate stackTraceExpr(Expr exception, MethodAccess stackTraceString) {
printStackCall.getAnArgument() = printWriter and printStackCall.getAnArgument() = printWriter and
printStackCall.getQualifier() = exception and printStackCall.getQualifier() = exception and
stackTraceString.getQualifier() = stringWriterVar.getAnAccess() and stackTraceString.getQualifier() = stringWriterVar.getAnAccess() and
stackTraceString.getMethod().getName() = "toString" and stackTraceString.getMethod() instanceof ToStringMethod
stackTraceString.getMethod().getNumberOfParameters() = 0
) )
} }

View File

@@ -33,9 +33,8 @@ class InsecureAlgoLiteral extends ShortStringLiteral {
} }
predicate objectToString(MethodAccess ma) { predicate objectToString(MethodAccess ma) {
exists(Method m | exists(ToStringMethod m |
m = ma.getMethod() and m = ma.getMethod() and
m.hasName("toString") and
m.getDeclaringType() instanceof TypeObject and m.getDeclaringType() instanceof TypeObject and
variableTrack(ma.getQualifier()).getType().getErasure() instanceof TypeObject variableTrack(ma.getQualifier()).getType().getErasure() instanceof TypeObject
) )

View File

@@ -19,14 +19,14 @@ class HardcodedCredentialApiCallConfiguration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node n) { override predicate isSource(DataFlow::Node n) {
n.asExpr() instanceof HardcodedExpr and n.asExpr() instanceof HardcodedExpr and
not n.asExpr().getEnclosingCallable().getName() = "toString" not n.asExpr().getEnclosingCallable() instanceof ToStringMethod
} }
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsApiSink } override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsApiSink }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.asExpr().getType() instanceof TypeString and node1.asExpr().getType() instanceof TypeString and
exists(MethodAccess ma | ma.getMethod().getName().regexpMatch("getBytes|toCharArray") | exists(MethodAccess ma | ma.getMethod().hasName(["getBytes", "toCharArray"]) |
node2.asExpr() = ma and node2.asExpr() = ma and
ma.getQualifier() = node1.asExpr() ma.getQualifier() = node1.asExpr()
) )

View File

@@ -10,9 +10,8 @@
import java import java
from MethodAccess ma, Method tostring from MethodAccess ma, ToStringMethod tostring
where where
tostring.hasName("toString") and
tostring.getDeclaringType() instanceof TypeString and tostring.getDeclaringType() instanceof TypeString and
ma.getMethod() = tostring ma.getMethod() = tostring
select ma, "Redundant call to 'toString' on a String object." select ma, "Redundant call to 'toString' on a String object."

View File

@@ -14,20 +14,13 @@ import java
import semmle.code.java.StringFormat import semmle.code.java.StringFormat
predicate explicitToStringCall(Expr e) { predicate explicitToStringCall(Expr e) {
exists(MethodAccess ma, Method toString | toString = ma.getMethod() | exists(MethodAccess ma |
e = ma.getQualifier() and ma.getMethod() instanceof ToStringMethod and
toString.getName() = "toString" and e = ma.getQualifier()
toString.getNumberOfParameters() = 0 and
not toString.isStatic()
) )
} }
predicate directlyDeclaresToString(Class c) { predicate directlyDeclaresToString(Class c) { any(ToStringMethod m).getDeclaringType() = c }
exists(Method m | m.getDeclaringType() = c |
m.getName() = "toString" and
m.getNumberOfParameters() = 0
)
}
predicate inheritsObjectToString(Class t) { predicate inheritsObjectToString(Class t) {
not directlyDeclaresToString(t.getSourceDeclaration()) and not directlyDeclaresToString(t.getSourceDeclaration()) and

View File

@@ -68,7 +68,7 @@ predicate isBooleanTrue(Expr expr) {
or or
exists(MethodAccess ma | exists(MethodAccess ma |
expr = ma and expr = ma and
ma.getMethod().hasName("toString") and ma.getMethod() instanceof ToStringMethod and
ma.getQualifier().(FieldAccess).getField().hasName("TRUE") and ma.getQualifier().(FieldAccess).getField().hasName("TRUE") and
ma.getQualifier() ma.getQualifier()
.(FieldAccess) .(FieldAccess)

View File

@@ -353,7 +353,7 @@ class EqualsMethod extends Method {
class HashCodeMethod extends Method { class HashCodeMethod extends Method {
HashCodeMethod() { HashCodeMethod() {
this.hasName("hashCode") and this.hasName("hashCode") and
this.getNumberOfParameters() = 0 this.hasNoParameters()
} }
} }
@@ -365,6 +365,14 @@ class CloneMethod extends Method {
} }
} }
/** A method with the same signature as `java.lang.Object.toString`. */
class ToStringMethod extends Method {
ToStringMethod() {
this.hasName("toString") and
this.hasNoParameters()
}
}
/** /**
* The public static `main` method, with a single formal parameter * The public static `main` method, with a single formal parameter
* of type `String[]` and return type `void`. * of type `String[]` and return type `void`.

View File

@@ -194,7 +194,7 @@ private predicate source(RefType t, ObjNode n) {
private predicate sink(ObjNode n) { private predicate sink(ObjNode n) {
exists(MethodAccess toString | exists(MethodAccess toString |
toString.getQualifier() = n.asExpr() and toString.getQualifier() = n.asExpr() and
toString.getMethod().hasName("toString") toString.getMethod() instanceof ToStringMethod
) and ) and
n.getTypeBound().getErasure() instanceof TypeObject n.getTypeBound().getErasure() instanceof TypeObject
} }

View File

@@ -8,7 +8,8 @@ import semmle.code.java.Expr
import semmle.code.java.security.Validation import semmle.code.java.security.Validation
/** /**
* Holds if `method` is a `toString()` method on a boxed type. These never return special characters. * Holds if `method` is a `toString()` method on a boxed type, with or without parameters.
* These never return special characters.
*/ */
private predicate boxedToString(Method method) { private predicate boxedToString(Method method) {
method.getDeclaringType() instanceof BoxedType and method.getDeclaringType() instanceof BoxedType and
@@ -44,11 +45,9 @@ private predicate controlledStringProp(Expr src, Expr dest) {
exists(AddExpr concatOp | concatOp = dest | src = concatOp.getAnOperand()) exists(AddExpr concatOp | concatOp = dest | src = concatOp.getAnOperand())
or or
// `toString()` on a safe string is safe. // `toString()` on a safe string is safe.
exists(MethodAccess toStringCall, Method toString | exists(MethodAccess toStringCall |
src = toStringCall.getQualifier() and src = toStringCall.getQualifier() and
toString = toStringCall.getMethod() and toStringCall.getMethod() instanceof ToStringMethod and
toString.hasName("toString") and
toString.getNumberOfParameters() = 0 and
dest = toStringCall dest = toStringCall
) )
} }