Merge pull request #18601 from erik-krogh/del-deps-jan-2025

All: delete outdated deprecations
This commit is contained in:
Erik Krogh Kristensen
2025-01-28 13:31:41 +01:00
committed by GitHub
63 changed files with 66 additions and 3445 deletions

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* Deleted the deprecated `getAllocatorCall` predicate from `DeleteOrDeleteArrayExpr`, use `getDeallocatorCall` instead.

View File

@@ -1110,11 +1110,6 @@ class DeleteOrDeleteArrayExpr extends Expr, TDeleteOrDeleteArrayExpr {
expr_deallocator(underlyingElement(this), unresolveElement(result), _)
}
/**
* DEPRECATED: use `getDeallocatorCall` instead.
*/
deprecated FunctionCall getAllocatorCall() { result = this.getChild(0) }
/**
* Gets the call to a non-default `operator delete`/`delete[]` that deallocates storage, if any.
*

View File

@@ -0,0 +1,5 @@
---
category: breaking
---
* Deleted the deprecated `getInstanceType` predicate from the `UnboundGenericType` class.
* Deleted the deprecated `getElement` predicate from the `Node` class in `ControlFlowGraph.qll`, use `getAstNode` instead.

View File

@@ -143,18 +143,6 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric {
result = UnboundGeneric.super.getAConstructedGeneric()
}
/**
* DEPRECATED: predicate does not contain any tuples.
*
* Gets the instance type of this type. For an unbound generic type, the instance type
* is a constructed type created from the unbound type, with each of the supplied type
* arguments being the corresponding type parameter.
*/
deprecated ConstructedType getInstanceType() {
result = this.getAConstructedGeneric() and
forall(TypeParameter tp, int i | tp = this.getTypeParameter(i) | tp = result.getTypeArgument(i))
}
override Location getALocation() { type_location(this, result) }
override UnboundGenericType getUnboundDeclaration() {
@@ -312,10 +300,6 @@ class TypeParameterConstraints extends Element, @type_parameter_constraints {
* ```
*/
class UnboundGenericStruct extends Struct, UnboundGenericType {
deprecated override ConstructedStruct getInstanceType() {
result = UnboundGenericType.super.getInstanceType()
}
override ConstructedStruct getAConstructedGeneric() {
result = UnboundGenericType.super.getAConstructedGeneric()
}
@@ -335,10 +319,6 @@ class UnboundGenericStruct extends Struct, UnboundGenericType {
* ```
*/
class UnboundGenericClass extends Class, UnboundGenericType {
deprecated override ConstructedClass getInstanceType() {
result = UnboundGenericType.super.getInstanceType()
}
override ConstructedClass getAConstructedGeneric() {
result = UnboundGenericType.super.getAConstructedGeneric()
}
@@ -358,10 +338,6 @@ class UnboundGenericClass extends Class, UnboundGenericType {
* ```
*/
class UnboundGenericInterface extends Interface, UnboundGenericType {
deprecated override ConstructedInterface getInstanceType() {
result = UnboundGenericType.super.getInstanceType()
}
override ConstructedInterface getAConstructedGeneric() {
result = UnboundGenericType.super.getAConstructedGeneric()
}
@@ -382,10 +358,6 @@ class UnboundGenericInterface extends Interface, UnboundGenericType {
* ```
*/
class UnboundGenericDelegateType extends DelegateType, UnboundGenericType {
deprecated override ConstructedDelegateType getInstanceType() {
result = UnboundGenericType.super.getInstanceType()
}
override ConstructedDelegateType getAConstructedGeneric() {
result = UnboundGenericType.super.getAConstructedGeneric()
}

View File

@@ -29,13 +29,6 @@ module ControlFlow {
/** Gets the control flow element that this node corresponds to, if any. */
final ControlFlowElement getAstNode() { result = super.getAstNode() }
/**
* DEPRECATED: Use `getAstNode` instead.
*
* Gets the control flow element that this node corresponds to, if any.
*/
deprecated ControlFlowElement getElement() { result = this.getAstNode() }
/** Gets the basic block that this control flow node belongs to. */
BasicBlock getBasicBlock() { result.getANode() = this }

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* Deleted the deprecated `describeBitSize` predicate from `IncorrectIntegerConversionLib.qll`

View File

@@ -448,20 +448,6 @@ private module ConversionWithoutBoundsCheckConfig implements DataFlow::StateConf
*/
module Flow = DataFlow::GlobalWithState<ConversionWithoutBoundsCheckConfig>;
/** Gets a string describing the size of the integer parsed. */
deprecated string describeBitSize(int bitSize, int intTypeBitSize) {
intTypeBitSize in [0, 32, 64] and
if bitSize != 0
then bitSize in [8, 16, 32, 64] and result = "a " + bitSize + "-bit integer"
else
if intTypeBitSize = 0
then result = "an integer with architecture-dependent bit size"
else
result =
"a number with architecture-dependent bit-width, which is constrained to be " +
intTypeBitSize + "-bit by build constraints,"
}
/** Gets a string describing the size of the integer parsed. */
string describeBitSize2(DataFlow::Node source) {
exists(int sourceBitSize, int intTypeBitSize, boolean isSigned, string signedString |

View File

@@ -0,0 +1,11 @@
---
category: breaking
---
* Deleted the deprecated `isLValue` and `isRValue` predicates from the `VarAccess` class, use `isVarWrite` and `isVarRead` respectively instead.
* Deleted the deprecated `getRhs` predicate from the `VarWrite` class, use `getASource` instead.
* Deleted the deprecated `LValue` and `RValue` classes, use `VarWrite` and `VarRead` respectively instead.
* Deleted a lot of deprecated classes ending in "*Access", use the corresponding "*Call" classes instead.
* Deleted a lot of deprecated predicates ending in "*Access", use the corresponding "*Call" predicates instead.
* Deleted the deprecated `EnvInput` and `DatabaseInput` classes from `FlowSources.qll`, use the threat models feature instead.
* Deleted some deprecated API predicates from `SensitiveApi.qll`, use the Sink classes from that file instead.

View File

@@ -1924,9 +1924,6 @@ class VarAccess extends Expr, @varaccess {
exists(UnaryAssignExpr e | e.getExpr() = this)
}
/** DEPRECATED: Alias for `isVarWrite`. */
deprecated predicate isLValue() { this.isVarWrite() }
/**
* Holds if this variable access is a read access.
*
@@ -1936,9 +1933,6 @@ class VarAccess extends Expr, @varaccess {
*/
predicate isVarRead() { not exists(AssignExpr a | a.getDest() = this) }
/** DEPRECATED: Alias for `isVarRead`. */
deprecated predicate isRValue() { this.isVarRead() }
/** Gets a printable representation of this expression. */
override string toString() {
exists(Expr q | q = this.getQualifier() |
@@ -2002,14 +1996,8 @@ class VarWrite extends VarAccess {
* are source expressions of the assignment.
*/
Expr getASource() { exists(Assignment e | e.getDest() = this and e.getSource() = result) }
/** DEPRECATED: (Inaccurately-named) alias for `getASource` */
deprecated Expr getRhs() { result = this.getASource() }
}
/** DEPRECATED: Alias for `VarWrite`. */
deprecated class LValue = VarWrite;
/**
* A read access to a variable.
*
@@ -2021,9 +2009,6 @@ class VarRead extends VarAccess {
VarRead() { this.isVarRead() }
}
/** DEPRECATED: Alias for `VarRead`. */
deprecated class RValue = VarRead;
/** A method call is an invocation of a method with a list of arguments. */
class MethodCall extends Expr, Call, @methodaccess {
/** Gets the qualifying expression of this method access, if any. */
@@ -2082,9 +2067,6 @@ class MethodCall extends Expr, Call, @methodaccess {
*/
predicate isOwnMethodCall() { Qualifier::ownMemberAccess(this) }
/** DEPRECATED: Alias for `isOwnMethodCall`. */
deprecated predicate isOwnMethodAccess() { this.isOwnMethodCall() }
/**
* Holds if this is a method call to an instance method of the enclosing
* class `t`. That is, the qualifier is either an explicit or implicit
@@ -2092,15 +2074,9 @@ class MethodCall extends Expr, Call, @methodaccess {
*/
predicate isEnclosingMethodCall(RefType t) { Qualifier::enclosingMemberAccess(this, t) }
/** DEPRECATED: Alias for `isEnclosingMethodCall`. */
deprecated predicate isEnclosingMethodAccess(RefType t) { this.isEnclosingMethodCall(t) }
override string getAPrimaryQlClass() { result = "MethodCall" }
}
/** DEPRECATED: Alias for `MethodCall`. */
deprecated class MethodAccess = MethodCall;
/** A type access is a (possibly qualified) reference to a type. */
class TypeAccess extends Expr, Annotatable, @typeaccess {
/** Gets the qualifier of this type access, if any. */
@@ -2275,25 +2251,16 @@ class VirtualMethodCall extends MethodCall {
}
}
/** DEPRECATED: Alias for `VirtualMethodCall`. */
deprecated class VirtualMethodAccess = VirtualMethodCall;
/** A static method call. */
class StaticMethodCall extends MethodCall {
StaticMethodCall() { this.getMethod().isStatic() }
}
/** DEPRECATED: Alias for `StaticMethodCall`. */
deprecated class StaticMethodAccess = StaticMethodCall;
/** A call to a method in the superclass. */
class SuperMethodCall extends MethodCall {
SuperMethodCall() { this.getQualifier() instanceof SuperAccess }
}
/** DEPRECATED: Alias for `SuperMethodCall`. */
deprecated class SuperMethodAccess = SuperMethodCall;
/**
* A constructor call, which occurs either as a constructor invocation inside a
* constructor, or as part of a class instance expression.

View File

@@ -250,9 +250,6 @@ class MethodCallSystemGetProperty extends MethodCall {
}
}
/** DEPRECATED: Alias for `MethodCallSystemGetProperty`. */
deprecated class MethodAccessSystemGetProperty = MethodCallSystemGetProperty;
/**
* Any method named `exit` on class `java.lang.Runtime` or `java.lang.System`.
*/

View File

@@ -83,9 +83,6 @@ class ReflectiveClassIdentifierMethodCall extends ReflectiveClassIdentifier, Met
}
}
/** DEPRECATED: Alias for `ReflectiveClassIdentifierMethodCall`. */
deprecated class ReflectiveClassIdentifierMethodAccess = ReflectiveClassIdentifierMethodCall;
/**
* Gets a `ReflectiveClassIdentifier` that we believe may represent the value of `expr`.
*/
@@ -320,9 +317,6 @@ class ClassMethodCall extends MethodCall {
}
}
/** DEPRECATED: Alias for `ClassMethodCall`. */
deprecated class ClassMethodAccess = ClassMethodCall;
/**
* A call to `Class.getConstructors(..)` or `Class.getDeclaredConstructors(..)`.
*/
@@ -333,9 +327,6 @@ class ReflectiveGetConstructorsCall extends ClassMethodCall {
}
}
/** DEPRECATED: Alias for `ReflectiveGetConstructorsCall`. */
deprecated class ReflectiveConstructorsAccess = ReflectiveGetConstructorsCall;
/**
* A call to `Class.getMethods(..)` or `Class.getDeclaredMethods(..)`.
*/
@@ -346,9 +337,6 @@ class ReflectiveGetMethodsCall extends ClassMethodCall {
}
}
/** DEPRECATED: Alias for `ReflectiveGetMethodsCall`. */
deprecated class ReflectiveMethodsAccess = ReflectiveGetMethodsCall;
/**
* A call to `Class.getMethod(..)` or `Class.getDeclaredMethod(..)`.
*/
@@ -378,9 +366,6 @@ class ReflectiveGetMethodCall extends ClassMethodCall {
}
}
/** DEPRECATED: Alias for `ReflectiveGetMethodCall`. */
deprecated class ReflectiveMethodAccess = ReflectiveGetMethodCall;
/**
* A call to `Class.getAnnotation(..)`.
*/
@@ -395,9 +380,6 @@ class ReflectiveGetAnnotationCall extends ClassMethodCall {
}
}
/** DEPRECATED: Alias for `ReflectiveGetAnnotationCall`. */
deprecated class ReflectiveAnnotationAccess = ReflectiveGetAnnotationCall;
/**
* A call to `Class.getField(..)` that accesses a field.
*/
@@ -423,6 +405,3 @@ class ReflectiveGetFieldCall extends ClassMethodCall {
result.hasName(this.getArgument(0).(StringLiteral).getValue())
}
}
/** DEPRECATED: Alias for `ReflectiveGetFieldCall`. */
deprecated class ReflectiveFieldAccess = ReflectiveGetFieldCall;

View File

@@ -200,25 +200,6 @@ abstract class LocalUserInput extends UserInput {
override string getThreatModel() { result = "local" }
}
/**
* DEPRECATED: Use the threat models feature.
* That is, use `ActiveThreatModelSource` as the class of nodes for sources
* and set up the threat model configuration to filter source nodes.
* Alternatively, use `getThreatModel` to filter nodes to create the
* class of nodes you need.
*
* A node with input from the local environment, such as files, standard in,
* environment variables, and main method parameters.
*/
deprecated class EnvInput extends DataFlow::Node {
EnvInput() {
this instanceof EnvironmentInput or
this instanceof CliInput or
this instanceof FileInput or
this instanceof StdinInput
}
}
/**
* A node with input from the local environment, such as
* environment variables.
@@ -271,17 +252,6 @@ private class FileInput extends LocalUserInput {
override string getThreatModel() { result = "file" }
}
/**
* DEPRECATED: Use the threat models feature.
* That is, use `ActiveThreatModelSource` as the class of nodes for sources
* and set up the threat model configuration to filter source nodes.
* Alternatively, use `getThreatModel` to filter nodes to create the
* class of nodes you need.
*
* A node with input from a database.
*/
deprecated class DatabaseInput = DbInput;
/**
* A node with input from a database.
*/

View File

@@ -484,9 +484,6 @@ class ObjectOutputStreamVar extends LocalVariableDecl {
result.getQualifier() = this.getAnAccess() and
result.getMethod().hasName("writeObject")
}
/** DEPRECATED: Alias for `getAWriteObjectMethodCall`. */
deprecated MethodCall getAWriteObjectMethodAccess() { result = this.getAWriteObjectMethodCall() }
}
/** Flow through string formatting. */

View File

@@ -168,9 +168,6 @@ class ReflectiveGetMethodCallEntryPoint extends EntryPoint, ReflectiveGetMethodC
}
}
/** DEPRECATED: Alias for `ReflectiveGetMethodCallEntryPoint`. */
deprecated class ReflectiveMethodAccessEntryPoint = ReflectiveGetMethodCallEntryPoint;
/**
* Classes that are entry points recognised by annotations.
*/

View File

@@ -25,9 +25,6 @@ class MockitoVerifiedMethodCall extends MethodCall {
}
}
/** DEPRECATED: Alias for `MockitoVerifiedMethodCall`. */
deprecated class MockitoVerifiedMethodAccess = MockitoVerifiedMethodCall;
/**
* A type that can be mocked by Mockito.
*/

View File

