mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge pull request #18601 from erik-krogh/del-deps-jan-2025
All: delete outdated deprecations
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* Deleted the deprecated `getAllocatorCall` predicate from `DeleteOrDeleteArrayExpr`, use `getDeallocatorCall` instead.
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* Deleted the deprecated `describeBitSize` predicate from `IncorrectIntegerConversionLib.qll`
|
||||
@@ -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 |
|
||||
|
||||
11
java/ql/lib/change-notes/2025-01-27-outdated-deprecations.md
Normal file
11
java/ql/lib/change-notes/2025-01-27-outdated-deprecations.md
Normal 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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -25,9 +25,6 @@ class MockitoVerifiedMethodCall extends MethodCall {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `MockitoVerifiedMethodCall`. */
|
||||
deprecated class MockitoVerifiedMethodAccess = MockitoVerifiedMethodCall;
|
||||
|
||||
/**
|
||||
* A type that can be mocked by Mockito.
|
||||
*/
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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`.
|
||||
*/
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,6 +58,3 @@ class PartialPathTraversalMethodCall extends MethodCall {
|
||||
not isSafe(this.getArgument(0))
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `PartialPathTraversalMethodCall`. */
|
||||
deprecated class PartialPathTraversalMethodAccess = PartialPathTraversalMethodCall;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
17
ruby/ql/lib/change-notes/2025-01-27-outdated-deprecations.md
Normal file
17
ruby/ql/lib/change-notes/2025-01-27-outdated-deprecations.md
Normal 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.
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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 |
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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.
|
||||
@@ -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();
|
||||
|
||||
@@ -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<
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* Deleted the deprecated `ConsistencyChecks` module.
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
|
||||
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user