Java: Add support for additional read and store steps and additional nodes.

This commit is contained in:
Anders Schack-Mulligen
2023-09-21 11:46:17 +02:00
parent 7e04ac55b7
commit 9f905497a5
3 changed files with 76 additions and 2 deletions

View File

@@ -57,6 +57,22 @@ abstract class FluentMethod extends ValuePreservingMethod {
override predicate returnsValue(int arg) { arg = -1 }
}
/**
* A unit class for adding additional data flow nodes.
*
* Extend this class to add additional data flow nodes for use in globally
* applicable additional steps.
*/
class AdditionalDataFlowNode extends Unit {
/**
* Holds if an additional node is needed in relation to `e`. The pair `(e,id)`
* must uniquely identify the node.
* The added node can be selected for use in a predicate by the corresponding
* `DataFlow::AdditionalNode.nodeAt(Expr e, string id)` predicate.
*/
abstract predicate nodeAt(Expr e, string id);
}
/**
* A unit class for adding additional taint steps.
*
@@ -85,6 +101,36 @@ class AdditionalValueStep extends Unit {
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
}
/**
* A unit class for adding additional store steps.
*
* Extend this class to add additional store steps that should apply to all
* data flow configurations. A store step must be local, so non-local steps are
* ignored.
*/
class AdditionalStoreStep extends Unit {
/**
* Holds if the step from `node1` to `node2` is a store step of `c` and should
* apply to all data flow configurations.
*/
abstract predicate step(DataFlow::Node node1, DataFlow::Content c, DataFlow::Node node2);
}
/**
* A unit class for adding additional read steps.
*
* Extend this class to add additional read steps that should apply to all
* data flow configurations. A read step must be local, so non-local steps are
* ignored.
*/
class AdditionalReadStep extends Unit {
/**
* Holds if the step from `node1` to `node2` is a read step of `c` and should
* apply to all data flow configurations.
*/
abstract predicate step(DataFlow::Node node1, DataFlow::Content c, DataFlow::Node node2);
}
/**
* A method or constructor that preserves taint.
*

View File

@@ -3,6 +3,7 @@ private import semmle.code.java.dataflow.InstanceAccess
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.TypeFlow
private import semmle.code.java.dataflow.FlowSteps
private import DataFlowPrivate
private import DataFlowUtil
private import FlowSummaryImpl as FlowSummaryImpl
@@ -56,7 +57,8 @@ private module Cached {
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TFieldValueNode(Field f) or
TCaptureNode(CaptureFlow::SynthesizedCaptureNode cn)
TCaptureNode(CaptureFlow::SynthesizedCaptureNode cn) or
TAdditionalNode(Expr e, string id) { any(AdditionalDataFlowNode adfn).nodeAt(e, id) }
cached
newtype TContent =
@@ -133,6 +135,8 @@ module Public {
result = this.(CaptureNode).getTypeImpl()
or
result = this.(FieldValueNode).getField().getType()
or
result instanceof TypeObject and this instanceof AdditionalNode
}
/** Gets the callable in which this node occurs. */
@@ -335,6 +339,21 @@ module Public {
/** Holds if this is an access to an object's own instance. */
predicate isOwnInstanceAccess() { this.getInstanceAccess().isOwnInstanceAccess() }
}
/** A node introduced by an extension of `AdditionalDataFlowNode`. */
class AdditionalNode extends Node, TAdditionalNode {
Expr e_;
string id_;
AdditionalNode() { this = TAdditionalNode(e_, id_) }
override string toString() { result = e_.toString() + " (" + id_ + ")" }
override Location getLocation() { result = e_.getLocation() }
/** Holds if this node was introduced by `AdditionalDataFlowNode.nodeAt(e, id)`. */
predicate nodeAt(Expr e, string id) { e = e_ and id = id_ }
}
}
private import Public
@@ -378,7 +397,8 @@ module Private {
result = nodeGetEnclosingCallable(n.(ImplicitPostUpdateNode).getPreUpdateNode()) or
result.asSummarizedCallable() = n.(FlowSummaryNode).getSummarizedCallable() or
result.asCallable() = n.(CaptureNode).getSynthesizedCaptureNode().getEnclosingCallable() or
result.asFieldScope() = n.(FieldValueNode).getField()
result.asFieldScope() = n.(FieldValueNode).getField() or
result.asCallable() = any(Expr e | n.(AdditionalNode).nodeAt(e, _)).getEnclosingCallable()
}
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */

View File

@@ -228,6 +228,10 @@ predicate storeStep(Node node1, ContentSet f, Node node2) {
node2.(FlowSummaryNode).getSummaryNode())
or
captureStoreStep(node1, f, node2)
or
any(AdditionalStoreStep a).step(node1, f, node2) and
pragma[only_bind_out](node1.getEnclosingCallable()) =
pragma[only_bind_out](node2.getEnclosingCallable())
}
/**
@@ -262,6 +266,10 @@ predicate readStep(Node node1, ContentSet f, Node node2) {
node2.(FlowSummaryNode).getSummaryNode())
or
captureReadStep(node1, f, node2)
or
any(AdditionalReadStep a).step(node1, f, node2) and
pragma[only_bind_out](node1.getEnclosingCallable()) =
pragma[only_bind_out](node2.getEnclosingCallable())
}
/**