@@ -45,9 +45,6 @@ class LocalDatabaseOpenMethodCall extends Storable, Call {
}
}
/** DEPRECATED: Alias for `LocalDatabaseOpenMethodCall`. */
deprecated class LocalDatabaseOpenMethodAccess = LocalDatabaseOpenMethodCall;
/** A method that is both a database input and a database store. */
private class LocalDatabaseInputStoreMethod extends Method {
LocalDatabaseInputStoreMethod() {

View File

@@ -45,9 +45,6 @@ class SharedPreferencesEditorMethodCall extends Storable, MethodCall {
}
}
/** DEPRECATED: Alias for `SharedPreferencesEditorMethodCall`. */
deprecated class SharedPreferencesEditorMethodAccess = SharedPreferencesEditorMethodCall;
/**
* Holds if `input` is the second argument of a setter method
* called on `editor`, which is an instance of `SharedPreferences$Editor`.

View File

@@ -12,9 +12,6 @@ class EqualsCall extends MethodCall {
EqualsCall() { this.getMethod() instanceof EqualsMethod }
}
/** DEPRECATED: Alias for `EqualsCall`. */
deprecated class EqualsAccess = EqualsCall;
/**
* Holds if `sink` compares password `p` against a hardcoded expression `source`.
*/

View File

@@ -44,9 +44,6 @@ class JwtParserWithInsecureParseSink extends ApiSinkNode {
/** Gets the method access that does the insecure parsing. */
MethodCall getParseMethodCall() { result = insecureParseMa }
/** DEPRECATED: Alias for `getParseMethodCall`. */
deprecated MethodCall getParseMethodAccess() { result = this.getParseMethodCall() }
}
/**

View File

@@ -58,6 +58,3 @@ class PartialPathTraversalMethodCall extends MethodCall {
not isSafe(this.getArgument(0))
}
}
/** DEPRECATED: Alias for `PartialPathTraversalMethodCall`. */
deprecated class PartialPathTraversalMethodAccess = PartialPathTraversalMethodCall;

View File

@@ -65,9 +65,6 @@ class SensitiveMethodCall extends SensitiveExpr, MethodCall {
}
}
/** DEPRECATED: Alias for `SensitiveMethodCall`. */
deprecated class SensitiveMethodAccess = SensitiveMethodCall;
/** Access to a variable that might contain sensitive data. */
class SensitiveVarAccess extends SensitiveExpr, VarAccess {
SensitiveVarAccess() {

View File

@@ -31,42 +31,3 @@ class UsernameSink extends CredentialsSinkNode {
class CryptoKeySink extends CredentialsSinkNode {
CryptoKeySink() { sinkNode(this, "credentials-key") }
}
/**
* DEPRECATED: Use the `PasswordSink` class instead.
* Holds if callable `c` from a standard Java API expects a password parameter at index `i`.
*/
deprecated predicate javaApiCallablePasswordParam(Callable c, int i) {
exists(PasswordSink sink, MethodCall mc |
sink.asExpr() = mc.getArgument(i) and c = mc.getCallee()
)
}
/**
* DEPRECATED: Use the `UsernameSink` class instead.
* Holds if callable `c` from a standard Java API expects a username parameter at index `i`.
*/
deprecated predicate javaApiCallableUsernameParam(Callable c, int i) {
exists(UsernameSink sink, MethodCall mc |
sink.asExpr() = mc.getArgument(i) and c = mc.getCallee()
)
}
/**
* DEPRECATED: Use the `CryptoKeySink` class instead.
* Holds if callable `c` from a standard Java API expects a cryptographic key parameter at index `i`.
*/
deprecated predicate javaApiCallableCryptoKeyParam(Callable c, int i) {
exists(CryptoKeySink sink, MethodCall mc |
sink.asExpr() = mc.getArgument(i) and c = mc.getCallee()
)
}
/**
* DEPRECATED: Use the `CredentialsSinkNode` class instead.
* Holds if callable `c` from a known API expects a credential parameter at index `i`.
*/
deprecated predicate otherApiCallableCredentialParam(Callable c, int i) {
c.hasQualifiedName("javax.crypto.spec", "IvParameterSpec", "IvParameterSpec") and
i = 0
}

View File

@@ -215,9 +215,6 @@ abstract class MethodCallInsecureFileCreation extends MethodCall {
DataFlow::Node getNode() { result.asExpr() = this }
}
/** DEPRECATED: Alias for `MethodCallInsecureFileCreation`. */
deprecated class MethodAccessInsecureFileCreation = MethodCallInsecureFileCreation;
/**
* An insecure call to `java.io.File.createTempFile`.
*/
@@ -236,9 +233,6 @@ class MethodCallInsecureFileCreateTempFile extends MethodCallInsecureFileCreatio
override string getFileSystemEntityType() { result = "file" }
}
/** DEPRECATED: Alias for `MethodCallInsecureFileCreateTempFile`. */
deprecated class MethodAccessInsecureFileCreateTempFile = MethodCallInsecureFileCreateTempFile;
/**
* The `com.google.common.io.Files.createTempDir` method.
*/
@@ -259,7 +253,3 @@ class MethodCallInsecureGuavaFilesCreateTempFile extends MethodCallInsecureFileC
override string getFileSystemEntityType() { result = "directory" }
}
/** DEPRECATED: Alias for `MethodCallInsecureGuavaFilesCreateTempFile`. */
deprecated class MethodAccessInsecureGuavaFilesCreateTempFile =
MethodCallInsecureGuavaFilesCreateTempFile;

View File

@@ -240,9 +240,6 @@ class UnsafeDeserializationSink extends ApiSinkNode, DataFlow::ExprNode {
/** Gets a call that triggers unsafe deserialization. */
MethodCall getMethodCall() { unsafeDeserialization(result, this.getExpr()) }
/** DEPRECATED: Alias for `getMethodCall`. */
deprecated MethodCall getMethodAccess() { result = this.getMethodCall() }
}
/** Holds if `node` is a sanitizer for unsafe deserialization */

View File

@@ -550,21 +550,10 @@ class XmlReaderConfig extends ParserConfig {
}
}
deprecated private module ExplicitlySafeXmlReaderFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ExplicitlySafeXmlReader }
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SafeXmlReaderFlowSink }
int fieldFlowBranchLimit() { result = 0 }
}
private predicate explicitlySafeXmlReaderNode(DataFlow::Node src) {
src.asExpr() instanceof ExplicitlySafeXmlReader
}
deprecated private module ExplicitlySafeXmlReaderFlowDeprecated =
DataFlow::Global<ExplicitlySafeXmlReaderFlowConfig>;
private module ExplicitlySafeXmlReaderFlow = DataFlow::SimpleGlobal<explicitlySafeXmlReaderNode/1>;
/** An argument to a safe XML reader. */
@@ -608,28 +597,12 @@ class ExplicitlySafeXmlReader extends VarAccess {
)
)
}
/** DEPRECATED. Holds if `SafeXmlReaderFlowSink` detects flow from this to `sink` */
deprecated predicate flowsTo(SafeXmlReaderFlowSink sink) {
ExplicitlySafeXmlReaderFlowDeprecated::flow(DataFlow::exprNode(this), DataFlow::exprNode(sink))
}
}
deprecated private module CreatedSafeXmlReaderFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CreatedSafeXmlReader }
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SafeXmlReaderFlowSink }
int fieldFlowBranchLimit() { result = 0 }
}
private predicate createdSafeXmlReaderNode(DataFlow::Node src) {
src.asExpr() instanceof CreatedSafeXmlReader
}
deprecated private module CreatedSafeXmlReaderFlowDeprecated =
DataFlow::Global<CreatedSafeXmlReaderFlowConfig>;
private module CreatedSafeXmlReaderFlow = DataFlow::SimpleGlobal<createdSafeXmlReaderNode/1>;
/** An `XmlReader` that is obtained from a safe source. */
@@ -651,11 +624,6 @@ class CreatedSafeXmlReader extends Call {
package.matches("com.google.%common.xml.parsing")
)
}
/** DEPRECATED. Holds if `CreatedSafeXmlReaderFlowConfig` detects flow from this to `sink` */
deprecated predicate flowsTo(SafeXmlReaderFlowSink sink) {
CreatedSafeXmlReaderFlowDeprecated::flow(DataFlow::exprNode(this), DataFlow::exprNode(sink))
}
}
/*
@@ -816,7 +784,7 @@ class TransformerFactorySource extends XmlParserCall {
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() {
SafeTransformerFactoryFlow2::flowsTo(DataFlow::exprNode(this.getQualifier()))
SafeTransformerFactoryFlow::flowsTo(DataFlow::exprNode(this.getQualifier()))
}
}
@@ -831,38 +799,11 @@ class TransformerFactoryConfig extends TransformerConfig {
}
}
/**
* DEPRECATED.
*
* A dataflow configuration that identifies `TransformerFactory` and `SAXTransformerFactory`
* instances that have been safely configured.
*/
deprecated module SafeTransformerFactoryFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeTransformerFactory }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod().getDeclaringType() instanceof TransformerFactory
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private predicate safeTransformerFactoryNode(DataFlow::Node src) {
src.asExpr() instanceof SafeTransformerFactory
}
/**
* DEPRECATED.
*
* Identifies `TransformerFactory` and `SAXTransformerFactory`
* instances that have been safely configured.
*/
deprecated module SafeTransformerFactoryFlow = DataFlow::Global<SafeTransformerFactoryFlowConfig>;
private module SafeTransformerFactoryFlow2 = DataFlow::SimpleGlobal<safeTransformerFactoryNode/1>;
private module SafeTransformerFactoryFlow = DataFlow::SimpleGlobal<safeTransformerFactoryNode/1>;
/** A safely configured `TransformerFactory`. */
class SafeTransformerFactory extends VarAccess {
@@ -885,7 +826,7 @@ class SafeTransformer extends MethodCall {
this.getMethod() = m and
m.getDeclaringType() instanceof TransformerFactory and
m.hasName("newTransformer") and
SafeTransformerFactoryFlow2::flowsTo(DataFlow::exprNode(this.getQualifier()))
SafeTransformerFactoryFlow::flowsTo(DataFlow::exprNode(this.getQualifier()))
)
}
}
@@ -908,7 +849,7 @@ class SaxTransformerFactoryNewXmlFilter extends XmlParserCall {
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() {
SafeTransformerFactoryFlow2::flowsTo(DataFlow::exprNode(this.getQualifier()))
SafeTransformerFactoryFlow::flowsTo(DataFlow::exprNode(this.getQualifier()))
}
}

View File

@@ -54,9 +54,6 @@ class SqlResourceOpeningMethodCall extends MethodCall {
}
}
/** DEPRECATED: Alias for `SqlResourceOpeningMethodCall`. */
deprecated class SqlResourceOpeningMethodAccess = SqlResourceOpeningMethodCall;
/**
* A candidate for a "closeable init" expression, which may require calling a "close" method.
*/

View File

@@ -0,0 +1,6 @@
---
category: breaking
---
* Deleted the old deprecated TypeTracking library.
* Deleted the deprecated `classRef` predicate from the `FieldStorage` module, use `subclassRef` instead.
* Deleted a lot of deprecated modules and predicates from `Stdlib.qll`, use API-graphs directly instead.

View File

@@ -1,70 +0,0 @@
/**
* DEPRECATED: Use `semmle.python.dataflow.new.TypeTracking` instead.
*
* This file acts as a wrapper for `internal.TypeTracker`, exposing some of the functionality with
* names that are more appropriate for Python.
*/
private import python
private import internal.TypeTracker as Internal
private import internal.TypeTrackerSpecific as InternalSpecific
/** A string that may appear as the name of an attribute or access path. */
deprecated class AttributeName = InternalSpecific::TypeTrackerContent;
/** An attribute name, or the empty string (representing no attribute). */
deprecated class OptionalAttributeName = InternalSpecific::OptionalTypeTrackerContent;
/**
* DEPRECATED: Use `semmle.python.dataflow.new.TypeTracking` instead.
*
* The summary of the steps needed to track a value to a given dataflow node.
*
* This can be used to track objects that implement a certain API in order to
* recognize calls to that API. Note that type-tracking does not by itself provide a
* source/sink relation, that is, it may determine that a node has a given type,
* but it won't determine where that type came from.
*
* It is recommended that all uses of this type are written in the following form,
* for tracking some type `myType`:
* ```ql
* DataFlow::TypeTrackingNode myType(DataFlow::TypeTracker t) {
* t.start() and
* result = < source of myType >
* or
* exists (DataFlow::TypeTracker t2 |
* result = myType(t2).track(t2, t)
* )
* }
*
* DataFlow::LocalSourceNode myType() { myType(DataFlow::TypeTracker::end()) }
* ```
*
* Instead of `result = myType(t2).track(t2, t)`, you can also use the equivalent
* `t = t2.step(myType(t2), result)`. If you additionally want to track individual
* intra-procedural steps, use `t = t2.smallstep(myCallback(t2), result)`.
*/
deprecated class TypeTracker extends Internal::TypeTracker {
/**
* Holds if this is the starting point of type tracking, and the value starts in the attribute named `attrName`.
* The type tracking only ends after the attribute has been loaded.
*/
predicate startInAttr(string attrName) { this.startInContent(attrName) }
/**
* INTERNAL. DO NOT USE.
*
* Gets the attribute associated with this type tracker.
*/
string getAttr() { result = this.getContent() }
}
deprecated module TypeTracker = Internal::TypeTracker;
deprecated class StepSummary = Internal::StepSummary;
deprecated module StepSummary = Internal::StepSummary;
deprecated class TypeBackTracker = Internal::TypeBackTracker;
deprecated module TypeBackTracker = Internal::TypeBackTracker;

View File

