Move value-preserving callable class into FlowSteps

This commit is contained in:
Chris Smowton
2021-03-05 11:55:53 +00:00
parent da0a7f343a
commit 990bdc20b0
3 changed files with 57 additions and 56 deletions

View File

@@ -20,6 +20,60 @@ private module Frameworks {
private import semmle.code.java.frameworks.ApacheHttp
}
/**
* A method or constructor that returns the exact value of one of its parameters or the qualifier.
*
* Extend this class and override `returnsValue` to add additional value-preserving steps through a
* method that should be added to the basic local flow step relation.
*
* These steps will be visible for all global data-flow purposes, as well as via
* `DataFlow::Node.getASuccessor` and other related functions exposing intraprocedural dataflow.
*/
abstract class ValuePreservingCallable extends Callable {
/**
* Holds if this callable returns precisely the value passed into argument `arg`.
* `arg` is a parameter index, or is -1 to indicate the qualifier.
*/
abstract predicate returnsValue(int arg);
}
/**
* A method or constructor that returns the exact value of its qualifier (e.g., `return this;`)
*
* Extend this class and override `returnsValue` to add additional value-preserving steps through a
* method that should be added to the basic local flow step relation.
*
* These steps will be visible for all global data-flow purposes, as well as via
* `DataFlow::Node.getASuccessor` and other related functions exposing intraprocedural dataflow.
*/
abstract class FluentMethod extends ValuePreservingCallable {
override predicate returnsValue(int arg) { arg = -1 }
}
private class StandardLibraryValuePreservingCallable extends ValuePreservingCallable {
int returnsArgNo;
StandardLibraryValuePreservingCallable() {
this.getDeclaringType().hasQualifiedName("java.util", "Objects") and
(
this.hasName(["requireNonNull", "requireNonNullElseGet"]) and returnsArgNo = 0
or
this.hasName("requireNonNullElse") and returnsArgNo = [0 .. this.getNumberOfParameters() - 1]
or
this.hasName("toString") and returnsArgNo = 1
)
or
this.getDeclaringType()
.getSourceDeclaration()
.getASourceSupertype*()
.hasQualifiedName("java.util", "Stack") and
this.hasName("push") and
returnsArgNo = 0
}
override predicate returnsValue(int argNo) { argNo = returnsArgNo }
}
/**
* A unit class for adding additional taint steps.
*

View File

@@ -8,6 +8,7 @@ private import semmle.code.java.dataflow.SSA
private import semmle.code.java.dataflow.TypeFlow
private import semmle.code.java.controlflow.Guards
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSteps
import semmle.code.java.dataflow.InstanceAccess
cached
@@ -368,60 +369,6 @@ predicate hasNonlocalValue(FieldRead fr) {
*/
predicate localFlowStep(Node node1, Node node2) { simpleLocalFlowStep(node1, node2) }
/**
* A method or constructor that returns the exact value of one of its parameters or the qualifier.
*
* Extend this class and override `returnsValue` to add additional value-preserving steps through a
* method that should be added to the basic local flow step relation.
*
* These steps will be visible for all global data-flow purposes, as well as via
* `DataFlow::Node.getASuccessor` and other related functions exposing intraprocedural dataflow.
*/
abstract class ValuePreservingCallable extends Callable {
/**
* Holds if this callable returns precisely the value passed into argument `arg`.
* `arg` is a parameter index, or is -1 to indicate the qualifier.
*/
abstract predicate returnsValue(int arg);
}
/**
* A method or constructor that returns the exact value of its qualifier (e.g., `return this;`)
*
* Extend this class and override `returnsValue` to add additional value-preserving steps through a
* method that should be added to the basic local flow step relation.
*
* These steps will be visible for all global data-flow purposes, as well as via
* `DataFlow::Node.getASuccessor` and other related functions exposing intraprocedural dataflow.
*/
abstract class FluentMethod extends ValuePreservingCallable {
override predicate returnsValue(int arg) { arg = -1 }
}
private class StandardLibraryValuePreservingCallable extends ValuePreservingCallable {
int returnsArgNo;
StandardLibraryValuePreservingCallable() {
this.getDeclaringType().hasQualifiedName("java.util", "Objects") and
(
this.hasName(["requireNonNull", "requireNonNullElseGet"]) and returnsArgNo = 0
or
this.hasName("requireNonNullElse") and returnsArgNo = [0 .. this.getNumberOfParameters() - 1]
or
this.hasName("toString") and returnsArgNo = 1
)
or
this.getDeclaringType()
.getSourceDeclaration()
.getASourceSupertype*()
.hasQualifiedName("java.util", "Stack") and
this.hasName("push") and
returnsArgNo = 0
}
override predicate returnsValue(int argNo) { argNo = returnsArgNo }
}
/**
* INTERNAL: do not use.
*

View File

@@ -15,11 +15,11 @@ class Conf extends DataFlow::Configuration {
}
}
class Model extends DataFlow::FluentMethod {
class Model extends FluentMethod {
Model() { this.getName() = "modelledFluentMethod" }
}
class IdentityModel extends DataFlow::ValuePreservingCallable {
class IdentityModel extends ValuePreservingCallable {
IdentityModel() { this.getName() = "modelledIdentity" }
override predicate returnsValue(int arg) { arg = 0 }