@@ -1,957 +0,0 @@
/** Step Summaries and Type Tracking */
private import TypeTrackerSpecific
private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic
cached
private module Cached {
/**
* A description of a step on an inter-procedural data flow path.
*/
cached
deprecated newtype TStepSummary =
LevelStep() or
CallStep() or
ReturnStep() or
deprecated StoreStep(TypeTrackerContent content) {
exists(DataFlowPublic::AttributeContent dfc | dfc.getAttribute() = content |
basicStoreStep(_, _, dfc)
)
} or
deprecated LoadStep(TypeTrackerContent content) {
exists(DataFlowPublic::AttributeContent dfc | dfc.getAttribute() = content |
basicLoadStep(_, _, dfc)
)
} or
deprecated LoadStoreStep(TypeTrackerContent load, TypeTrackerContent store) {
exists(DataFlowPublic::AttributeContent dfcLoad, DataFlowPublic::AttributeContent dfcStore |
dfcLoad.getAttribute() = load and dfcStore.getAttribute() = store
|
basicLoadStoreStep(_, _, dfcLoad, dfcStore)
)
} or
deprecated WithContent(ContentFilter filter) { basicWithContentStep(_, _, filter) } or
deprecated WithoutContent(ContentFilter filter) { basicWithoutContentStep(_, _, filter) } or
JumpStep()
cached
deprecated newtype TTypeTracker =
deprecated MkTypeTracker(Boolean hasCall, OptionalTypeTrackerContent content) {
content = noContent()
or
// Restrict `content` to those that might eventually match a load.
// We can't rely on `basicStoreStep` since `startInContent` might be used with
// a content that has no corresponding store.
exists(DataFlowPublic::AttributeContent loadContents |
(
basicLoadStep(_, _, loadContents)
or
basicLoadStoreStep(_, _, loadContents, _)
) and
compatibleContents(content, loadContents.getAttribute())
)
}
cached
deprecated newtype TTypeBackTracker =
deprecated MkTypeBackTracker(Boolean hasReturn, OptionalTypeTrackerContent content) {
content = noContent()
or
// As in MkTypeTracker, restrict `content` to those that might eventually match a store.
exists(DataFlowPublic::AttributeContent storeContent |
(
basicStoreStep(_, _, storeContent)
or
basicLoadStoreStep(_, _, _, storeContent)
) and
compatibleContents(storeContent.getAttribute(), content)
)
}
/** Gets a type tracker with no content and the call bit set to the given value. */
cached
deprecated TypeTracker noContentTypeTracker(boolean hasCall) {
result = MkTypeTracker(hasCall, noContent())
}
/** Gets the summary resulting from appending `step` to type-tracking summary `tt`. */
cached
deprecated TypeTracker append(TypeTracker tt, StepSummary step) {
exists(Boolean hasCall, OptionalTypeTrackerContent currentContents |
tt = MkTypeTracker(hasCall, currentContents)
|
step = LevelStep() and result = tt
or
step = CallStep() and result = MkTypeTracker(true, currentContents)
or
step = ReturnStep() and hasCall = false and result = tt
or
step = JumpStep() and
result = MkTypeTracker(false, currentContents)
or
exists(ContentFilter filter | result = tt |
step = WithContent(filter) and
currentContents = filter.getAMatchingContent()
or
step = WithoutContent(filter) and
not currentContents = filter.getAMatchingContent()
)
)
or
exists(TypeTrackerContent storeContents, boolean hasCall |
exists(TypeTrackerContent loadContents |
step = LoadStep(pragma[only_bind_into](loadContents)) and
tt = MkTypeTracker(hasCall, storeContents) and
compatibleContents(storeContents, loadContents) and
result = noContentTypeTracker(hasCall)
)
or
step = StoreStep(pragma[only_bind_into](storeContents)) and
tt = noContentTypeTracker(hasCall) and
result = MkTypeTracker(hasCall, storeContents)
)
or
exists(
TypeTrackerContent currentContent, TypeTrackerContent store, TypeTrackerContent load,
boolean hasCall
|
step = LoadStoreStep(pragma[only_bind_into](load), pragma[only_bind_into](store)) and
compatibleContents(pragma[only_bind_into](currentContent), load) and
tt = MkTypeTracker(pragma[only_bind_into](hasCall), currentContent) and
result = MkTypeTracker(pragma[only_bind_out](hasCall), store)
)
}
pragma[nomagic]
deprecated private TypeBackTracker noContentTypeBackTracker(boolean hasReturn) {
result = MkTypeBackTracker(hasReturn, noContent())
}
/** Gets the summary resulting from prepending `step` to this type-tracking summary. */
cached
deprecated TypeBackTracker prepend(TypeBackTracker tbt, StepSummary step) {
exists(Boolean hasReturn, OptionalTypeTrackerContent content |
tbt = MkTypeBackTracker(hasReturn, content)
|
step = LevelStep() and result = tbt
or
step = CallStep() and hasReturn = false and result = tbt
or
step = ReturnStep() and result = MkTypeBackTracker(true, content)
or
step = JumpStep() and
result = MkTypeBackTracker(false, content)
or
exists(ContentFilter filter | result = tbt |
step = WithContent(filter) and
content = filter.getAMatchingContent()
or
step = WithoutContent(filter) and
not content = filter.getAMatchingContent()
)
)
or
exists(TypeTrackerContent loadContents, boolean hasReturn |
exists(TypeTrackerContent storeContents |
step = StoreStep(pragma[only_bind_into](storeContents)) and
tbt = MkTypeBackTracker(hasReturn, loadContents) and
compatibleContents(storeContents, loadContents) and
result = noContentTypeBackTracker(hasReturn)
)
or
step = LoadStep(pragma[only_bind_into](loadContents)) and
tbt = noContentTypeBackTracker(hasReturn) and
result = MkTypeBackTracker(hasReturn, loadContents)
)
or
exists(
TypeTrackerContent currentContent, TypeTrackerContent store, TypeTrackerContent load,
boolean hasCall
|
step = LoadStoreStep(pragma[only_bind_into](load), pragma[only_bind_into](store)) and
compatibleContents(store, pragma[only_bind_into](currentContent)) and
tbt = MkTypeBackTracker(pragma[only_bind_into](hasCall), currentContent) and
result = MkTypeBackTracker(pragma[only_bind_out](hasCall), load)
)
}
/**
* Gets the summary that corresponds to having taken a forwards
* heap and/or intra-procedural step from `nodeFrom` to `nodeTo`.
*
* Steps contained in this predicate should _not_ depend on the call graph.
*/
cached
deprecated predicate stepNoCall(
TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo, StepSummary summary
) {
exists(Node mid | nodeFrom.flowsTo(mid) and smallstepNoCall(mid, nodeTo, summary))
}
/**
* Gets the summary that corresponds to having taken a forwards
* inter-procedural step from `nodeFrom` to `nodeTo`.
*/
cached
deprecated predicate stepCall(
TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo, StepSummary summary
) {
exists(Node mid | nodeFrom.flowsTo(mid) and smallstepCall(mid, nodeTo, summary))
}
cached
deprecated predicate smallstepNoCall(Node nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
jumpStep(nodeFrom, nodeTo) and
summary = JumpStep()
or
levelStepNoCall(nodeFrom, nodeTo) and
summary = LevelStep()
or
exists(TypeTrackerContent content |
flowsToStoreStep(nodeFrom, nodeTo, content) and
summary = StoreStep(content)
or
exists(DataFlowPublic::AttributeContent dfc | dfc.getAttribute() = content |
basicLoadStep(nodeFrom, nodeTo, dfc)
) and
summary = LoadStep(content)
)
or
exists(TypeTrackerContent loadContent, TypeTrackerContent storeContent |
flowsToLoadStoreStep(nodeFrom, nodeTo, loadContent, storeContent) and
summary = LoadStoreStep(loadContent, storeContent)
)
or
exists(ContentFilter filter |
basicWithContentStep(nodeFrom, nodeTo, filter) and
summary = WithContent(filter)
or
basicWithoutContentStep(nodeFrom, nodeTo, filter) and
summary = WithoutContent(filter)
)
}
cached
deprecated predicate smallstepCall(Node nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
callStep(nodeFrom, nodeTo) and summary = CallStep()
or
returnStep(nodeFrom, nodeTo) and
summary = ReturnStep()
or
levelStepCall(nodeFrom, nodeTo) and
summary = LevelStep()
}
}
private import Cached
deprecated private predicate step(
TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo, StepSummary summary
) {
stepNoCall(nodeFrom, nodeTo, summary)
or
stepCall(nodeFrom, nodeTo, summary)
}
pragma[nomagic]
deprecated private predicate stepProj(TypeTrackingNode nodeFrom, StepSummary summary) {
step(nodeFrom, _, summary)
}
deprecated private predicate smallstep(Node nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
smallstepNoCall(nodeFrom, nodeTo, summary)
or
smallstepCall(nodeFrom, nodeTo, summary)
}
pragma[nomagic]
deprecated private predicate smallstepProj(Node nodeFrom, StepSummary summary) {
smallstep(nodeFrom, _, summary)
}
/**
* Holds if `nodeFrom` is being written to the `content` of the object in `nodeTo`.
*
* Note that `nodeTo` will always be a local source node that flows to the place where the content
* is written in `basicStoreStep`. This may lead to the flow of information going "back in time"
* from the point of view of the execution of the program.
*
* For instance, if we interpret attribute writes in Python as writing to content with the same
* name as the attribute and consider the following snippet
*
* ```python
* def foo(y):
* x = Foo()
* bar(x)
* x.attr = y
* baz(x)
*
* def bar(x):
* z = x.attr
* ```
* for the attribute write `x.attr = y`, we will have `content` being the literal string `"attr"`,
* `nodeFrom` will be `y`, and `nodeTo` will be the object `Foo()` created on the first line of the
* function. This means we will track the fact that `x.attr` can have the type of `y` into the
* assignment to `z` inside `bar`, even though this attribute write happens _after_ `bar` is called.
*/
deprecated private predicate flowsToStoreStep(
Node nodeFrom, TypeTrackingNode nodeTo, TypeTrackerContent content
) {
exists(Node obj |
nodeTo.flowsTo(obj) and
exists(DataFlowPublic::AttributeContent dfc | dfc.getAttribute() = content |
basicStoreStep(nodeFrom, obj, dfc)
)
)
}
/**
* Holds if `loadContent` is loaded from `nodeFrom` and written to `storeContent` of `nodeTo`.
*/
deprecated private predicate flowsToLoadStoreStep(
Node nodeFrom, TypeTrackingNode nodeTo, TypeTrackerContent loadContent,
TypeTrackerContent storeContent
) {
exists(Node obj |
nodeTo.flowsTo(obj) and
exists(DataFlowPublic::AttributeContent loadDfc, DataFlowPublic::AttributeContent storeDfc |
loadDfc.getAttribute() = loadContent and storeDfc.getAttribute() = storeContent
|
basicLoadStoreStep(nodeFrom, obj, loadDfc, storeDfc)
)
)
}
/**
* INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead.
*
* A description of a step on an inter-procedural data flow path.
*/
deprecated class StepSummary extends TStepSummary {
/** Gets a textual representation of this step summary. */
string toString() {
this instanceof LevelStep and result = "level"
or
this instanceof CallStep and result = "call"
or
this instanceof ReturnStep and result = "return"
or
exists(TypeTrackerContent content | this = StoreStep(content) | result = "store " + content)
or
exists(TypeTrackerContent content | this = LoadStep(content) | result = "load " + content)
or
exists(TypeTrackerContent load, TypeTrackerContent store |
this = LoadStoreStep(load, store) and
result = "load-store " + load + " -> " + store
)
or
this instanceof JumpStep and result = "jump"
}
}
/** Provides predicates for updating step summaries (`StepSummary`s). */
deprecated module StepSummary {
predicate append = Cached::append/2;
/**
* Gets the summary that corresponds to having taken a forwards
* inter-procedural step from `nodeFrom` to `nodeTo`.
*
* This predicate should normally not be used; consider using `step`
* instead.
*/
predicate stepCall = Cached::stepCall/3;
/**
* Gets the summary that corresponds to having taken a forwards
* intra-procedural step from `nodeFrom` to `nodeTo`.
*
* This predicate should normally not be used; consider using `step`
* instead.
*/
predicate stepNoCall = Cached::stepNoCall/3;
/**
* Gets the summary that corresponds to having taken a forwards
* heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*/
predicate step(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
stepNoCall(nodeFrom, nodeTo, summary)
or
stepCall(nodeFrom, nodeTo, summary)
}
/**
* Gets the summary that corresponds to having taken a forwards
* inter-procedural step from `nodeFrom` to `nodeTo`.
*
* This predicate should normally not be used; consider using `step`
* instead.
*/
predicate smallstepNoCall = Cached::smallstepNoCall/3;
/**
* Gets the summary that corresponds to having taken a forwards
* intra-procedural step from `nodeFrom` to `nodeTo`.
*
* This predicate should normally not be used; consider using `step`
* instead.
*/
predicate smallstepCall = Cached::smallstepCall/3;
/**
* Gets the summary that corresponds to having taken a forwards
* local, heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*
* Unlike `StepSummary::step`, this predicate does not compress
* type-preserving steps.
*/
predicate smallstep(Node nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
smallstepNoCall(nodeFrom, nodeTo, summary)
or
smallstepCall(nodeFrom, nodeTo, summary)
}
/** Gets the step summary for a level step. */
StepSummary levelStep() { result = LevelStep() }
/** Gets the step summary for a call step. */
StepSummary callStep() { result = CallStep() }
/** Gets the step summary for a return step. */
StepSummary returnStep() { result = ReturnStep() }
/** Gets the step summary for storing into `content`. */
StepSummary storeStep(TypeTrackerContent content) { result = StoreStep(content) }
/** Gets the step summary for loading from `content`. */
StepSummary loadStep(TypeTrackerContent content) { result = LoadStep(content) }
/** Gets the step summary for loading from `load` and then storing into `store`. */
StepSummary loadStoreStep(TypeTrackerContent load, TypeTrackerContent store) {
result = LoadStoreStep(load, store)
}
/** Gets the step summary for a step that only permits contents matched by `filter`. */
StepSummary withContent(ContentFilter filter) { result = WithContent(filter) }
/** Gets the step summary for a step that blocks contents matched by `filter`. */
StepSummary withoutContent(ContentFilter filter) { result = WithoutContent(filter) }
/** Gets the step summary for a jump step. */
StepSummary jumpStep() { result = JumpStep() }
}
/**
* DEPRECATED: Use `semmle.python.dataflow.new.TypeTracking` instead.
*
* A summary of the steps needed to track a value to a given dataflow node.
*
* This can be used to track objects that implement a certain API in order to
* recognize calls to that API. Note that type-tracking does not by itself provide a
* source/sink relation, that is, it may determine that a node has a given type,
* but it won't determine where that type came from.
*
* It is recommended that all uses of this type are written in the following form,
* for tracking some type `myType`:
* ```ql
* DataFlow::TypeTrackingNode myType(DataFlow::TypeTracker t) {
* t.start() and
* result = < source of myType >
* or
* exists (DataFlow::TypeTracker t2 |
* result = myType(t2).track(t2, t)
* )
* }
*
* DataFlow::Node myType() { myType(DataFlow::TypeTracker::end()).flowsTo(result) }
* ```
*
* Instead of `result = myType(t2).track(t2, t)`, you can also use the equivalent
* `t = t2.step(myType(t2), result)`. If you additionally want to track individual
* intra-procedural steps, use `t = t2.smallstep(myCallback(t2), result)`.
*/
deprecated class TypeTracker extends TTypeTracker {
Boolean hasCall;
OptionalTypeTrackerContent content;
TypeTracker() { this = MkTypeTracker(hasCall, content) }
/** Gets the summary resulting from appending `step` to this type-tracking summary. */
TypeTracker append(StepSummary step) { result = append(this, step) }
/** Gets a textual representation of this summary. */
string toString() {
exists(string withCall, string withContent |
(if hasCall = true then withCall = "with" else withCall = "without") and
(
if content != noContent()
then withContent = " with content " + content
else withContent = ""
) and
result = "type tracker " + withCall + " call steps" + withContent
)
}
/**
* Holds if this is the starting point of type tracking.
*/
predicate start() { hasCall = false and content = noContent() }
/**
* Holds if this is the starting point of type tracking, and the value starts in the content named `contentName`.
* The type tracking only ends after the content has been loaded.
*/
predicate startInContent(TypeTrackerContent contentName) {
hasCall = false and content = contentName
}
/**
* Holds if this is the starting point of type tracking
* when tracking a parameter into a call, but not out of it.
*/
predicate call() { hasCall = true and content = noContent() }
/**
* Holds if this is the end point of type tracking.
*/
predicate end() { content = noContent() }
/**
* INTERNAL. DO NOT USE.
*
* Holds if this type has been tracked into a call.
*/
boolean hasCall() { result = hasCall }
/**
* INTERNAL. DO NOT USE.
*
* Gets the content associated with this type tracker.
*/
OptionalTypeTrackerContent getContent() { result = content }
/**
* Gets a type tracker that starts where this one has left off to allow continued
* tracking.
*
* This predicate is only defined if the type is not associated to a piece of content.
*/
TypeTracker continue() { content = noContent() and result = this }
/**
* Gets the summary that corresponds to having taken a forwards
* heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*/
bindingset[nodeFrom, this]
pragma[inline_late]
pragma[noopt]
TypeTracker step(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo) {
exists(StepSummary summary |
stepProj(nodeFrom, summary) and
result = this.append(summary) and
step(nodeFrom, nodeTo, summary)
)
}
bindingset[nodeFrom, this]
pragma[inline_late]
pragma[noopt]
private TypeTracker smallstepNoSimpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
exists(StepSummary summary |
smallstepProj(nodeFrom, summary) and
result = this.append(summary) and
smallstep(nodeFrom, nodeTo, summary)
)
}
/**
* Gets the summary that corresponds to having taken a forwards
* local, heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*
* Unlike `TypeTracker::step`, this predicate exposes all edges
* in the flow graph, and not just the edges between `Node`s.
* It may therefore be less performant.
*
* Type tracking predicates using small steps typically take the following form:
* ```ql
* DataFlow::Node myType(DataFlow::TypeTracker t) {
* t.start() and
* result = < source of myType >
* or
* exists (DataFlow::TypeTracker t2 |
* t = t2.smallstep(myType(t2), result)
* )
* }
*
* DataFlow::Node myType() {
* result = myType(DataFlow::TypeTracker::end())
* }
* ```
*/
pragma[inline]
TypeTracker smallstep(Node nodeFrom, Node nodeTo) {
result = this.smallstepNoSimpleLocalFlowStep(nodeFrom, nodeTo)
or
simpleLocalFlowStep(nodeFrom, nodeTo) and
result = this
}
}
/** Provides predicates for implementing custom `TypeTracker`s. */
deprecated module TypeTracker {
/**
* Gets a valid end point of type tracking.
*/
TypeTracker end() { result.end() }
/**
* INTERNAL USE ONLY.
*
* Gets a valid end point of type tracking with the call bit set to the given value.
*/
predicate end = Cached::noContentTypeTracker/1;
}
pragma[nomagic]
deprecated private predicate backStepProj(TypeTrackingNode nodeTo, StepSummary summary) {
step(_, nodeTo, summary)
}
deprecated private predicate backSmallstepProj(TypeTrackingNode nodeTo, StepSummary summary) {
smallstep(_, nodeTo, summary)
}
/**
* DEPRECATED: Use `semmle.python.dataflow.new.TypeTracking` instead.
*
* A summary of the steps needed to back-track a use of a value to a given dataflow node.
*
* This can for example be used to track callbacks that are passed to a certain API,
* so we can model specific parameters of that callback as having a certain type.
*
* Note that type back-tracking does not provide a source/sink relation, that is,
* it may determine that a node will be used in an API call somewhere, but it won't
* determine exactly where that use was, or the path that led to the use.
*
* It is recommended that all uses of this type are written in the following form,
* for back-tracking some callback type `myCallback`:
*
* ```ql
* DataFlow::TypeTrackingNode myCallback(DataFlow::TypeBackTracker t) {
* t.start() and
* result = (< some API call >).getArgument(< n >).getALocalSource()
* or
* exists (DataFlow::TypeBackTracker t2 |
* result = myCallback(t2).backtrack(t2, t)
* )
* }
*
* DataFlow::TypeTrackingNode myCallback() { result = myCallback(DataFlow::TypeBackTracker::end()) }
* ```
*
* Instead of `result = myCallback(t2).backtrack(t2, t)`, you can also use the equivalent
* `t2 = t.step(result, myCallback(t2))`. If you additionally want to track individual
* intra-procedural steps, use `t2 = t.smallstep(result, myCallback(t2))`.
*/
deprecated class TypeBackTracker extends TTypeBackTracker {
Boolean hasReturn;
OptionalTypeTrackerContent content;
TypeBackTracker() { this = MkTypeBackTracker(hasReturn, content) }
/** Gets the summary resulting from prepending `step` to this type-tracking summary. */
TypeBackTracker prepend(StepSummary step) { result = prepend(this, step) }
/** Gets a textual representation of this summary. */
string toString() {
exists(string withReturn, string withContent |
(if hasReturn = true then withReturn = "with" else withReturn = "without") and
(
if content != noContent()
then withContent = " with content " + content
else withContent = ""
) and
result = "type back-tracker " + withReturn + " return steps" + withContent
)
}
/**
* Holds if this is the starting point of type tracking.
*/
predicate start() { hasReturn = false and content = noContent() }
/**
* Holds if this is the end point of type tracking.
*/
predicate end() { content = noContent() }
/**
* INTERNAL. DO NOT USE.
*
* Holds if this type has been back-tracked into a call through return edge.
*/
boolean hasReturn() { result = hasReturn }
/**
* Gets a type tracker that starts where this one has left off to allow continued
* tracking.
*
* This predicate is only defined if the type has not been tracked into a piece of content.
*/
TypeBackTracker continue() { content = noContent() and result = this }
/**
* Gets the summary that corresponds to having taken a backwards
* heap and/or inter-procedural step from `nodeTo` to `nodeFrom`.
*/
bindingset[nodeTo, result]
pragma[inline_late]
pragma[noopt]
TypeBackTracker step(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo) {
exists(StepSummary summary |
backStepProj(nodeTo, summary) and
this = result.prepend(summary) and
step(nodeFrom, nodeTo, summary)
)
}
bindingset[nodeTo, result]
pragma[inline_late]
pragma[noopt]
private TypeBackTracker smallstepNoSimpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
exists(StepSummary summary |
backSmallstepProj(nodeTo, summary) and
this = result.prepend(summary) and
smallstep(nodeFrom, nodeTo, summary)
)
}
/**
* Gets the summary that corresponds to having taken a backwards
* local, heap and/or inter-procedural step from `nodeTo` to `nodeFrom`.
*
* Unlike `TypeBackTracker::step`, this predicate exposes all edges
* in the flowgraph, and not just the edges between
* `TypeTrackingNode`s. It may therefore be less performant.
*
* Type tracking predicates using small steps typically take the following form:
* ```ql
* DataFlow::Node myType(DataFlow::TypeBackTracker t) {
* t.start() and
* result = < some API call >.getArgument(< n >)
* or
* exists (DataFlow::TypeBackTracker t2 |
* t = t2.smallstep(result, myType(t2))
* )
* }
*
* DataFlow::Node myType() {
* result = myType(DataFlow::TypeBackTracker::end())
* }
* ```
*/
pragma[inline]
TypeBackTracker smallstep(Node nodeFrom, Node nodeTo) {
this = this.smallstepNoSimpleLocalFlowStep(nodeFrom, nodeTo)
or
simpleLocalFlowStep(nodeFrom, nodeTo) and
this = result
}
/**
* Gets a forwards summary that is compatible with this backwards summary.
* That is, if this summary describes the steps needed to back-track a value
* from `sink` to `mid`, and the result is a valid summary of the steps needed
* to track a value from `source` to `mid`, then the value from `source` may
* also flow to `sink`.
*/
TypeTracker getACompatibleTypeTracker() {
exists(boolean hasCall, OptionalTypeTrackerContent c |
result = MkTypeTracker(hasCall, c) and
(
compatibleContents(c, content)
or
content = noContent() and c = content
)
|
hasCall = false
or
this.hasReturn() = false
)
}
}
/** Provides predicates for implementing custom `TypeBackTracker`s. */
deprecated module TypeBackTracker {
/**
* Gets a valid end point of type back-tracking.
*/
TypeBackTracker end() { result.end() }
}
/**
* INTERNAL: Do not use.
*
* Provides logic for constructing a call graph in mutual recursion with type tracking.
*
* When type tracking is used to construct a call graph, we cannot use the join-order
* from `stepInlineLate`, because `step` becomes a recursive call, which means that we
* will have a conjunct with 3 recursive calls: the call to `step`, the call to `stepProj`,
* and the recursive type tracking call itself. The solution is to split the three-way
* non-linear recursion into two non-linear predicates: one that first joins with the
* projected `stepCall` relation, followed by a predicate that joins with the full
* `stepCall` relation (`stepNoCall` not being recursive, can be join-ordered in the
* same way as in `stepInlineLate`).
*/
deprecated module CallGraphConstruction {
/** The input to call graph construction. */
signature module InputSig {
/** A state to track during type tracking. */
class State;
/** Holds if type tracking should start at `start` in state `state`. */
deprecated predicate start(Node start, State state);
/**
* Holds if type tracking should use the step from `nodeFrom` to `nodeTo`,
* which _does not_ depend on the call graph.
*
* Implementing this predicate using `StepSummary::[small]stepNoCall` yields
* standard type tracking.
*/
deprecated predicate stepNoCall(Node nodeFrom, Node nodeTo, StepSummary summary);
/**
* Holds if type tracking should use the step from `nodeFrom` to `nodeTo`,
* which _does_ depend on the call graph.
*
* Implementing this predicate using `StepSummary::[small]stepCall` yields
* standard type tracking.
*/
deprecated predicate stepCall(Node nodeFrom, Node nodeTo, StepSummary summary);
/** A projection of an element from the state space. */
class StateProj;
/** Gets the projection of `state`. */
StateProj stateProj(State state);
/** Holds if type tracking should stop at `n` when we are tracking projected state `stateProj`. */
deprecated predicate filter(Node n, StateProj stateProj);
}
/** Provides the `track` predicate for use in call graph construction. */
module Make<InputSig Input> {
pragma[nomagic]
deprecated private predicate stepNoCallProj(Node nodeFrom, StepSummary summary) {
Input::stepNoCall(nodeFrom, _, summary)
}
pragma[nomagic]
deprecated private predicate stepCallProj(Node nodeFrom, StepSummary summary) {
Input::stepCall(nodeFrom, _, summary)
}
bindingset[nodeFrom, t]
pragma[inline_late]
pragma[noopt]
deprecated private TypeTracker stepNoCallInlineLate(
TypeTracker t, TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo
) {
exists(StepSummary summary |
stepNoCallProj(nodeFrom, summary) and
result = t.append(summary) and
Input::stepNoCall(nodeFrom, nodeTo, summary)
)
}
bindingset[state]
pragma[inline_late]
private Input::StateProj stateProjInlineLate(Input::State state) {
result = Input::stateProj(state)
}
pragma[nomagic]
deprecated private Node track(Input::State state, TypeTracker t) {
t.start() and Input::start(result, state)
or
exists(Input::StateProj stateProj |
stateProj = stateProjInlineLate(state) and
not Input::filter(result, stateProj)
|
exists(TypeTracker t2 | t = stepNoCallInlineLate(t2, track(state, t2), result))
or
exists(StepSummary summary |
// non-linear recursion
Input::stepCall(trackCall(state, t, summary), result, summary)
)
)
}
bindingset[t, summary]
pragma[inline_late]
deprecated private TypeTracker appendInlineLate(TypeTracker t, StepSummary summary) {
result = t.append(summary)
}
pragma[nomagic]
deprecated private Node trackCall(Input::State state, TypeTracker t, StepSummary summary) {
exists(TypeTracker t2 |
// non-linear recursion
result = track(state, t2) and
stepCallProj(result, summary) and
t = appendInlineLate(t2, summary)
)
}
/** Gets a node that can be reached from _some_ start node in state `state`. */
pragma[nomagic]
deprecated Node track(Input::State state) { result = track(state, TypeTracker::end()) }
}
/** A simple version of `CallGraphConstruction` that uses standard type tracking. */
module Simple {
/** The input to call graph construction. */
signature module InputSig {
/** A state to track during type tracking. */
class State;
/** Holds if type tracking should start at `start` in state `state`. */
deprecated predicate start(Node start, State state);
/** Holds if type tracking should stop at `n`. */
deprecated predicate filter(Node n);
}
/** Provides the `track` predicate for use in call graph construction. */
module Make<InputSig Input> {
deprecated private module I implements CallGraphConstruction::InputSig {
private import codeql.util.Unit
class State = Input::State;
predicate start(Node start, State state) { Input::start(start, state) }
predicate stepNoCall(Node nodeFrom, Node nodeTo, StepSummary summary) {
StepSummary::stepNoCall(nodeFrom, nodeTo, summary)
}
predicate stepCall(Node nodeFrom, Node nodeTo, StepSummary summary) {
StepSummary::stepCall(nodeFrom, nodeTo, summary)
}
class StateProj = Unit;
Unit stateProj(State state) { exists(state) and exists(result) }
predicate filter(Node n, Unit u) {
Input::filter(n) and
exists(u)
}
}
deprecated import CallGraphConstruction::Make<I>
}
}
}

View File

@@ -1,102 +0,0 @@
/**
* Provides Python-specific definitions for use in the type tracker library.
*/
private import python
private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic
private import TypeTrackingImpl as TypeTrackingImpl
deprecated class Node = DataFlowPublic::Node;
deprecated class TypeTrackingNode = DataFlowPublic::TypeTrackingNode;
/** A content name for use by type trackers, or the empty string. */
deprecated class OptionalTypeTrackerContent extends string {
OptionalTypeTrackerContent() {
this = ""
or
this = any(DataFlowPublic::AttributeContent dfc).getAttribute()
}
}
/** A content name for use by type trackers. */
deprecated class TypeTrackerContent extends OptionalTypeTrackerContent {
TypeTrackerContent() { this != "" }
}
/** Gets the content string representing no value. */
deprecated OptionalTypeTrackerContent noContent() { result = "" }
/**
* A label to use for `WithContent` and `WithoutContent` steps, restricting
* which `ContentSet` may pass through. Not currently used in Python.
*/
deprecated class ContentFilter extends Unit {
TypeTrackerContent getAMatchingContent() { none() }
}
pragma[inline]
deprecated predicate compatibleContents(
TypeTrackerContent storeContent, TypeTrackerContent loadContent
) {
storeContent = loadContent
}
deprecated predicate simpleLocalFlowStep =
TypeTrackingImpl::TypeTrackingInput::simpleLocalSmallStep/2;
deprecated predicate jumpStep = TypeTrackingImpl::TypeTrackingInput::jumpStep/2;
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */
deprecated predicate levelStepCall(Node nodeFrom, Node nodeTo) { none() }
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which does not depend on the call graph. */
deprecated predicate levelStepNoCall = TypeTrackingImpl::TypeTrackingInput::levelStepNoCall/2;
/**
* Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call.
*
* Flow into summarized library methods is not included, as that will lead to negative
* recursion (or, at best, terrible performance), since identifying calls to library
* methods is done using API graphs (which uses type tracking).
*/
deprecated predicate callStep = TypeTrackingImpl::TypeTrackingInput::callStep/2;
/** Holds if `nodeFrom` steps to `nodeTo` by being returned from a call. */
deprecated predicate returnStep = TypeTrackingImpl::TypeTrackingInput::returnStep/2;
/**
* Holds if `nodeFrom` is being written to the `content` content of the object in `nodeTo`.
*/
deprecated predicate basicStoreStep = TypeTrackingImpl::TypeTrackingInput::storeStep/3;
/**
* Holds if `nodeTo` is the result of accessing the `content` content of `nodeFrom`.
*/
deprecated predicate basicLoadStep = TypeTrackingImpl::TypeTrackingInput::loadStep/3;
/**
* Holds if the `loadContent` of `nodeFrom` is stored in the `storeContent` of `nodeTo`.
*/
deprecated predicate basicLoadStoreStep = TypeTrackingImpl::TypeTrackingInput::loadStoreStep/4;
/**
* Holds if type-tracking should step from `nodeFrom` to `nodeTo` but block flow of contents matched by `filter` through here.
*/
deprecated predicate basicWithoutContentStep(Node nodeFrom, Node nodeTo, ContentFilter filter) {
none()
}
/**
* Holds if type-tracking should step from `nodeFrom` to `nodeTo` if inside a content matched by `filter`.
*/
deprecated predicate basicWithContentStep(Node nodeFrom, Node nodeTo, ContentFilter filter) {
none()
}
/**
* A utility class that is equivalent to `boolean` but does not require type joining.
*/
deprecated class Boolean extends boolean {
Boolean() { this = true or this = false }
}

View File

@@ -1781,15 +1781,6 @@ module StdlibPrivate {
* See https://docs.python.org/3/library/cgi.html.
*/
module FieldStorage {
/**
* DEPRECATED: Use `subclassRef` predicate instead.
*
* Gets a reference to the `cgi.FieldStorage` class.
*/
deprecated API::Node classRef() {
result = API::moduleImport("cgi").getMember("FieldStorage")
}
/** Gets a reference to the `cgi.FieldStorage` class or any subclass. */
API::Node subclassRef() {
result = API::moduleImport("cgi").getMember("FieldStorage").getASubclass*()
@@ -1900,168 +1891,15 @@ module StdlibPrivate {
// ---------------------------------------------------------------------------
// BaseHTTPServer (Python 2 only)
// ---------------------------------------------------------------------------
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `BaseHttpServer` module.
*/
deprecated API::Node baseHttpServer() { result = API::moduleImport("BaseHTTPServer") }
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `BaseHttpServer` module.
*/
deprecated module BaseHttpServer {
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `BaseHTTPServer.BaseHTTPRequestHandler` class (Python 2 only).
*/
deprecated module BaseHttpRequestHandler {
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `BaseHttpServer.BaseHttpRequestHandler` class.
*/
deprecated API::Node classRef() {
result = baseHttpServer().getMember("BaseHTTPRequestHandler")
}
}
}
// ---------------------------------------------------------------------------
// SimpleHTTPServer (Python 2 only)
// ---------------------------------------------------------------------------
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `SimpleHttpServer` module.
*/
deprecated API::Node simpleHttpServer() { result = API::moduleImport("SimpleHTTPServer") }
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `SimpleHttpServer` module.
*/
deprecated module SimpleHttpServer {
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `SimpleHTTPServer.SimpleHTTPRequestHandler` class (Python 2 only).
*/
deprecated module SimpleHttpRequestHandler {
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `SimpleHttpServer.SimpleHttpRequestHandler` class.
*/
deprecated API::Node classRef() {
result = simpleHttpServer().getMember("SimpleHTTPRequestHandler")
}
}
}
// ---------------------------------------------------------------------------
// CGIHTTPServer (Python 2 only)
// ---------------------------------------------------------------------------
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `CGIHTTPServer` module.
*/
deprecated API::Node cgiHttpServer() { result = API::moduleImport("CGIHTTPServer") }
/** Provides models for the `CGIHTTPServer` module. */
deprecated module CgiHttpServer {
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `CGIHTTPServer.CGIHTTPRequestHandler` class (Python 2 only).
*/
deprecated module CgiHttpRequestHandler {
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `CGIHTTPServer.CgiHttpRequestHandler` class.
*/
deprecated API::Node classRef() {
result = cgiHttpServer().getMember("CGIHTTPRequestHandler")
}
}
}
// ---------------------------------------------------------------------------
// http (Python 3 only)
// ---------------------------------------------------------------------------
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `http` module.
*/
deprecated API::Node http() { result = API::moduleImport("http") }
/** Provides models for the `http` module. */
deprecated module StdlibHttp {
// -------------------------------------------------------------------------
// http.server
// -------------------------------------------------------------------------
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `http.server` module.
*/
deprecated API::Node server() { result = http().getMember("server") }
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `http.server` module
*/
deprecated module Server {
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `http.server.BaseHTTPRequestHandler` class (Python 3 only).
*
* See https://docs.python.org/3.9/library/http.server.html#http.server.BaseHTTPRequestHandler.
*/
deprecated module BaseHttpRequestHandler {
/** Gets a reference to the `http.server.BaseHttpRequestHandler` class. */
deprecated API::Node classRef() { result = server().getMember("BaseHTTPRequestHandler") }
}
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `http.server.SimpleHTTPRequestHandler` class (Python 3 only).
*
* See https://docs.python.org/3.9/library/http.server.html#http.server.SimpleHTTPRequestHandler.
*/
deprecated module SimpleHttpRequestHandler {
/** Gets a reference to the `http.server.SimpleHttpRequestHandler` class. */
deprecated API::Node classRef() { result = server().getMember("SimpleHTTPRequestHandler") }
}
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Provides models for the `http.server.CGIHTTPRequestHandler` class (Python 3 only).
*
* See https://docs.python.org/3.9/library/http.server.html#http.server.CGIHTTPRequestHandler.
*/
deprecated module CgiHttpRequestHandler {
/**
* DEPRECATED: Use API-graphs directly instead.
*
* Gets a reference to the `http.server.CGIHTTPRequestHandler` class.
*/
deprecated API::Node classRef() { result = server().getMember("CGIHTTPRequestHandler") }
}
}
}
/**
* Provides models for the `BaseHTTPRequestHandler` class and subclasses.
*

View File

@@ -0,0 +1,17 @@
---
category: breaking
---
* Deleted the deprecated `getCallNode` predicate from `API::Node`, use `asCall()` instead.
* Deleted the deprecated `getASubclass`, `getAnImmediateSubclass`, `getASuccessor`, `getAPredecessor`, `getASuccessor`, `getDepth`, and `getPath` predicates from `API::Node`.
* Deleted the deprecated `Root`, `Use`, and `Def` classes from `ApiGraphs.qll`.
* Deleted the deprecated `Label` module from `ApiGraphs.qll`.
* Deleted the deprecated `getAUse`, `getAnImmediateUse`, `getARhs`, and `getAValueReachingRhs` predicates from `API::Node`, use `getAValueReachableFromSource`, `asSource`, `asSink`, and `getAValueReachingSink` instead.
* Deleted the deprecated `getAVariable` predicate from the `ExprNode` class, use `getVariable` instead.
* Deleted the deprecated `getAPotentialFieldAccessMethod` predicate from the `ActiveRecordModelClass` class.
* Deleted the deprecated `ActiveRecordModelClassMethodCall` class from `ActiveRecord.qll`, use `ActiveRecordModelClass.getClassNode().trackModule().getMethod()` instead.
* Deleted the deprecated `PotentiallyUnsafeSqlExecutingMethodCall` class from `ActiveRecord.qll`, use the `SqlExecution` concept instead.
* Deleted the deprecated `ModelClass` and `ModelInstance` classes from `ActiveResource.qll`, use `ModelClassNode` and `ModelClassNode.getAnInstanceReference()` instead.
* Deleted the deprecated `Collection` class from `ActiveResource.qll`, use `CollectionSource` instead.
* Deleted the deprecated `ServiceInstantiation` and `ClientInstantiation` classes from `Twirp.qll`.
* Deleted a lot of deprecated dataflow modules from "*Query.qll" files.
* Deleted the old deprecated TypeTracking library.

View File

@@ -264,12 +264,6 @@ module API {
pragma[inline_late]
DataFlow::CallNode asCall() { this = Impl::MkMethodAccessNode(result) }
/**
* DEPRECATED. Use `asCall()` instead.
*/
pragma[inline]
deprecated DataFlow::CallNode getCallNode() { this = Impl::MkMethodAccessNode(result) }
/**
* Gets a module or class that descends from the module or class referenced by this API node.
*/
@@ -607,104 +601,10 @@ module API {
*/
string toString() { none() }
/**
* Gets a node representing a (direct or indirect) subclass of the class represented by this node.
* ```rb
* class A; end
* class B < A; end
* class C < B; end
* ```
* In the example above, `getMember("A").getASubclass()` will return uses of `A`, `B` and `C`.
*/
pragma[inline]
deprecated Node getASubclass() { result = this }
/**
* Gets a node representing a direct subclass of the class represented by this node.
* ```rb
* class A; end
* class B < A; end
* class C < B; end
* ```
* In the example above, `getMember("A").getAnImmediateSubclass()` will return uses of `B` only.
*/
pragma[inline]
deprecated Node getAnImmediateSubclass() {
result = this.asModule().getAnImmediateDescendent().trackModule()
}
/** DEPRECATED. This predicate has been renamed to `getAValueReachableFromSource()`. */
deprecated DataFlow::Node getAUse() { result = this.getAValueReachableFromSource() }
/** DEPRECATED. This predicate has been renamed to `asSource()`. */
deprecated DataFlow::LocalSourceNode getAnImmediateUse() { result = this.asSource() }
/** DEPRECATED. This predicate has been renamed to `asSink()`. */
deprecated DataFlow::Node getARhs() { result = this.asSink() }
/** DEPRECATED. This predicate has been renamed to `getAValueReachingSink()`. */
deprecated DataFlow::Node getAValueReachingRhs() { result = this.getAValueReachingSink() }
/**
* DEPRECATED. API graph nodes are no longer associated with specific paths.
*
* Gets a string representation of the lexicographically least among all shortest access paths
* from the root to this node.
*/
deprecated string getPath() { none() }
/**
* DEPRECATED. Use label-specific predicates in this class, such as `getMember`, instead of using `getASuccessor`.
*
* Gets a node such that there is an edge in the API graph between this node and the other
* one, and that edge is labeled with `lbl`.
*/
pragma[inline]
deprecated Node getASuccessor(Label::ApiLabel lbl) {
labelledEdge(this.getAnEpsilonSuccessor(), lbl, result)
}
/**
* DEPRECATED. API graphs no longer support backward traversal of edges. If possible use `.backtrack()` to get
* a node intended for backtracking.
*
* Gets a node such that there is an edge in the API graph between that other node and
* this one, and that edge is labeled with `lbl`
*/
deprecated Node getAPredecessor(Label::ApiLabel lbl) { this = result.getASuccessor(lbl) }
/**
* DEPRECATED. API graphs no longer support backward traversal of edges. If possible use `.backtrack()` to get
* a node intended for backtracking.
*
* Gets a node such that there is an edge in the API graph between this node and the other
* one.
*/
deprecated Node getAPredecessor() { result = this.getAPredecessor(_) }
/**
* Gets a node such that there is an edge in the API graph between that other node and
* this one.
*/
pragma[inline]
deprecated Node getASuccessor() { result = this.getASuccessor(_) }
/** DEPRECATED. API graphs are no longer associated with a depth. */
deprecated int getDepth() { none() }
pragma[inline]
private Node getAnEpsilonSuccessor() { result = getAnEpsilonSuccessorInline(this) }
}
/** DEPRECATED. Use `API::root()` to access the root node. */
deprecated class Root = RootNode;
/** DEPRECATED. A node corresponding to the use of an API component. */
deprecated class Use = ForwardNode;
/** DEPRECATED. A node corresponding to a value escaping into an API component. */
deprecated class Def = SinkNode;
/** The root node of an API graph. */
private class RootNode extends Node, Impl::MkRoot {
override string toString() { result = "Root()" }
@@ -1327,270 +1227,4 @@ module API {
node = MkMethodAccessNode(entry.getACall())
}
}
/**
* Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`.
*/
pragma[nomagic]
deprecated private predicate labelledEdge(Node pred, Label::ApiLabel lbl, Node succ) {
exists(string name |
Impl::memberEdge(pred, name, succ) and
lbl = Label::member(name)
)
or
exists(string name |
Impl::methodEdge(pred, name, succ) and
lbl = Label::method(name)
)
or
exists(DataFlow::Content content |
Impl::contentEdge(pred, content, succ) and
lbl = Label::content(content)
)
or
exists(DataFlowDispatch::ParameterPosition pos |
Impl::parameterEdge(pred, pos, succ) and
lbl = Label::getLabelFromParameterPosition(pos)
)
or
exists(DataFlowDispatch::ArgumentPosition pos |
Impl::argumentEdge(pred, pos, succ) and
lbl = Label::getLabelFromArgumentPosition(pos)
)
or
Impl::instanceEdge(pred, succ) and
lbl = Label::instance()
or
Impl::returnEdge(pred, succ) and
lbl = Label::return()
or
exists(EntryPoint entry |
Impl::entryPointEdge(entry, succ) and
pred = root() and
lbl = Label::entryPoint(entry)
)
}
/**
* DEPRECATED. Treating the API graph as an explicit labelled graph is deprecated - instead use the methods on `API:Node` directly.
*
* Provides classes modeling the various edges (labels) in the API graph.
*/
deprecated module Label {
/** All the possible labels in the API graph. */
private newtype TLabel =
MkLabelMember(string member) { member = any(ConstantReadAccess a).getName() } or
MkLabelMethod(string m) { m = any(DataFlow::CallNode c).getMethodName() } or
MkLabelReturn() or
MkLabelInstance() or
MkLabelKeywordParameter(string name) {
any(DataFlowDispatch::ArgumentPosition arg).isKeyword(name)
or
any(DataFlowDispatch::ParameterPosition arg).isKeyword(name)
} or
MkLabelParameter(int n) {
any(DataFlowDispatch::ArgumentPosition c).isPositional(n)
or
any(DataFlowDispatch::ParameterPosition c).isPositional(n)
} or
MkLabelBlockParameter() or
MkLabelEntryPoint(EntryPoint name) or
MkLabelContent(DataFlow::Content content)
/** A label in the API-graph */
class ApiLabel extends TLabel {
/** Gets a string representation of this label. */
string toString() { result = "???" }
}
private import LabelImpl
private module LabelImpl {
private import Impl
/** A label for a member, for example a constant. */
class LabelMember extends ApiLabel, MkLabelMember {
private string member;
LabelMember() { this = MkLabelMember(member) }
/** Gets the member name associated with this label. */
string getMember() { result = member }
override string toString() { result = "getMember(\"" + member + "\")" }
}
/** A label for a method. */
class LabelMethod extends ApiLabel, MkLabelMethod {
private string method;
LabelMethod() { this = MkLabelMethod(method) }
/** Gets the method name associated with this label. */
string getMethod() { result = method }
override string toString() { result = "getMethod(\"" + method + "\")" }
}
/** A label for the return value of a method. */
class LabelReturn extends ApiLabel, MkLabelReturn {
override string toString() { result = "getReturn()" }
}
/** A label for getting instances of a module/class. */
class LabelInstance extends ApiLabel, MkLabelInstance {
override string toString() { result = "getInstance()" }
}
/** A label for a keyword parameter. */
class LabelKeywordParameter extends ApiLabel, MkLabelKeywordParameter {
private string name;
LabelKeywordParameter() { this = MkLabelKeywordParameter(name) }
/** Gets the name of the keyword parameter associated with this label. */
string getName() { result = name }
override string toString() { result = "getKeywordParameter(\"" + name + "\")" }
}
/** A label for a parameter. */
class LabelParameter extends ApiLabel, MkLabelParameter {
private int n;
LabelParameter() { this = MkLabelParameter(n) }
/** Gets the parameter number associated with this label. */
int getIndex() { result = n }
override string toString() { result = "getParameter(" + n + ")" }
}
/** A label for a block parameter. */
class LabelBlockParameter extends ApiLabel, MkLabelBlockParameter {
override string toString() { result = "getBlock()" }
}
/** A label from the root node to a custom entry point. */
class LabelEntryPoint extends ApiLabel, MkLabelEntryPoint {
private API::EntryPoint name;
LabelEntryPoint() { this = MkLabelEntryPoint(name) }
override string toString() { result = "entryPoint(\"" + name + "\")" }
/** Gets the name of the entry point. */
API::EntryPoint getName() { result = name }
}
/** A label representing contents of an object. */
class LabelContent extends ApiLabel, MkLabelContent {
private DataFlow::Content content;
LabelContent() { this = MkLabelContent(content) }
override string toString() {
result = "getContent(" + content.toString().replaceAll(" ", "_") + ")"
}
/** Gets the content represented by this label. */
DataFlow::Content getContent() { result = content }
}
}
/** Gets the `member` edge label for member `m`. */
LabelMember member(string m) { result.getMember() = m }
/** Gets the `method` edge label. */
LabelMethod method(string m) { result.getMethod() = m }
/** Gets the `return` edge label. */
LabelReturn return() { any() }
/** Gets the `instance` edge label. */
LabelInstance instance() { any() }
/** Gets the label representing the given keyword argument/parameter. */
LabelKeywordParameter keywordParameter(string name) { result.getName() = name }
/** Gets the label representing the `n`th positional argument/parameter. */
LabelParameter parameter(int n) { result.getIndex() = n }
/** Gets the label representing the block argument/parameter. */
LabelBlockParameter blockParameter() { any() }
/** Gets the label for the edge from the root node to a custom entry point of the given name. */
LabelEntryPoint entryPoint(API::EntryPoint name) { result.getName() = name }
/** Gets a label representing the given content. */
LabelContent content(DataFlow::Content content) { result.getContent() = content }
/** Gets the API graph label corresponding to the given argument position. */
Label::ApiLabel getLabelFromArgumentPosition(DataFlowDispatch::ArgumentPosition pos) {
exists(int n |
pos.isPositional(n) and
result = Label::parameter(n)
)
or
exists(string name |
pos.isKeyword(name) and
result = Label::keywordParameter(name)
)
or
pos.isBlock() and
result = Label::blockParameter()
or
pos.isAny() and
(
result = Label::parameter(_)
or
result = Label::keywordParameter(_)
or
result = Label::blockParameter()
// NOTE: `self` should NOT be included, as described in the QLDoc for `isAny()`
)
or
pos.isAnyNamed() and
result = Label::keywordParameter(_)
//
// Note: there is currently no API graph label for `self`.
// It was omitted since in practice it means going back to where you came from.
// For example, `base.getMethod("foo").getSelf()` would just be `base`.
// However, it's possible we'll need it later, for identifying `self` parameters or post-update nodes.
}
/** Gets the API graph label corresponding to the given parameter position. */
Label::ApiLabel getLabelFromParameterPosition(DataFlowDispatch::ParameterPosition pos) {
exists(int n |
pos.isPositional(n) and
result = Label::parameter(n)
)
or
exists(string name |
pos.isKeyword(name) and
result = Label::keywordParameter(name)
)
or
pos.isBlock() and
result = Label::blockParameter()
or
pos.isAny() and
(
result = Label::parameter(_)
or
result = Label::keywordParameter(_)
or
result = Label::blockParameter()
// NOTE: `self` should NOT be included, as described in the QLDoc for `isAny()`
)
or
pos.isAnyNamed() and
result = Label::keywordParameter(_)
//
// Note: there is currently no API graph label for `self`.
// It was omitted since in practice it means going back to where you came from.
// For example, `base.getMethod("foo").getSelf()` would just be `base`.
// However, it's possible we'll need it later, for identifying `self` parameters or post-update nodes.
}
}
}

View File

@@ -200,13 +200,6 @@ module ExprNodes {
override LhsExpr getExpr() { result = super.getExpr() }
/**
* DEPRECATED: use `getVariable` instead.
*
* Gets a variable used in (or introduced by) this LHS.
*/
deprecated Variable getAVariable() { result = e.(VariableAccess).getVariable() }
/** Gets the variable used in (or introduced by) this LHS. */
Variable getVariable() { result = e.(VariableAccess).getVariable() }
}

View File

@@ -635,8 +635,7 @@ private module Cached {
} or
TElementContentOfTypeContent(string type, Boolean includeUnknown) {
type = any(Content::KnownElementContent content).getIndex().getValueType()
} or
deprecated TNoContentSet() // Only used by type-tracking
}
cached
class TContentSet =

View File

@@ -1284,13 +1284,6 @@ class LhsExprNode extends ExprNode {
/** Gets the underlying AST node as a `LhsExpr`. */
LhsExpr asLhsExprAstNode() { result = lhsExprCfgNode.getExpr() }
/**
* DEPRECATED: use `getVariable` instead.
*
* Gets a variable used in (or introduced by) this LHS.
*/
deprecated Variable getAVariable() { result = lhsExprCfgNode.getAVariable() }
/** Gets the variable used in (or introduced by) this LHS. */
Variable getVariable() { result = lhsExprCfgNode.getVariable() }
}

View File

@@ -103,74 +103,10 @@ class ActiveRecordModelClass extends ClassDeclaration {
cls = activeRecordBaseClass().getADescendentModule() and this = cls.getADeclaration()
}
// Gets the class declaration for this class and all of its super classes
private ModuleBase getAllClassDeclarations() { result = cls.getAnAncestor().getADeclaration() }
/**
* Gets methods defined in this class that may access a field from the database.
*/
deprecated Method getAPotentialFieldAccessMethod() {
// It's a method on this class or one of its super classes
result = this.getAllClassDeclarations().getAMethod() and
// There is a value that can be returned by this method which may include field data
exists(DataFlow::Node returned, ActiveRecordInstanceMethodCall cNode, MethodCall c |
exprNodeReturnedFrom(returned, result) and
cNode.flowsTo(returned) and
c = cNode.asExpr().getExpr()
|
// The referenced method is not built-in, and...
not isBuiltInMethodForActiveRecordModelInstance(c.getMethodName()) and
(
// ...The receiver does not have a matching method definition, or...
not exists(
cNode.getInstance().getClass().getAllClassDeclarations().getMethod(c.getMethodName())
)
or
// ...the called method can access a field
c.getATarget() = cNode.getInstance().getClass().getAPotentialFieldAccessMethod()
)
)
}
/** Gets the class as a `DataFlow::ClassNode`. */
DataFlow::ClassNode getClassNode() { result = cls }
}
/**
* Gets a potential reference to an ActiveRecord class object.
*/
deprecated private API::Node getAnActiveRecordModelClassRef() {
result = any(ActiveRecordModelClass cls).getClassNode().trackModule()
or
// For methods with an unknown call target, assume this might be a database field, thus returning another ActiveRecord object.
// In this case we do not know which class it belongs to, which is why this predicate can't associate the reference with a specific class.
result = getAnUnknownActiveRecordModelClassCall().getReturn()
}
/**
* Gets a call performed on an ActiveRecord class object, without a known call target in the codebase.
*/
deprecated private API::MethodAccessNode getAnUnknownActiveRecordModelClassCall() {
result = getAnActiveRecordModelClassRef().getMethod(_) and
result.asCall().asExpr().getExpr() instanceof UnknownMethodCall
}
/**
* DEPRECATED. Use `ActiveRecordModelClass.getClassNode().trackModule().getMethod()` instead.
*
* A class method call whose receiver is an `ActiveRecordModelClass`.
*/
deprecated class ActiveRecordModelClassMethodCall extends MethodCall {
ActiveRecordModelClassMethodCall() {
this = getAnUnknownActiveRecordModelClassCall().asCall().asExpr().getExpr()
}
/** Gets the `ActiveRecordModelClass` of the receiver of this method, if it can be determined. */
ActiveRecordModelClass getReceiverClass() {
this = result.getClassNode().trackModule().getMethod(_).asCall().asExpr().getExpr()
}
}
private predicate sqlFragmentArgumentInner(DataFlow::CallNode call, DataFlow::Node sink) {
call =
activeRecordQueryBuilderCall([
@@ -257,39 +193,6 @@ private predicate unsafeSqlExpr(Expr sqlFragmentExpr) {
sqlFragmentExpr instanceof MethodCall
}
/**
* DEPRECATED. Use the `SqlExecution` concept or `ActiveRecordSqlExecutionRange`.
*
* A method call that may result in executing unintended user-controlled SQL
* queries if the `getSqlFragmentSinkArgument()` expression is tainted by
* unsanitized user-controlled input. For example, supposing that `User` is an
* `ActiveRecord` model class, then
*
* ```rb
* User.where("name = '#{user_name}'")
* ```
*
* may be unsafe if `user_name` is from unsanitized user input, as a value such
* as `"') OR 1=1 --"` could result in the application looking up all users
* rather than just one with a matching name.
*/
deprecated class PotentiallyUnsafeSqlExecutingMethodCall extends ActiveRecordModelClassMethodCall {
private DataFlow::CallNode call;
PotentiallyUnsafeSqlExecutingMethodCall() {
call.asExpr().getExpr() = this and sqlFragmentArgument(call, _)
}
/**
* Gets the SQL fragment argument of this method call.
*/
Expr getSqlFragmentSinkArgument() {
exists(DataFlow::Node sink |
sqlFragmentArgument(call, sink) and result = sink.asExpr().getExpr()
)
}
}
/**
* A SQL execution arising from a call to the ActiveRecord library.
*/

View File

@@ -66,27 +66,6 @@ module ActiveResource {
}
}
/** DEPRECATED. Use `ModelClassNode` instead. */
deprecated class ModelClass extends ClassDeclaration {
private ModelClassNode cls;
ModelClass() { this = cls.getADeclaration() }
/** Gets the class for which this is a declaration. */
ModelClassNode getClassNode() { result = cls }
/** Gets the API node for this class object. */
deprecated API::Node getModelApiNode() { result = cls.trackModule() }
/** Gets a call to `site=`, which sets the base URL for this model. */
SiteAssignCall getASiteAssignment() { result = cls.getASiteAssignment() }
/** Holds if `c` sets a base URL which does not use HTTPS. */
predicate disablesCertificateValidation(SiteAssignCall c) {
cls.disablesCertificateValidation(c)
}
}
/**
* A call to a class method on an ActiveResource model class.
*
@@ -169,20 +148,6 @@ module ActiveResource {
CustomHttpCall() { this.getMethodName() = ["get", "post", "put", "patch", "delete"] }
}
/**
* DEPRECATED. Use `ModelClassNode.getAnInstanceReference()` instead.
*
* An ActiveResource model object.
*/
deprecated class ModelInstance extends DataFlow::Node {
private ModelClassNode cls;
ModelInstance() { this = cls.getAnInstanceReference().getAValueReachableFromSource() }
/** Gets the model class for this instance. */
ModelClassNode getModelClass() { result = cls }
}
/**
* A call to a method on an ActiveResource model object.
*/
@@ -191,22 +156,10 @@ module ActiveResource {
ModelInstanceMethodCall() { this = cls.getAnInstanceReference().getAMethodCall(_) }
/** Gets the model instance for this call. */
deprecated ModelInstance getInstance() { result = this.getReceiver() }
/** Gets the model class for this call. */
ModelClassNode getModelClass() { result = cls }
}
/**
* DEPRECATED. Use `CollectionSource` instead.
*
* A data flow node that may refer to a collection of ActiveResource model objects.
*/
deprecated class Collection extends DataFlow::Node {
Collection() { this = any(CollectionSource src).track().getAValueReachableFromSource() }
}
/**
* A call that returns a collection of ActiveResource model objects.
*/

View File

@@ -13,36 +13,6 @@ private import codeql.ruby.Concepts
* Provides classes for modeling the `Twirp` framework.
*/
module Twirp {
/**
* A Twirp service instantiation
*/
deprecated class ServiceInstantiation extends DataFlow::CallNode {
ServiceInstantiation() {
this = API::getTopLevelMember("Twirp").getMember("Service").getAnInstantiation()
}
/**
* Gets a handler's method.
*/
DataFlow::MethodNode getAHandlerMethodNode() {
result = this.getArgument(0).backtrack().getMethod(_).asCallable()
}
/**
* Gets a handler's method as an AST node.
*/
Ast::Method getAHandlerMethod() { result = this.getAHandlerMethodNode().asCallableAstNode() }
}
/**
* A Twirp client
*/
deprecated class ClientInstantiation extends DataFlow::CallNode {
ClientInstantiation() {
this = API::getTopLevelMember("Twirp").getMember("Client").getAnInstantiation()
}
}
/** The URL of a Twirp service, considered as a sink. */
class ServiceUrlAsSsrfSink extends ServerSideRequestForgery::Sink {
ServiceUrlAsSsrfSink() {

View File

@@ -34,9 +34,3 @@ private module InsecureDownloadConfig implements DataFlow::StateConfigSig {
* Taint-tracking for download of sensitive file through insecure connection.
*/
module InsecureDownloadFlow = DataFlow::GlobalWithState<InsecureDownloadConfig>;
/** DEPRECATED: Use `InsecureDownloadConfig` */
deprecated module Config = InsecureDownloadConfig;
/** DEPRECATED: Use `InsecureDownloadFlow` */
deprecated module Flow = InsecureDownloadFlow;

View File

@@ -7,15 +7,6 @@ private import codeql.ruby.DataFlow
private import codeql.ruby.TaintTracking
private import LdapInjectionCustomizations::LdapInjection as LI
/**
* Provides a taint-tracking configuration for detecting LDAP Injections vulnerabilities.
* DEPRECATED: Use `LdapInjectionFlow` instead
*/
deprecated module LdapInjection {
import LdapInjectionCustomizations::LdapInjection
import TaintTracking::Global<LdapInjectionConfig>
}
private module LdapInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof LI::Source }

View File

@@ -11,15 +11,6 @@ import codeql.ruby.AST
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
/**
* Provides a taint-tracking configuration for cross-site scripting vulnerabilities.
* DEPRECATED: Use StoredXssFlow
*/
deprecated module StoredXss {
import XSS::StoredXss
import TaintTracking::Global<StoredXssConfig>
}
private module StoredXssConfig implements DataFlow::ConfigSig {
private import XSS::StoredXss

View File

@@ -43,8 +43,6 @@ module UnsafeCodeConstruction {
result = getANodeExecutedAsCode(TypeBackTracker::end(), codeExec)
}
deprecated import codeql.ruby.typetracking.TypeTracker as TypeTracker
/** Gets a node that is eventually executed as code at `codeExec`, type-tracked with `t`. */
private DataFlow::LocalSourceNode getANodeExecutedAsCode(
TypeBackTracker t, Concepts::CodeExecution codeExec

View File

@@ -48,8 +48,6 @@ module UnsafeShellCommandConstruction {
source = backtrackShellExec(TypeBackTracker::end(), shellExec)
}
deprecated import codeql.ruby.typetracking.TypeTracker as TypeTracker
private DataFlow::LocalSourceNode backtrackShellExec(
TypeBackTracker t, Concepts::SystemCommandExecution shellExec
) {

View File

@@ -10,14 +10,6 @@ private import codeql.ruby.DataFlow
private import codeql.ruby.TaintTracking
import XpathInjectionCustomizations::XpathInjection
/**
* Provides a taint-tracking configuration for detecting "Xpath Injection" vulnerabilities.
* DEPRECATED: Use `XpathInjectionFlow`
*/
deprecated module XpathInjection {
import TaintTracking::Global<XpathInjectionConfig>
}
private module XpathInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }

View File

@@ -1,936 +0,0 @@
/**
* DEPRECATED: Use `codeql.ruby.typetracking.TypeTracking` instead.
*
* Step Summaries and Type Tracking
*/
private import TypeTrackerSpecific
private import codeql.util.Boolean
cached
private module Cached {
/**
* A description of a step on an inter-procedural data flow path.
*/
cached
deprecated newtype TStepSummary =
LevelStep() or
CallStep() or
ReturnStep() or
deprecated StoreStep(TypeTrackerContent content) { basicStoreStep(_, _, content) } or
deprecated LoadStep(TypeTrackerContent content) { basicLoadStep(_, _, content) } or
deprecated LoadStoreStep(TypeTrackerContent load, TypeTrackerContent store) {
basicLoadStoreStep(_, _, load, store)
} or
deprecated WithContent(ContentFilter filter) { basicWithContentStep(_, _, filter) } or
deprecated WithoutContent(ContentFilter filter) { basicWithoutContentStep(_, _, filter) } or
JumpStep()
cached
deprecated newtype TTypeTracker =
deprecated MkTypeTracker(Boolean hasCall, OptionalTypeTrackerContent content) {
content = noContent()
or
// Restrict `content` to those that might eventually match a load.
// We can't rely on `basicStoreStep` since `startInContent` might be used with
// a content that has no corresponding store.
exists(TypeTrackerContent loadContents |
(
basicLoadStep(_, _, loadContents)
or
basicLoadStoreStep(_, _, loadContents, _)
) and
compatibleContents(content, loadContents)
)
}
cached
deprecated newtype TTypeBackTracker =
deprecated MkTypeBackTracker(Boolean hasReturn, OptionalTypeTrackerContent content) {
content = noContent()
or
// As in MkTypeTracker, restrict `content` to those that might eventually match a store.
exists(TypeTrackerContent storeContent |
(
basicStoreStep(_, _, storeContent)
or
basicLoadStoreStep(_, _, _, storeContent)
) and
compatibleContents(storeContent, content)
)
}
/** Gets a type tracker with no content and the call bit set to the given value. */
cached
deprecated TypeTracker noContentTypeTracker(boolean hasCall) {
result = MkTypeTracker(hasCall, noContent())
}
/** Gets the summary resulting from appending `step` to type-tracking summary `tt`. */
cached
deprecated TypeTracker append(TypeTracker tt, StepSummary step) {
exists(Boolean hasCall, OptionalTypeTrackerContent currentContents |
tt = MkTypeTracker(hasCall, currentContents)
|
step = LevelStep() and result = tt
or
step = CallStep() and result = MkTypeTracker(true, currentContents)
or
step = ReturnStep() and hasCall = false and result = tt
or
step = JumpStep() and
result = MkTypeTracker(false, currentContents)
or
exists(ContentFilter filter | result = tt |
step = WithContent(filter) and
currentContents = filter.getAMatchingContent()
or
step = WithoutContent(filter) and
not currentContents = filter.getAMatchingContent()
)
)
or
exists(TypeTrackerContent storeContents, boolean hasCall |
exists(TypeTrackerContent loadContents |
step = LoadStep(pragma[only_bind_into](loadContents)) and
tt = MkTypeTracker(hasCall, storeContents) and
compatibleContents(storeContents, loadContents) and
result = noContentTypeTracker(hasCall)
)
or
step = StoreStep(pragma[only_bind_into](storeContents)) and
tt = noContentTypeTracker(hasCall) and
result = MkTypeTracker(hasCall, storeContents)
)
or
exists(
TypeTrackerContent currentContent, TypeTrackerContent store, TypeTrackerContent load,
boolean hasCall
|
step = LoadStoreStep(pragma[only_bind_into](load), pragma[only_bind_into](store)) and
compatibleContents(pragma[only_bind_into](currentContent), load) and
tt = MkTypeTracker(pragma[only_bind_into](hasCall), currentContent) and
result = MkTypeTracker(pragma[only_bind_out](hasCall), store)
)
}
pragma[nomagic]
deprecated private TypeBackTracker noContentTypeBackTracker(boolean hasReturn) {
result = MkTypeBackTracker(hasReturn, noContent())
}
/** Gets the summary resulting from prepending `step` to this type-tracking summary. */
cached
deprecated TypeBackTracker prepend(TypeBackTracker tbt, StepSummary step) {
exists(Boolean hasReturn, OptionalTypeTrackerContent content |
tbt = MkTypeBackTracker(hasReturn, content)
|
step = LevelStep() and result = tbt
or
step = CallStep() and hasReturn = false and result = tbt
or
step = ReturnStep() and result = MkTypeBackTracker(true, content)
or
step = JumpStep() and
result = MkTypeBackTracker(false, content)
or
exists(ContentFilter filter | result = tbt |
step = WithContent(filter) and
content = filter.getAMatchingContent()
or
step = WithoutContent(filter) and
not content = filter.getAMatchingContent()
)
)
or
exists(TypeTrackerContent loadContents, boolean hasReturn |
exists(TypeTrackerContent storeContents |
step = StoreStep(pragma[only_bind_into](storeContents)) and
tbt = MkTypeBackTracker(hasReturn, loadContents) and
compatibleContents(storeContents, loadContents) and
result = noContentTypeBackTracker(hasReturn)
)
or
step = LoadStep(pragma[only_bind_into](loadContents)) and
tbt = noContentTypeBackTracker(hasReturn) and
result = MkTypeBackTracker(hasReturn, loadContents)
)
or
exists(
TypeTrackerContent currentContent, TypeTrackerContent store, TypeTrackerContent load,
boolean hasCall
|
step = LoadStoreStep(pragma[only_bind_into](load), pragma[only_bind_into](store)) and
compatibleContents(store, pragma[only_bind_into](currentContent)) and
tbt = MkTypeBackTracker(pragma[only_bind_into](hasCall), currentContent) and
result = MkTypeBackTracker(pragma[only_bind_out](hasCall), load)
)
}
/**
* Gets the summary that corresponds to having taken a forwards
* heap and/or intra-procedural step from `nodeFrom` to `nodeTo`.
*
* Steps contained in this predicate should _not_ depend on the call graph.
*/
cached
deprecated predicate stepNoCall(
TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo, StepSummary summary
) {
exists(Node mid | nodeFrom.flowsTo(mid) and smallstepNoCall(mid, nodeTo, summary))
}
/**
* Gets the summary that corresponds to having taken a forwards
* inter-procedural step from `nodeFrom` to `nodeTo`.
*/
cached
deprecated predicate stepCall(
TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo, StepSummary summary
) {
exists(Node mid | nodeFrom.flowsTo(mid) and smallstepCall(mid, nodeTo, summary))
}
cached
deprecated predicate smallstepNoCall(Node nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
jumpStep(nodeFrom, nodeTo) and
summary = JumpStep()
or
levelStepNoCall(nodeFrom, nodeTo) and
summary = LevelStep()
or
exists(TypeTrackerContent content |
flowsToStoreStep(nodeFrom, nodeTo, content) and
summary = StoreStep(content)
or
basicLoadStep(nodeFrom, nodeTo, content) and summary = LoadStep(content)
)
or
exists(TypeTrackerContent loadContent, TypeTrackerContent storeContent |
flowsToLoadStoreStep(nodeFrom, nodeTo, loadContent, storeContent) and
summary = LoadStoreStep(loadContent, storeContent)
)
or
exists(ContentFilter filter |
basicWithContentStep(nodeFrom, nodeTo, filter) and
summary = WithContent(filter)
or
basicWithoutContentStep(nodeFrom, nodeTo, filter) and
summary = WithoutContent(filter)
)
}
cached
deprecated predicate smallstepCall(Node nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
callStep(nodeFrom, nodeTo) and summary = CallStep()
or
returnStep(nodeFrom, nodeTo) and
summary = ReturnStep()
or
levelStepCall(nodeFrom, nodeTo) and
summary = LevelStep()
}
}
private import Cached
deprecated private predicate step(
TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo, StepSummary summary
) {
stepNoCall(nodeFrom, nodeTo, summary)
or
stepCall(nodeFrom, nodeTo, summary)
}
pragma[nomagic]
deprecated private predicate stepProj(TypeTrackingNode nodeFrom, StepSummary summary) {
step(nodeFrom, _, summary)
}
deprecated private predicate smallstep(Node nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
smallstepNoCall(nodeFrom, nodeTo, summary)
or
smallstepCall(nodeFrom, nodeTo, summary)
}
pragma[nomagic]
deprecated private predicate smallstepProj(Node nodeFrom, StepSummary summary) {
smallstep(nodeFrom, _, summary)
}
/**
* Holds if `nodeFrom` is being written to the `content` of the object in `nodeTo`.
*
* Note that `nodeTo` will always be a local source node that flows to the place where the content
* is written in `basicStoreStep`. This may lead to the flow of information going "back in time"
* from the point of view of the execution of the program.
*
* For instance, if we interpret attribute writes in Python as writing to content with the same
* name as the attribute and consider the following snippet
*
* ```python
* def foo(y):
* x = Foo()
* bar(x)
* x.attr = y
* baz(x)
*
* def bar(x):
* z = x.attr
* ```
* for the attribute write `x.attr = y`, we will have `content` being the literal string `"attr"`,
* `nodeFrom` will be `y`, and `nodeTo` will be the object `Foo()` created on the first line of the
* function. This means we will track the fact that `x.attr` can have the type of `y` into the
* assignment to `z` inside `bar`, even though this attribute write happens _after_ `bar` is called.
*/
deprecated private predicate flowsToStoreStep(
Node nodeFrom, TypeTrackingNode nodeTo, TypeTrackerContent content
) {
exists(Node obj | nodeTo.flowsTo(obj) and basicStoreStep(nodeFrom, obj, content))
}
/**
* Holds if `loadContent` is loaded from `nodeFrom` and written to `storeContent` of `nodeTo`.
*/
deprecated private predicate flowsToLoadStoreStep(
Node nodeFrom, TypeTrackingNode nodeTo, TypeTrackerContent loadContent,
TypeTrackerContent storeContent
) {
exists(Node obj |
nodeTo.flowsTo(obj) and basicLoadStoreStep(nodeFrom, obj, loadContent, storeContent)
)
}
/**
* INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead.
*
* A description of a step on an inter-procedural data flow path.
*/
deprecated class StepSummary extends TStepSummary {
/** Gets a textual representation of this step summary. */
string toString() {
this instanceof LevelStep and result = "level"
or
this instanceof CallStep and result = "call"
or
this instanceof ReturnStep and result = "return"
or
exists(TypeTrackerContent content | this = StoreStep(content) | result = "store " + content)
or
exists(TypeTrackerContent content | this = LoadStep(content) | result = "load " + content)
or
exists(TypeTrackerContent load, TypeTrackerContent store |
this = LoadStoreStep(load, store) and
result = "load-store " + load + " -> " + store
)
or
this instanceof JumpStep and result = "jump"
}
}
/** Provides predicates for updating step summaries (`StepSummary`s). */
deprecated module StepSummary {
predicate append = Cached::append/2;
/**
* Gets the summary that corresponds to having taken a forwards
* inter-procedural step from `nodeFrom` to `nodeTo`.
*
* This predicate should normally not be used; consider using `step`
* instead.
*/
predicate stepCall = Cached::stepCall/3;
/**
* Gets the summary that corresponds to having taken a forwards
* intra-procedural step from `nodeFrom` to `nodeTo`.
*
* This predicate should normally not be used; consider using `step`
* instead.
*/
predicate stepNoCall = Cached::stepNoCall/3;
/**
* Gets the summary that corresponds to having taken a forwards
* heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*/
predicate step(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
stepNoCall(nodeFrom, nodeTo, summary)
or
stepCall(nodeFrom, nodeTo, summary)
}
/**
* Gets the summary that corresponds to having taken a forwards
* inter-procedural step from `nodeFrom` to `nodeTo`.
*
* This predicate should normally not be used; consider using `step`
* instead.
*/
predicate smallstepNoCall = Cached::smallstepNoCall/3;
/**
* Gets the summary that corresponds to having taken a forwards
* intra-procedural step from `nodeFrom` to `nodeTo`.
*
* This predicate should normally not be used; consider using `step`
* instead.
*/
predicate smallstepCall = Cached::smallstepCall/3;
/**
* Gets the summary that corresponds to having taken a forwards
* local, heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*
* Unlike `StepSummary::step`, this predicate does not compress
* type-preserving steps.
*/
predicate smallstep(Node nodeFrom, TypeTrackingNode nodeTo, StepSummary summary) {
smallstepNoCall(nodeFrom, nodeTo, summary)
or
smallstepCall(nodeFrom, nodeTo, summary)
}
/** Gets the step summary for a level step. */
StepSummary levelStep() { result = LevelStep() }
/** Gets the step summary for a call step. */
StepSummary callStep() { result = CallStep() }
/** Gets the step summary for a return step. */
StepSummary returnStep() { result = ReturnStep() }
/** Gets the step summary for storing into `content`. */
StepSummary storeStep(TypeTrackerContent content) { result = StoreStep(content) }
/** Gets the step summary for loading from `content`. */
StepSummary loadStep(TypeTrackerContent content) { result = LoadStep(content) }
/** Gets the step summary for loading from `load` and then storing into `store`. */
StepSummary loadStoreStep(TypeTrackerContent load, TypeTrackerContent store) {
result = LoadStoreStep(load, store)
}
/** Gets the step summary for a step that only permits contents matched by `filter`. */
StepSummary withContent(ContentFilter filter) { result = WithContent(filter) }
/** Gets the step summary for a step that blocks contents matched by `filter`. */
StepSummary withoutContent(ContentFilter filter) { result = WithoutContent(filter) }
/** Gets the step summary for a jump step. */
StepSummary jumpStep() { result = JumpStep() }
}
/**
* DEPRECATED: Use `codeql.ruby.typetracking.TypeTracking` instead.
*
* A summary of the steps needed to track a value to a given dataflow node.
*
* This can be used to track objects that implement a certain API in order to
* recognize calls to that API. Note that type-tracking does not by itself provide a
* source/sink relation, that is, it may determine that a node has a given type,
* but it won't determine where that type came from.
*
* It is recommended that all uses of this type are written in the following form,
* for tracking some type `myType`:
* ```ql
* DataFlow::TypeTrackingNode myType(DataFlow::TypeTracker t) {
* t.start() and
* result = < source of myType >
* or
* exists (DataFlow::TypeTracker t2 |
* result = myType(t2).track(t2, t)
* )
* }
*
* DataFlow::Node myType() { myType(DataFlow::TypeTracker::end()).flowsTo(result) }
* ```
*
* Instead of `result = myType(t2).track(t2, t)`, you can also use the equivalent
* `t = t2.step(myType(t2), result)`. If you additionally want to track individual
* intra-procedural steps, use `t = t2.smallstep(myCallback(t2), result)`.
*/
deprecated class TypeTracker extends TTypeTracker {
Boolean hasCall;
OptionalTypeTrackerContent content;
TypeTracker() { this = MkTypeTracker(hasCall, content) }
/** Gets the summary resulting from appending `step` to this type-tracking summary. */
TypeTracker append(StepSummary step) { result = append(this, step) }
/** Gets a textual representation of this summary. */
string toString() {
exists(string withCall, string withContent |
(if hasCall = true then withCall = "with" else withCall = "without") and
(
if content != noContent()
then withContent = " with content " + content
else withContent = ""
) and
result = "type tracker " + withCall + " call steps" + withContent
)
}
/**
* Holds if this is the starting point of type tracking.
*/
predicate start() { hasCall = false and content = noContent() }
/**
* Holds if this is the starting point of type tracking, and the value starts in the content named `contentName`.
* The type tracking only ends after the content has been loaded.
*/
predicate startInContent(TypeTrackerContent contentName) {
hasCall = false and content = contentName
}
/**
* Holds if this is the starting point of type tracking
* when tracking a parameter into a call, but not out of it.
*/
predicate call() { hasCall = true and content = noContent() }
/**
* Holds if this is the end point of type tracking.
*/
predicate end() { content = noContent() }
/**
* INTERNAL. DO NOT USE.
*
* Holds if this type has been tracked into a call.
*/
boolean hasCall() { result = hasCall }
/**
* INTERNAL. DO NOT USE.
*
* Gets the content associated with this type tracker.
*/
OptionalTypeTrackerContent getContent() { result = content }
/**
* Gets a type tracker that starts where this one has left off to allow continued
* tracking.
*
* This predicate is only defined if the type is not associated to a piece of content.
*/
TypeTracker continue() { content = noContent() and result = this }
/**
* Gets the summary that corresponds to having taken a forwards
* heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*/
bindingset[nodeFrom, this]
pragma[inline_late]
pragma[noopt]
TypeTracker step(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo) {
exists(StepSummary summary |
stepProj(nodeFrom, summary) and
result = this.append(summary) and
step(nodeFrom, nodeTo, summary)
)
}
bindingset[nodeFrom, this]
pragma[inline_late]
pragma[noopt]
private TypeTracker smallstepNoSimpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
exists(StepSummary summary |
smallstepProj(nodeFrom, summary) and
result = this.append(summary) and
smallstep(nodeFrom, nodeTo, summary)
)
}
/**
* Gets the summary that corresponds to having taken a forwards
* local, heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*
* Unlike `TypeTracker::step`, this predicate exposes all edges
* in the flow graph, and not just the edges between `Node`s.
* It may therefore be less performant.
*
* Type tracking predicates using small steps typically take the following form:
* ```ql
* DataFlow::Node myType(DataFlow::TypeTracker t) {
* t.start() and
* result = < source of myType >
* or
* exists (DataFlow::TypeTracker t2 |
* t = t2.smallstep(myType(t2), result)
* )
* }
*
* DataFlow::Node myType() {
* result = myType(DataFlow::TypeTracker::end())
* }
* ```
*/
pragma[inline]
TypeTracker smallstep(Node nodeFrom, Node nodeTo) {
result = this.smallstepNoSimpleLocalFlowStep(nodeFrom, nodeTo)
or
simpleLocalFlowStep(nodeFrom, nodeTo) and
result = this
}
}
/** Provides predicates for implementing custom `TypeTracker`s. */
deprecated module TypeTracker {
/**
* Gets a valid end point of type tracking.
*/
TypeTracker end() { result.end() }
/**
* INTERNAL USE ONLY.
*
* Gets a valid end point of type tracking with the call bit set to the given value.
*/
predicate end = Cached::noContentTypeTracker/1;
}
pragma[nomagic]
deprecated private predicate backStepProj(TypeTrackingNode nodeTo, StepSummary summary) {
step(_, nodeTo, summary)
}
deprecated private predicate backSmallstepProj(TypeTrackingNode nodeTo, StepSummary summary) {
smallstep(_, nodeTo, summary)
}
/**
* DEPRECATED: Use `codeql.ruby.typetracking.TypeTracking` instead.
*
* A summary of the steps needed to back-track a use of a value to a given dataflow node.
*
* This can for example be used to track callbacks that are passed to a certain API,
* so we can model specific parameters of that callback as having a certain type.
*
* Note that type back-tracking does not provide a source/sink relation, that is,
* it may determine that a node will be used in an API call somewhere, but it won't
* determine exactly where that use was, or the path that led to the use.
*
* It is recommended that all uses of this type are written in the following form,
* for back-tracking some callback type `myCallback`:
*
* ```ql
* DataFlow::TypeTrackingNode myCallback(DataFlow::TypeBackTracker t) {
* t.start() and
* result = (< some API call >).getArgument(< n >).getALocalSource()
* or
* exists (DataFlow::TypeBackTracker t2 |
* result = myCallback(t2).backtrack(t2, t)
* )
* }
*
* DataFlow::TypeTrackingNode myCallback() { result = myCallback(DataFlow::TypeBackTracker::end()) }
* ```
*
* Instead of `result = myCallback(t2).backtrack(t2, t)`, you can also use the equivalent
* `t2 = t.step(result, myCallback(t2))`. If you additionally want to track individual
* intra-procedural steps, use `t2 = t.smallstep(result, myCallback(t2))`.
*/
deprecated class TypeBackTracker extends TTypeBackTracker {
Boolean hasReturn;
OptionalTypeTrackerContent content;
TypeBackTracker() { this = MkTypeBackTracker(hasReturn, content) }
/** Gets the summary resulting from prepending `step` to this type-tracking summary. */
TypeBackTracker prepend(StepSummary step) { result = prepend(this, step) }
/** Gets a textual representation of this summary. */
string toString() {
exists(string withReturn, string withContent |
(if hasReturn = true then withReturn = "with" else withReturn = "without") and
(
if content != noContent()
then withContent = " with content " + content
else withContent = ""
) and
result = "type back-tracker " + withReturn + " return steps" + withContent
)
}
/**
* Holds if this is the starting point of type tracking.
*/
predicate start() { hasReturn = false and content = noContent() }
/**
* Holds if this is the end point of type tracking.
*/
predicate end() { content = noContent() }
/**
* INTERNAL. DO NOT USE.
*
* Holds if this type has been back-tracked into a call through return edge.
*/
boolean hasReturn() { result = hasReturn }
/**
* Gets a type tracker that starts where this one has left off to allow continued
* tracking.
*
* This predicate is only defined if the type has not been tracked into a piece of content.
*/
TypeBackTracker continue() { content = noContent() and result = this }
/**
* Gets the summary that corresponds to having taken a backwards
* heap and/or inter-procedural step from `nodeTo` to `nodeFrom`.
*/
bindingset[nodeTo, result]
pragma[inline_late]
pragma[noopt]
TypeBackTracker step(TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo) {
exists(StepSummary summary |
backStepProj(nodeTo, summary) and
this = result.prepend(summary) and
step(nodeFrom, nodeTo, summary)
)
}
bindingset[nodeTo, result]
pragma[inline_late]
pragma[noopt]
private TypeBackTracker smallstepNoSimpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
exists(StepSummary summary |
backSmallstepProj(nodeTo, summary) and
this = result.prepend(summary) and
smallstep(nodeFrom, nodeTo, summary)
)
}
/**
* Gets the summary that corresponds to having taken a backwards
* local, heap and/or inter-procedural step from `nodeTo` to `nodeFrom`.
*
* Unlike `TypeBackTracker::step`, this predicate exposes all edges
* in the flowgraph, and not just the edges between
* `TypeTrackingNode`s. It may therefore be less performant.
*
* Type tracking predicates using small steps typically take the following form:
* ```ql
* DataFlow::Node myType(DataFlow::TypeBackTracker t) {
* t.start() and
* result = < some API call >.getArgument(< n >)
* or
* exists (DataFlow::TypeBackTracker t2 |
* t = t2.smallstep(result, myType(t2))
* )
* }
*
* DataFlow::Node myType() {
* result = myType(DataFlow::TypeBackTracker::end())
* }
* ```
*/
pragma[inline]
TypeBackTracker smallstep(Node nodeFrom, Node nodeTo) {
this = this.smallstepNoSimpleLocalFlowStep(nodeFrom, nodeTo)
or
simpleLocalFlowStep(nodeFrom, nodeTo) and
this = result
}
/**
* Gets a forwards summary that is compatible with this backwards summary.
* That is, if this summary describes the steps needed to back-track a value
* from `sink` to `mid`, and the result is a valid summary of the steps needed
* to track a value from `source` to `mid`, then the value from `source` may
* also flow to `sink`.
*/
TypeTracker getACompatibleTypeTracker() {
exists(boolean hasCall, OptionalTypeTrackerContent c |
result = MkTypeTracker(hasCall, c) and
(
compatibleContents(c, content)
or
content = noContent() and c = content
)
|
hasCall = false
or
this.hasReturn() = false
)
}
}
/** Provides predicates for implementing custom `TypeBackTracker`s. */
deprecated module TypeBackTracker {
/**
* Gets a valid end point of type back-tracking.
*/
TypeBackTracker end() { result.end() }
}
/**
* INTERNAL: Do not use.
*
* Provides logic for constructing a call graph in mutual recursion with type tracking.
*
* When type tracking is used to construct a call graph, we cannot use the join-order
* from `stepInlineLate`, because `step` becomes a recursive call, which means that we
* will have a conjunct with 3 recursive calls: the call to `step`, the call to `stepProj`,
* and the recursive type tracking call itself. The solution is to split the three-way
* non-linear recursion into two non-linear predicates: one that first joins with the
* projected `stepCall` relation, followed by a predicate that joins with the full
* `stepCall` relation (`stepNoCall` not being recursive, can be join-ordered in the
* same way as in `stepInlineLate`).
*/
deprecated module CallGraphConstruction {
/** The input to call graph construction. */
signature module InputSig {
/** A state to track during type tracking. */
class State;
/** Holds if type tracking should start at `start` in state `state`. */
deprecated predicate start(Node start, State state);
/**
* Holds if type tracking should use the step from `nodeFrom` to `nodeTo`,
* which _does not_ depend on the call graph.
*
* Implementing this predicate using `StepSummary::[small]stepNoCall` yields
* standard type tracking.
*/
deprecated predicate stepNoCall(Node nodeFrom, Node nodeTo, StepSummary summary);
/**
* Holds if type tracking should use the step from `nodeFrom` to `nodeTo`,
* which _does_ depend on the call graph.
*
* Implementing this predicate using `StepSummary::[small]stepCall` yields
* standard type tracking.
*/
deprecated predicate stepCall(Node nodeFrom, Node nodeTo, StepSummary summary);
/** A projection of an element from the state space. */
class StateProj;
/** Gets the projection of `state`. */
StateProj stateProj(State state);
/** Holds if type tracking should stop at `n` when we are tracking projected state `stateProj`. */
deprecated predicate filter(Node n, StateProj stateProj);
}
/** Provides the `track` predicate for use in call graph construction. */
module Make<InputSig Input> {
pragma[nomagic]
deprecated private predicate stepNoCallProj(Node nodeFrom, StepSummary summary) {
Input::stepNoCall(nodeFrom, _, summary)
}
pragma[nomagic]
deprecated private predicate stepCallProj(Node nodeFrom, StepSummary summary) {
Input::stepCall(nodeFrom, _, summary)
}
bindingset[nodeFrom, t]
pragma[inline_late]
pragma[noopt]
deprecated private TypeTracker stepNoCallInlineLate(
TypeTracker t, TypeTrackingNode nodeFrom, TypeTrackingNode nodeTo
) {
exists(StepSummary summary |
stepNoCallProj(nodeFrom, summary) and
result = t.append(summary) and
Input::stepNoCall(nodeFrom, nodeTo, summary)
)
}
bindingset[state]
pragma[inline_late]
private Input::StateProj stateProjInlineLate(Input::State state) {
result = Input::stateProj(state)
}
pragma[nomagic]
deprecated private Node track(Input::State state, TypeTracker t) {
t.start() and Input::start(result, state)
or
exists(Input::StateProj stateProj |
stateProj = stateProjInlineLate(state) and
not Input::filter(result, stateProj)
|
exists(TypeTracker t2 | t = stepNoCallInlineLate(t2, track(state, t2), result))
or
exists(StepSummary summary |
// non-linear recursion
Input::stepCall(trackCall(state, t, summary), result, summary)
)
)
}
bindingset[t, summary]
pragma[inline_late]
deprecated private TypeTracker appendInlineLate(TypeTracker t, StepSummary summary) {
result = t.append(summary)
}
pragma[nomagic]
deprecated private Node trackCall(Input::State state, TypeTracker t, StepSummary summary) {
exists(TypeTracker t2 |
// non-linear recursion
result = track(state, t2) and
stepCallProj(result, summary) and
t = appendInlineLate(t2, summary)
)
}
/** Gets a node that can be reached from _some_ start node in state `state`. */
pragma[nomagic]
deprecated Node track(Input::State state) { result = track(state, TypeTracker::end()) }
}
/** A simple version of `CallGraphConstruction` that uses standard type tracking. */
module Simple {
/** The input to call graph construction. */
signature module InputSig {
/** A state to track during type tracking. */
class State;
/** Holds if type tracking should start at `start` in state `state`. */
deprecated predicate start(Node start, State state);
/** Holds if type tracking should stop at `n`. */
deprecated predicate filter(Node n);
}
/** Provides the `track` predicate for use in call graph construction. */
module Make<InputSig Input> {
deprecated private module I implements CallGraphConstruction::InputSig {
private import codeql.util.Unit
class State = Input::State;
predicate start(Node start, State state) { Input::start(start, state) }
predicate stepNoCall(Node nodeFrom, Node nodeTo, StepSummary summary) {
StepSummary::stepNoCall(nodeFrom, nodeTo, summary)
}
predicate stepCall(Node nodeFrom, Node nodeTo, StepSummary summary) {
StepSummary::stepCall(nodeFrom, nodeTo, summary)
}
class StateProj = Unit;
Unit stateProj(State state) { exists(state) and exists(result) }
predicate filter(Node n, Unit u) {
Input::filter(n) and
exists(u)
}
}
deprecated import CallGraphConstruction::Make<I>
}
}
}

View File

@@ -1,135 +0,0 @@
private import codeql.ruby.dataflow.internal.DataFlowPublic as DataFlowPublic
private import codeql.ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate
private import internal.TypeTrackingImpl as TypeTrackingImpl
deprecated import codeql.util.Boolean
deprecated class Node = DataFlowPublic::Node;
deprecated class TypeTrackingNode = DataFlowPublic::LocalSourceNode;
deprecated class TypeTrackerContent = DataFlowPublic::ContentSet;
/**
* An optional content set, that is, a `ContentSet` or the special "no content set" value.
*/
deprecated class OptionalTypeTrackerContent extends DataFlowPrivate::TOptionalContentSet {
/** Gets a textual representation of this content set. */
string toString() {
this instanceof DataFlowPrivate::TNoContentSet and
result = "no content"
or
result = this.(DataFlowPublic::ContentSet).toString()
}
}
/**
* A label to use for `WithContent` and `WithoutContent` steps, restricting
* which `ContentSet` may pass through.
*/
deprecated class ContentFilter = TypeTrackingImpl::TypeTrackingInput::ContentFilter;
/** Module for getting `ContentFilter` values. */
deprecated module ContentFilter {
/** Gets the filter that only allow element contents. */
ContentFilter hasElements() { any() }
}
/**
* Holds if a value stored with `storeContents` can be read back with `loadContents`.
*/
pragma[inline]
deprecated predicate compatibleContents(
TypeTrackerContent storeContents, TypeTrackerContent loadContents
) {
storeContents.getAStoreContent() = loadContents.getAReadContent()
}
/** Gets the "no content set" value to use for a type tracker not inside any content. */
deprecated OptionalTypeTrackerContent noContent() { result = DataFlowPrivate::TNoContentSet() }
/** Holds if there is a simple local flow step from `nodeFrom` to `nodeTo` */
deprecated predicate simpleLocalFlowStep =
TypeTrackingImpl::TypeTrackingInput::simpleLocalSmallStep/2;
/**
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
deprecated predicate jumpStep = TypeTrackingImpl::TypeTrackingInput::jumpStep/2;
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */
deprecated predicate levelStepCall = TypeTrackingImpl::TypeTrackingInput::levelStepCall/2;
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which does not depend on the call graph. */
deprecated predicate levelStepNoCall = TypeTrackingImpl::TypeTrackingInput::levelStepNoCall/2;
/**
* Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call.
*
* Flow into summarized library methods is not included, as that will lead to negative
* recursion (or, at best, terrible performance), since identifying calls to library
* methods is done using API graphs (which uses type tracking).
*/
deprecated predicate callStep = TypeTrackingImpl::TypeTrackingInput::callStep/2;
/**
* Holds if `nodeFrom` steps to `nodeTo` by being returned from a call.
*
* Flow out of summarized library methods is not included, as that will lead to negative
* recursion (or, at best, terrible performance), since identifying calls to library
* methods is done using API graphs (which uses type tracking).
*/
deprecated predicate returnStep = TypeTrackingImpl::TypeTrackingInput::returnStep/2;
/**
* Holds if `nodeFrom` is being written to the `contents` of the object
* in `nodeTo`.
*
* Note that the choice of `nodeTo` does not have to make sense
* "chronologically". All we care about is whether the `contents` of
* `nodeTo` can have a specific type, and the assumption is that if a specific
* type appears here, then any access of that particular content can yield
* something of that particular type.
*
* Thus, in an example such as
*
* ```rb
* def foo(y)
* x = Foo.new
* bar(x)
* x.content = y
* baz(x)
* end
*
* def bar(x)
* z = x.content
* end
* ```
* for the content write `x.content = y`, we will have `contents` being the
* literal string `"content"`, `nodeFrom` will be `y`, and `nodeTo` will be the
* `Foo` object created on the first line of the function. This means we will
* track the fact that `x.content` can have the type of `y` into the assignment
* to `z` inside `bar`, even though this content write happens _after_ `bar` is
* called.
*/
deprecated predicate basicStoreStep = TypeTrackingImpl::TypeTrackingInput::storeStep/3;
/**
* Holds if `nodeTo` is the result of accessing the `content` content of `nodeFrom`.
*/
deprecated predicate basicLoadStep = TypeTrackingImpl::TypeTrackingInput::loadStep/3;
/**
* Holds if the `loadContent` of `nodeFrom` is stored in the `storeContent` of `nodeTo`.
*/
deprecated predicate basicLoadStoreStep = TypeTrackingImpl::TypeTrackingInput::loadStoreStep/4;
/**
* Holds if type-tracking should step from `nodeFrom` to `nodeTo` but block flow of contents matched by `filter` through here.
*/
deprecated predicate basicWithoutContentStep =
TypeTrackingImpl::TypeTrackingInput::withoutContentStep/3;
/**
* Holds if type-tracking should step from `nodeFrom` to `nodeTo` if inside a content matched by `filter`.
*/
deprecated predicate basicWithContentStep = TypeTrackingImpl::TypeTrackingInput::withContentStep/3;

View File

@@ -3,6 +3,3 @@ sourceTest
| hello_world_server.rb:32:18:32:20 | req |
ssrfSinkTest
| hello_world_client.rb:6:47:6:75 | "http://localhost:8080/twirp" |
serviceInstantiationTest
| hello_world_server.rb:24:11:24:61 | call to new |
| hello_world_server.rb:38:1:38:57 | call to new |

View File

@@ -4,5 +4,3 @@ private import codeql.ruby.DataFlow
query predicate sourceTest(Twirp::UnmarshaledParameter source) { any() }
query predicate ssrfSinkTest(Twirp::ServiceUrlAsSsrfSink sink) { any() }
deprecated query predicate serviceInstantiationTest(Twirp::ServiceInstantiation si) { any() }

View File

@@ -146,87 +146,6 @@ activeRecordSqlExecutionRanges
| ActiveRecord.rb:73:20:73:39 | "username = #{...}" |
| ActiveRecord.rb:85:21:85:44 | ...[...] |
| ActiveRecord.rb:123:27:123:76 | "this is an unsafe annotation:..." |
activeRecordModelClassMethodCalls
| ActiveRecord.rb:2:3:2:17 | call to has_many |
| ActiveRecord.rb:6:3:6:24 | call to belongs_to |
| ActiveRecord.rb:9:5:9:68 | call to find |
| ActiveRecord.rb:13:5:13:40 | call to find_by |
| ActiveRecord.rb:13:5:13:46 | call to users |
| ActiveRecord.rb:36:5:36:25 | call to destroy_by |
| ActiveRecord.rb:45:5:45:45 | call to calculate |
| ActiveRecord.rb:46:5:46:43 | call to delete_by |
| ActiveRecord.rb:47:5:47:46 | call to destroy_by |
| ActiveRecord.rb:48:5:48:35 | call to where |
| ActiveRecord.rb:51:5:51:14 | call to where |
| ActiveRecord.rb:51:5:51:48 | call to not |
| ActiveRecord.rb:53:5:53:30 | call to find_by_name |
| ActiveRecord.rb:54:5:54:36 | call to not_a_find_by_method |
| ActiveRecord.rb:63:5:63:33 | call to delete_by |
| ActiveRecord.rb:69:5:69:29 | call to order |
| ActiveRecord.rb:73:7:73:40 | call to find_by |
| ActiveRecord.rb:77:5:77:33 | call to find_by |
| ActiveRecord.rb:79:5:79:34 | call to find |
| ActiveRecord.rb:89:5:89:24 | call to create |
| ActiveRecord.rb:93:5:93:66 | call to create |
| ActiveRecord.rb:97:5:97:68 | call to create |
| ActiveRecord.rb:101:5:101:16 | call to create |
| ActiveRecord.rb:105:5:105:27 | call to update |
| ActiveRecord.rb:109:5:109:69 | call to update |
| ActiveRecord.rb:113:5:113:71 | call to update |
| ActiveRecord.rb:119:13:119:54 | call to annotate |
| ActiveRecord.rb:123:13:123:77 | call to annotate |
| associations.rb:2:3:2:17 | call to has_many |
| associations.rb:6:3:6:20 | call to belongs_to |
| associations.rb:7:3:7:20 | call to has_many |
| associations.rb:8:3:8:31 | call to has_and_belongs_to_many |
| associations.rb:12:3:12:32 | call to has_and_belongs_to_many |
| associations.rb:16:3:16:18 | call to belongs_to |
| associations.rb:19:11:19:20 | call to new |
| associations.rb:21:9:21:21 | call to posts |
| associations.rb:21:9:21:28 | call to create |
| associations.rb:23:12:23:25 | call to comments |
| associations.rb:23:12:23:32 | call to create |
| associations.rb:25:11:25:22 | call to author |
| associations.rb:27:9:27:21 | call to posts |
| associations.rb:27:9:27:28 | call to create |
| associations.rb:29:1:29:13 | call to posts |
| associations.rb:29:1:29:22 | ... << ... |
| associations.rb:31:1:31:12 | call to author= |
| associations.rb:35:1:35:14 | call to comments |
| associations.rb:35:1:35:21 | call to create |
| associations.rb:35:1:35:28 | call to create |
| associations.rb:37:1:37:13 | call to posts |
| associations.rb:37:1:37:20 | call to reload |
| associations.rb:37:1:37:27 | call to create |
| associations.rb:39:1:39:15 | call to build_tag |
| associations.rb:40:1:40:15 | call to build_tag |
| associations.rb:42:1:42:13 | call to posts |
| associations.rb:42:1:42:25 | call to push |
| associations.rb:43:1:43:13 | call to posts |
| associations.rb:43:1:43:27 | call to concat |
| associations.rb:44:1:44:13 | call to posts |
| associations.rb:44:1:44:19 | call to build |
| associations.rb:45:1:45:13 | call to posts |
| associations.rb:45:1:45:20 | call to create |
| associations.rb:46:1:46:13 | call to posts |
| associations.rb:46:1:46:21 | call to create! |
| associations.rb:47:1:47:13 | call to posts |
| associations.rb:47:1:47:20 | call to delete |
| associations.rb:48:1:48:13 | call to posts |
| associations.rb:48:1:48:24 | call to delete_all |
| associations.rb:49:1:49:13 | call to posts |
| associations.rb:49:1:49:21 | call to destroy |
| associations.rb:50:1:50:13 | call to posts |
| associations.rb:50:1:50:25 | call to destroy_all |
| associations.rb:51:1:51:13 | call to posts |
| associations.rb:51:1:51:22 | call to distinct |
| associations.rb:51:1:51:36 | call to find |
| associations.rb:52:1:52:13 | call to posts |
| associations.rb:52:1:52:19 | call to reset |
| associations.rb:52:1:52:33 | call to find |
| associations.rb:53:1:53:13 | call to posts |
| associations.rb:53:1:53:20 | call to reload |
| associations.rb:53:1:53:34 | call to find |
activeRecordModelClassMethodCallsReplacement
| ActiveRecord.rb:1:1:3:3 | UserGroup | ActiveRecord.rb:2:3:2:17 | call to has_many |
| ActiveRecord.rb:1:1:3:3 | UserGroup | ActiveRecord.rb:13:5:13:40 | call to find_by |
@@ -272,18 +191,6 @@ activeRecordModelClassMethodCallsReplacement
| associations.rb:5:1:9:3 | Post | associations.rb:8:3:8:31 | call to has_and_belongs_to_many |
| associations.rb:11:1:13:3 | Tag | associations.rb:12:3:12:32 | call to has_and_belongs_to_many |
| associations.rb:15:1:17:3 | Comment | associations.rb:16:3:16:18 | call to belongs_to |
potentiallyUnsafeSqlExecutingMethodCall
| ActiveRecord.rb:9:5:9:68 | call to find |
| ActiveRecord.rb:36:5:36:25 | call to destroy_by |
| ActiveRecord.rb:45:5:45:45 | call to calculate |
| ActiveRecord.rb:46:5:46:43 | call to delete_by |
| ActiveRecord.rb:47:5:47:46 | call to destroy_by |
| ActiveRecord.rb:48:5:48:35 | call to where |
| ActiveRecord.rb:51:5:51:48 | call to not |
| ActiveRecord.rb:63:5:63:33 | call to delete_by |
| ActiveRecord.rb:69:5:69:29 | call to order |
| ActiveRecord.rb:73:7:73:40 | call to find_by |
| ActiveRecord.rb:123:13:123:77 | call to annotate |
activeRecordModelInstantiations
| ActiveRecord.rb:9:5:9:68 | call to find | ActiveRecord.rb:5:1:32:3 | User |
| ActiveRecord.rb:13:5:13:40 | call to find_by | ActiveRecord.rb:1:1:3:3 | UserGroup |

View File

@@ -9,22 +9,12 @@ query predicate activeRecordInstances(ActiveRecordInstance i) { any() }
query predicate activeRecordSqlExecutionRanges(ActiveRecordSqlExecutionRange range) { any() }
deprecated query predicate activeRecordModelClassMethodCalls(ActiveRecordModelClassMethodCall call) {
any()
}
query predicate activeRecordModelClassMethodCallsReplacement(
ActiveRecordModelClass cls, DataFlow::CallNode call
) {
call = cls.getClassNode().trackModule().getAMethodCall(_)
}
deprecated query predicate potentiallyUnsafeSqlExecutingMethodCall(
PotentiallyUnsafeSqlExecutingMethodCall call
) {
any()
}
query predicate activeRecordModelInstantiations(
ActiveRecordModelInstantiation i, ActiveRecordModelClass cls
) {

View File

@@ -10,29 +10,6 @@ modelClassMethodCalls
| active_resource.rb:23:10:23:19 | call to all |
| active_resource.rb:24:10:24:26 | call to find |
| active_resource.rb:30:3:30:11 | call to site= |
modelInstances
| active_resource.rb:5:1:5:5 | alice |
| active_resource.rb:5:1:5:33 | ... = ... |
| active_resource.rb:5:9:5:33 | call to new |
| active_resource.rb:6:1:6:5 | alice |
| active_resource.rb:8:1:8:5 | alice |
| active_resource.rb:8:1:8:22 | ... = ... |
| active_resource.rb:8:9:8:22 | call to find |
| active_resource.rb:9:1:9:5 | alice |
| active_resource.rb:10:1:10:5 | alice |
| active_resource.rb:12:1:12:5 | alice |
| active_resource.rb:16:1:16:23 | call to new |
| active_resource.rb:17:1:17:5 | alice |
| active_resource.rb:18:1:18:22 | call to get |
| active_resource.rb:19:1:19:5 | alice |
| active_resource.rb:24:1:24:6 | people |
| active_resource.rb:24:1:24:26 | ... = ... |
| active_resource.rb:24:10:24:26 | call to find |
| active_resource.rb:26:1:26:5 | alice |
| active_resource.rb:26:1:26:20 | ... = ... |
| active_resource.rb:26:9:26:14 | people |
| active_resource.rb:26:9:26:20 | call to first |
| active_resource.rb:27:1:27:5 | alice |
modelInstancesAsSource
| active_resource.rb:1:1:3:3 | Person | active_resource.rb:5:9:5:33 | call to new |
| active_resource.rb:1:1:3:3 | Person | active_resource.rb:8:9:8:22 | call to find |
@@ -50,13 +27,6 @@ modelInstanceMethodCalls
| active_resource.rb:19:1:19:19 | call to delete |
| active_resource.rb:26:9:26:20 | call to first |
| active_resource.rb:27:1:27:10 | call to save |
collections
| active_resource.rb:23:1:23:19 | ... = ... |
| active_resource.rb:23:10:23:19 | call to all |
| active_resource.rb:24:1:24:6 | people |
| active_resource.rb:24:1:24:26 | ... = ... |
| active_resource.rb:24:10:24:26 | call to find |
| active_resource.rb:26:9:26:14 | people |
collectionSources
| active_resource.rb:23:10:23:19 | call to all |
| active_resource.rb:24:10:24:26 | call to find |

View File

@@ -14,8 +14,6 @@ query predicate modelClasses(
query predicate modelClassMethodCalls(ActiveResource::ModelClassMethodCall c) { any() }
deprecated query predicate modelInstances(ActiveResource::ModelInstance c) { any() }
query predicate modelInstancesAsSource(
ActiveResource::ModelClassNode cls, DataFlow::LocalSourceNode node
) {
@@ -24,6 +22,4 @@ query predicate modelInstancesAsSource(
query predicate modelInstanceMethodCalls(ActiveResource::ModelInstanceMethodCall c) { any() }
deprecated query predicate collections(ActiveResource::Collection c) { any() }
query predicate collectionSources(ActiveResource::CollectionSource c) { any() }

View File

@@ -0,0 +1,5 @@
---
category: breaking
---
* Deleted the deprecated `Make` and `MakeWithState` modules, use `Global` and `GlobalWithState` instead.
* Deleted the deprecated `hasFlow`, `hasFlowPath`, `hasFlowTo`, and `hasFlowToExpr` predicates, use `flow`, `flowPath`, `flowTo`, and `flowToExpr` respectively instead.

View File

@@ -703,11 +703,6 @@ module DataFlowMake<LocationSig Location, InputSig<Location> Lang> {
import Impl<C>
}
/** DEPRECATED: Use `Global` instead. */
deprecated module Make<ConfigSig Config> implements GlobalFlowSig {
import Global<Config>
}
/**
* Constructs a global data flow computation using flow state.
*/
@@ -731,11 +726,6 @@ module DataFlowMake<LocationSig Location, InputSig<Location> Lang> {
import Impl<C>
}
/** DEPRECATED: Use `GlobalWithState` instead. */
deprecated module MakeWithState<StateConfigSig Config> implements GlobalFlowSig {
import GlobalWithState<Config>
}
signature class PathNodeSig {
/** Gets a textual representation of this element. */
string toString();

View File

@@ -97,11 +97,6 @@ module TaintFlowMake<
import DataFlowInternal::Impl<C>
}
/** DEPRECATED: Use `Global` instead. */
deprecated module Make<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig {
import Global<Config>
}
/**
* Constructs a global taint tracking computation using flow state.
*/
@@ -130,13 +125,6 @@ module TaintFlowMake<
import DataFlowInternal::Impl<C>
}
/** DEPRECATED: Use `GlobalWithState` instead. */
deprecated module MakeWithState<DataFlow::StateConfigSig Config> implements
DataFlow::GlobalFlowSig
{
import GlobalWithState<Config>
}
signature int speculationLimitSig();
private module AddSpeculativeTaintSteps<

View File

@@ -4614,9 +4614,6 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
import S6
/** DEPRECATED: Use `flowPath` instead. */
deprecated predicate hasFlowPath = flowPath/2;
/**
* Holds if data can flow from `source` to `sink`.
*/
@@ -4626,25 +4623,16 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
)
}
/** DEPRECATED: Use `flow` instead. */
deprecated predicate hasFlow = flow/2;
/**
* Holds if data can flow from some source to `sink`.
*/
predicate flowTo(Node sink) { exists(PathNode n | n.isSink() and n.getNode() = sink) }
/** DEPRECATED: Use `flowTo` instead. */
deprecated predicate hasFlowTo = flowTo/1;
/**
* Holds if data can flow from some source to `sink`.
*/
predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) }
/** DEPRECATED: Use `flowToExpr` instead. */
deprecated predicate hasFlowToExpr = flowToExpr/1;
/**
* INTERNAL: Only for debugging.
*

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* Deleted the deprecated `ConsistencyChecks` module.

View File

@@ -137,8 +137,6 @@ module TypeTracking<LocationSig Location, TypeTrackingInput<Location> I> {
private module ConsistencyChecksInput implements MkImpl::ConsistencyChecksInputSig { }
deprecated module ConsistencyChecks = MkImpl::ConsistencyChecks<ConsistencyChecksInput>;
class TypeTracker = MkImpl::TypeTracker;
module TypeTracker = MkImpl::TypeTracker;

View File

@@ -830,13 +830,6 @@ module TypeTracking<LocationSig Location, TypeTrackingInput<Location> I> {
private predicate stepPlus(PathNode n1, PathNode n2) = fastTC(edges/2)(n1, n2)
/**
* DEPRECATED: Use `flowPath` instead.
*
* Holds if there is a path between `source` and `sink`.
*/
deprecated predicate hasFlow(PathNode source, PathNode sink) { flowPath(source, sink) }
/** Holds if there is a path between `source` and `sink`. */
predicate flowPath(PathNode source, PathNode sink) {
source.isSource() and

View File

@@ -0,0 +1,5 @@
---
category: breaking
---
* Deleted the deprecated `ArrayContent` class from the dataflow library, use `CollectionContent` instead.
* Deleted the deprecated `getOptionsInput`, `getRegexInput`, and `getStringInput` predicates from the regexp library, use `getAnOptionsInput`, `getRegexInputNode`, and `getStringInputNode` instead.

View File

@@ -250,11 +250,6 @@ module Content {
override string toString() { result = "Collection element" }
}
/**
* DEPRECATED: An element of a collection. This is an alias for the general CollectionContent.
*/
deprecated class ArrayContent = CollectionContent;
/** A captured variable. */
class CapturedVariableContent extends Content, TCapturedVariableContent {
CapturedVariable v;

View File

@@ -73,11 +73,6 @@ abstract class RegexCreation extends DataFlow::Node {
* such as parse mode flags (if any).
*/
DataFlow::Node getAnOptionsInput() { none() }
/**
* DEPRECATED: Use `getAnOptionsInput()` instead.
*/
deprecated DataFlow::Node getOptionsInput() { result = this.getAnOptionsInput() }
}
/**
@@ -309,21 +304,11 @@ abstract class RegexEval extends CallExpr {
*/
abstract DataFlow::Node getRegexInputNode();
/**
* DEPRECATED: Use `getRegexInputNode()` instead.
*/
deprecated Expr getRegexInput() { result = this.getRegexInputNode().asExpr() }
/**
* Gets the input to this call that is the string the regular expression is evaluated on.
*/
abstract DataFlow::Node getStringInputNode();
/**
* DEPRECATED: Use `getStringInputNode()` instead.
*/
deprecated Expr getStringInput() { result = this.getStringInputNode().asExpr() }
/**
* Gets a dataflow node for an options input that might contain options such
* as parse mode flags (if any).