Merge branch 'master' into moremsalloc

This commit is contained in:
Jonas Jensen 2019-03-26 13:50:14 +01:00 коммит произвёл GitHub
Родитель a319356b00 702fc80054
Коммит bdd6965d1b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
59 изменённых файлов: 1145 добавлений и 98 удалений

Просмотреть файл

@ -14,5 +14,6 @@
| Mismatching new/free or malloc/delete (`cpp/new-free-mismatch`) | Fewer false positive results | Fixed an issue where functions were being identified as allocation functions inappropriately. Also affects `cpp/new-array-delete-mismatch` and `cpp/new-delete-array-mismatch`. |
| Memory may not be freed (`cpp/memory-may-not-be-freed`) | More correct results | Support added for more Microsoft-specific allocation functions, including `LocalAlloc`, `GlobalAlloc`, `HeapAlloc` and `CoTaskMemAlloc`. |
| Memory is never freed (`cpp/memory-never-freed`) | More correct results | Support added for more Microsoft-specific allocation functions, including `LocalAlloc`, `GlobalAlloc`, `HeapAlloc` and `CoTaskMemAlloc`. |
| Resource not released in destructor (`cpp/resource-not-released-in-destructor`) | Fewer false positive results | Resource allocation and deallocation functions are now determined more accurately. |
## Changes to QL libraries

Просмотреть файл

@ -3,8 +3,8 @@
@name Call to memory access function may overflow buffer (CWE-119)
+ semmlecode-cpp-queries/Critical/OverflowStatic.ql: /CWE/CWE-119
@name Static array access may cause overflow (CWE-119)
# + semmlecode-cpp-queries/Critical/OverflowDestination.ql: /CWE/CWE-119
# ^ disabled due to timeout issue
+ semmlecode-cpp-queries/Critical/OverflowDestination.ql: /CWE/CWE-119
@name Copy function using source size (CWE-119)
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql: /CWE/CWE-119
@name Potentially unsafe call to strncat (CWE-119)
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql: /CWE/CWE-119

Просмотреть файл

@ -21,7 +21,7 @@ predicate acquireExpr(Expr acquire, string kind) {
exists(FunctionCall fc, Function f, string name |
fc = acquire and
f = fc.getTarget() and
name = f.getName() and
name = f.getQualifiedName() and
(
(
name = "fopen" and
@ -47,7 +47,7 @@ predicate releaseExpr(Expr release, Expr resource, string kind) {
exists(FunctionCall fc, Function f, string name |
fc = release and
f = fc.getTarget() and
name = f.getName() and
name = f.getQualifiedName() and
(
(
name = "fclose" and

Просмотреть файл

@ -73,3 +73,39 @@ public:
int *a, *b, *c;
};
class MyClass7
{
public:
MyClass7()
{
}
bool open()
{
// ...
}
void close()
{
// ...
}
};
class myClass7Test
{
public:
myClass7Test()
{
success = mc7.open(); // GOOD
}
~myClass7Test()
{
mc7.close();
}
private:
MyClass7 mc7;
bool success;
};

Просмотреть файл

@ -37,19 +37,21 @@ namespace Semmle.Extraction.CIL.Entities
if (!def.PublicKey.IsNil)
assemblyName.SetPublicKey(cx.mdReader.GetBlobBytes(def.PublicKey));
ShortId = cx.GetId(assemblyName.FullName) + "#file:///" + cx.assemblyPath.Replace("\\", "/");
ShortId = cx.GetId(FullName) + "#file:///" + cx.assemblyPath.Replace("\\", "/");
file = new File(cx, cx.assemblyPath);
}
static readonly Id suffix = new StringId(";assembly");
string FullName => assemblyName.GetPublicKey() is null ? assemblyName.FullName + ", PublicKeyToken=null" : assemblyName.FullName;
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return file;
yield return Tuples.assemblies(this, file, assemblyName.FullName, assemblyName.Name, assemblyName.Version.ToString());
yield return Tuples.assemblies(this, file, FullName, assemblyName.Name, assemblyName.Version.ToString());
if (cx.pdb != null)
{

Просмотреть файл

@ -257,9 +257,7 @@ private module Internal {
or
cfn.isJoin()
or
exists(ControlFlowNode pred | pred = cfn.getAPredecessor() |
strictcount(pred.getASuccessor()) > 1
)
cfn.getAPredecessor().isBranch()
}
/**

Просмотреть файл

@ -17,3 +17,4 @@ import Handler
import ControlFlow
import DataFlow
import Attribute
import Stubs

Просмотреть файл

@ -0,0 +1,55 @@
/**
* Provides predicates for analysing the return values of callables.
*/
private import CIL
cached
private module Cached {
/** Holds if method `m` always returns null. */
cached
predicate alwaysNullMethod(Method m) { forex(Expr e | m.canReturn(e) | alwaysNullExpr(e)) }
/** Holds if method `m` always returns non-null. */
cached
predicate alwaysNotNullMethod(Method m) { forex(Expr e | m.canReturn(e) | alwaysNotNullExpr(e)) }
/** Holds if method `m` always throws an exception. */
cached
predicate alwaysThrowsMethod(Method m) {
m.hasBody() and
not exists(m.getImplementation().getAnInstruction().(Return))
}
/** Holds if method `m` always throws an exception of type `t`. */
cached
predicate alwaysThrowsException(Method m, Type t) {
alwaysThrowsMethod(m) and
forex(Throw ex | ex = m.getImplementation().getAnInstruction() | t = ex.getExpr().getType())
}
}
import Cached
/** Holds if expression `expr` always evaluates to `null`. */
private predicate alwaysNullExpr(Expr expr) {
expr instanceof NullLiteral
or
alwaysNullMethod(expr.(StaticCall).getTarget())
or
forex(VariableUpdate vu | DefUse::variableUpdateUse(_, vu, expr) |
alwaysNullExpr(vu.getSource())
)
}
/** Holds if expression `expr` always evaluates to non-null. */
private predicate alwaysNotNullExpr(Expr expr) {
expr instanceof Opcodes::Newobj
or
expr instanceof Literal and not expr instanceof NullLiteral
or
alwaysNotNullMethod(expr.(StaticCall).getTarget())
or
forex(VariableUpdate vu | DefUse::variableUpdateUse(_, vu, expr) |
alwaysNotNullExpr(vu.getSource())
)
}

Просмотреть файл

@ -104,7 +104,10 @@ class ControlFlowNode extends @cil_controlflow_node {
Type getType() { none() }
/** Holds if this control flow node has more than one predecessor. */
predicate isJoin() { count(getAPredecessor()) > 1 }
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
/** Holds if this control flow node has more than one successor. */
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
}
/**
@ -137,6 +140,6 @@ class TrueFlow extends FlowType, TTrueFlow {
}
/** False control flow. */
class FalseFlow extends FlowType, TTrueFlow {
class FalseFlow extends FlowType, TFalseFlow {
override string toString() { result = "false" }
}

Просмотреть файл

@ -60,7 +60,7 @@ class Tainted extends TaintType, TTaintedValue { }
private predicate localExactStep(DataFlowNode src, DataFlowNode sink) {
src = sink.(Opcodes::Dup).getAnOperand()
or
DefUse::defUse(_, src, sink)
defUse(_, src, sink)
or
src = sink.(ParameterReadAccess).getTarget()
or
@ -88,7 +88,7 @@ private predicate localTaintStep(DataFlowNode src, DataFlowNode sink) {
}
cached
private module DefUse {
module DefUse {
/**
* A classification of variable references into reads and writes.
*/
@ -185,21 +185,26 @@ private module DefUse {
)
}
/** Holds if the update `def` can be used at the read `use`. */
/** Holds if the variable update `vu` can be used at the read `use`. */
cached
predicate defUse(StackVariable target, DataFlowNode def, ReadAccess use) {
exists(VariableUpdate vu | def = vu.getSource() |
defReachesReadWithinBlock(target, vu, use)
or
exists(BasicBlock bb, int i |
exists(refRank(bb, i, target, Read())) and
use = bb.getNode(i) and
defReachesEndOfBlock(bb.getAPredecessor(), vu, target) and
not defReachesReadWithinBlock(target, _, use)
)
predicate variableUpdateUse(StackVariable target, VariableUpdate vu, ReadAccess use) {
defReachesReadWithinBlock(target, vu, use)
or
exists(BasicBlock bb, int i |
exists(refRank(bb, i, target, Read())) and
use = bb.getNode(i) and
defReachesEndOfBlock(bb.getAPredecessor(), vu, target) and
not defReachesReadWithinBlock(target, _, use)
)
}
/** Holds if the update `def` can be used at the read `use`. */
cached
predicate defUse(StackVariable target, Expr def, ReadAccess use) {
exists(VariableUpdate vu | def = vu.getSource() | variableUpdateUse(target, vu, use))
}
}
private import DefUse
abstract library class VariableUpdate extends Instruction {
abstract Expr getSource();

Просмотреть файл

@ -127,6 +127,9 @@ class FloatLiteral extends Literal, @cil_ldc_r { }
/** An expression that pushes a `null` value onto the stack. */
class NullLiteral extends Literal, @cil_ldnull { }
/** An expression that pushes a string onto the stack. */
class StringLiteral extends Literal, @cil_ldstr { }
/** A branch with one operand. */
class UnaryBranch extends ConditionalBranch, @cil_unary_jump {
override int getPopCount() { result = 1 }

Просмотреть файл

@ -234,7 +234,7 @@ module Opcodes {
override string getOpcodeName() { result = "nop" }
}
class Ldstr extends Literal, @cil_ldstr {
class Ldstr extends StringLiteral, @cil_ldstr {
override string getOpcodeName() { result = "ldstr" }
override string getExtra() { result = "\"" + getValue() + "\"" }

Просмотреть файл

@ -50,6 +50,11 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation {
int getStackSize() { cil_method_stack_size(this, result) }
override string toString() { result = getMethod().toString() }
/** Gets a string representing the disassembly of this implementation. */
string getDisassembly() {
result = concat(Instruction i | i = this.getAnInstruction() | i.toString(), ", " order by i.getIndex())
}
}
/**
@ -63,6 +68,11 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
*/
MethodImplementation getAnImplementation() { result.getMethod() = this }
/** Gets the "best" implementation of this method, if any. */
BestImplementation getImplementation() {
result = getAnImplementation()
}
override Method getMethod() { result = this }
override string getName() { cil_method(this, result, _, _) }
@ -102,7 +112,7 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
int getCallPopCount() { result = count(getRawParameter(_)) }
/** Gets a method called by this method. */
Method getACallee() { result = getAnImplementation().getAnInstruction().(Call).getTarget() }
Method getACallee() { result = getImplementation().getAnInstruction().(Call).getTarget() }
/** Holds if this method is `virtual`. */
predicate isVirtual() { cil_virtual(this) }
@ -168,10 +178,10 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
/** Gets a method that overrides this method, if any. */
final Method getAnOverrider() { result.getOverriddenMethod() = this }
override predicate hasBody() { exists(getAnImplementation()) }
override predicate hasBody() { exists(getImplementation()) }
override predicate canReturn(DotNet::Expr expr) {
exists(Return ret | ret.getImplementation().getMethod() = this and expr = ret.getExpr())
exists(Return ret | ret.getImplementation() = this.getImplementation() and expr = ret.getExpr())
}
}
@ -198,7 +208,7 @@ class InstanceConstructor extends Constructor {
/** A method that always returns the `this` parameter. */
class ChainingMethod extends Method {
ChainingMethod() {
forex(Return ret | ret = getAnImplementation().getAnInstruction() |
forex(Return ret | ret = getImplementation().getAnInstruction() |
ret.getExpr() instanceof ThisAccess
)
}
@ -232,7 +242,7 @@ class TrivialGetter extends Method {
/** Gets the underlying field of this getter. */
Field getField() {
getAnImplementation().getAnInstruction().(FieldReadAccess).getTarget() = result
getImplementation().getAnInstruction().(FieldReadAccess).getTarget() = result
}
}
@ -249,7 +259,7 @@ class Setter extends Accessor {
*/
class TrivialSetter extends Method {
TrivialSetter() {
exists(MethodImplementation impl | impl = getAnImplementation() |
exists(MethodImplementation impl | impl = getImplementation() |
impl.getInstruction(0) instanceof ThisAccess and
impl.getInstruction(1).(ParameterReadAccess).getTarget().getIndex() = 1 and
impl.getInstruction(2) instanceof FieldWriteAccess
@ -258,7 +268,7 @@ class TrivialSetter extends Method {
/** Gets the underlying field of this setter. */
Field getField() {
result = getAnImplementation().getAnInstruction().(FieldWriteAccess).getTarget()
result = getImplementation().getAnInstruction().(FieldWriteAccess).getTarget()
}
}

Просмотреть файл

@ -0,0 +1,54 @@
/**
* Provides classes and predicates for identifying stub code.
*/
import CIL
/**
* The average number of instructions per method,
* below which an assembly is probably a stub.
*/
private float stubInstructionThreshold() { result = 5.1 }
cached
private module Cached {
/**
* A simple heuristic for determining whether an assembly is a
* reference assembly where the method bodies have dummy implementations.
* Look at the average number of instructions per method.
*/
cached
predicate assemblyIsStubImpl(Assembly asm) {
exists(int totalInstructions, int totalImplementations |
totalInstructions = count(Instruction i | i.getImplementation().getLocation() = asm) and
totalImplementations = count(MethodImplementation i |
i.getImplementation().getLocation() = asm
) and
totalInstructions.(float) / totalImplementations.(float) < stubInstructionThreshold()
)
}
cached
predicate bestImplementation(MethodImplementation mi) {
not assemblyIsStubImpl(mi.getLocation()) and
not exists(MethodImplementation better | mi.getMethod() = better.getMethod() |
mi.getNumberOfInstructions() < better.getNumberOfInstructions()
or
mi.getNumberOfInstructions() = better.getNumberOfInstructions() and
mi.getLocation().getFile().toString() > better.getLocation().getFile().toString()
) and
exists(mi.getAnInstruction())
}
}
private import Cached
predicate assemblyIsStub = assemblyIsStubImpl/1;
/**
* A method implementation that is the "best" one for a particular method,
* if there are several potential implementations to choose between, and
* excludes implementations that are probably from stub/reference assemblies.
*/
class BestImplementation extends MethodImplementation {
BestImplementation() { bestImplementation(this) }
}

Просмотреть файл

@ -126,11 +126,7 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
/** Gets the constraints on this type parameter, if any. */
TypeParameterConstraints getConstraints() { result.getTypeParameter() = this }
/**
* Holds if this type parameter is guaranteed to always be instantiated
* to a reference type.
*/
predicate isRefType() {
override predicate isRefType() {
exists(TypeParameterConstraints tpc | tpc = getConstraints() |
tpc.hasRefTypeConstraint() or
exists(tpc.getClassConstraint()) or
@ -139,11 +135,7 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
)
}
/**
* Holds if this type parameter is guaranteed to always be instantiated
* to a value type.
*/
predicate isValueType() {
override predicate isValueType() {
exists(TypeParameterConstraints tpc | tpc = getConstraints() |
tpc.hasValueTypeConstraint() or
tpc.getATypeParameterConstraint().isValueType()

Просмотреть файл

@ -37,6 +37,12 @@ class Type extends DotNet::Type, Member, TypeContainer, @type {
or
not this instanceof UnboundGenericType and getAChild().containsTypeParameters()
}
/** Holds if this type is a reference type, or a type parameter that is a reference type. */
predicate isRefType() { none() }
/** Holds if this type is a value type, or a type parameter that is a value type. */
predicate isValueType() { none() }
}
/**
@ -404,7 +410,9 @@ class VoidType extends DotNet::ValueOrRefType, Type, @void_type {
* Either a simple type (`SimpleType`), an `enum` (`Enum`), a `struct` (`Struct`),
* or a nullable type (`NullableType`).
*/
class ValueType extends ValueOrRefType, @value_type { }
class ValueType extends ValueOrRefType, @value_type {
override predicate isValueType() { any() }
}
/**
* A simple type. Simple types in C# are predefined `struct` types.
@ -659,6 +667,8 @@ class RefType extends ValueOrRefType, @ref_type {
result = (this.getNumberOverridden() * this.getInheritanceDepth()) /
this.getNumberOfCallables().(float)
}
override predicate isRefType() { any() }
}
// Helper predicate to avoid slow "negation_body"

Просмотреть файл

@ -336,9 +336,7 @@ private module Internal {
or
cfn.isJoin()
or
exists(ControlFlow::Node pred | pred = cfn.getAPredecessor() |
strictcount(pred.getASuccessor()) > 1
)
cfn.getAPredecessor().isBranch()
}
/**

Просмотреть файл

@ -273,7 +273,10 @@ module ControlFlow {
}
/** Holds if this node has more than one predecessor. */
predicate isJoin() { strictcount(getAPredecessor()) > 1 }
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
/** Holds if this node has more than one successor. */
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
}
/** Provides different types of control flow nodes. */

Просмотреть файл

@ -3,6 +3,8 @@
*/
import csharp
private import cil
private import dotnet
private import ControlFlow::SuccessorTypes
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.commons.ComparisonTest
@ -11,6 +13,7 @@ private import semmle.code.csharp.controlflow.BasicBlocks
private import semmle.code.csharp.controlflow.internal.Completion
private import semmle.code.csharp.dataflow.Nullness
private import semmle.code.csharp.frameworks.System
private import semmle.code.cil.CallableReturns
/** An abstract value. */
abstract class AbstractValue extends TAbstractValue {
@ -637,6 +640,15 @@ module Internal {
TMatchValue(CaseStmt cs, boolean b) { b = true or b = false } or
TEmptyCollectionValue(boolean b) { b = true or b = false }
/** A callable that always returns a non-`null` value. */
private class NonNullCallable extends DotNet::Callable {
NonNullCallable() {
exists(CIL::Method m | m.matchesHandle(this) | alwaysNotNullMethod(m) and not m.isVirtual())
or
this = any(SystemObjectClass c).getGetTypeMethod()
}
}
/** Holds if expression `e` is a non-`null` value. */
predicate nonNullValue(Expr e) {
e instanceof ObjectCreation
@ -644,17 +656,18 @@ module Internal {
e instanceof ArrayCreation
or
e.hasValue() and
not e instanceof NullLiteral
not e instanceof NullLiteral and
not e instanceof DefaultValueExpr
or
e instanceof ThisAccess
or
e instanceof AddExpr and
e.getType() instanceof StringType
or
e = any(MethodCall mc |
mc.getTarget() = any(SystemObjectClass c).getGetTypeMethod() and
not mc.isConditional()
)
e.(DefaultValueExpr).getType().isValueType()
or
e.(Call).getTarget().getSourceDeclaration() instanceof NonNullCallable and
not e.(QualifiableExpr).isConditional()
}
/** Holds if expression `e2` is a non-`null` value whenever `e1` is. */
@ -1285,9 +1298,7 @@ module Internal {
) {
isGuardedByNode1(guarded, g, sub, v) and
sub = g.getAChildExpr*() and
forall(Ssa::Definition def | def = sub.getAnSsaQualifier(_) |
isGuardedByNode2(guarded, def)
)
forall(Ssa::Definition def | def = sub.getAnSsaQualifier(_) | isGuardedByNode2(guarded, def))
}
/**

Просмотреть файл

@ -6,6 +6,8 @@
*/
import csharp
private import cil
private import semmle.code.cil.CallableReturns
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.frameworks.System
@ -38,6 +40,13 @@ private class ThrowingCall extends NonReturningCall {
exists(AssertMethod m | m = this.(FailingAssertion).getAssertMethod() |
c.getExceptionClass() = m.getExceptionClass()
)
or
exists(CIL::Method m, CIL::Type ex |
this.getTarget().matchesHandle(m) and
alwaysThrowsException(m, ex) and
c.getExceptionClass().matchesHandle(ex) and
not m.isVirtual()
)
}
override ThrowCompletion getACompletion() { result = c }

Просмотреть файл

@ -646,7 +646,7 @@ module DataFlow {
sourceDecl.matchesHandle(result.(Callable))
or
// CIL callable without C# implementation in the database
not sourceDecl.matchesHandle(any(Callable k)) and
not sourceDecl.matchesHandle(any(Callable k | k.hasBody())) and
result = sourceDecl
else
// C# callable without C# implementation in the database
@ -1437,7 +1437,7 @@ module DataFlow {
TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getElement() instanceof Expr } or
TSsaDefinitionNode(Ssa::Definition def) or
TCilParameterNode(CIL::Parameter p) { p.getMethod().hasBody() } or
TCilExprNode(CIL::Expr e) or
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
TImplicitDelegateCallNode(DelegateArgumentToLibraryCallable arg) or
TImplicitCapturedArgumentNode(Call c, LocalScopeVariable v) {
exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowIn(_, c) |

Просмотреть файл

@ -19,6 +19,7 @@
import csharp
private import ControlFlow
private import internal.CallableReturns
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.commons.ComparisonTest
private import semmle.code.csharp.controlflow.Guards as G
@ -57,9 +58,26 @@ class AlwaysNullExpr extends Expr {
this.(AssignExpr).getRValue() instanceof AlwaysNullExpr
or
this.(Cast).getExpr() instanceof AlwaysNullExpr
or
this instanceof DefaultValueExpr and this.getType().isRefType()
or
this = any(Ssa::Definition def |
forex(Ssa::Definition u | u = def.getAnUltimateDefinition() | nullDef(u))
).getARead()
or
exists(Callable target |
this.(Call).getTarget() = target and
not target.(Virtualizable).isVirtual() and
alwaysNullCallable(target)
)
}
}
/** Holds if SSA definition `def` is always `null`. */
private predicate nullDef(Ssa::ExplicitDefinition def) {
def.getADefinition().getSource() instanceof AlwaysNullExpr
}
/** An expression that is never `null`. */
class NonNullExpr extends Expr {
NonNullExpr() {
@ -69,15 +87,24 @@ class NonNullExpr extends Expr {
or
this instanceof G::NullGuardedExpr
or
exists(Ssa::Definition def | nonNullDef(def) | this = def.getARead())
this = any(Ssa::Definition def |
forex(Ssa::Definition u | u = def.getAnUltimateDefinition() | nonNullDef(u))
).getARead()
or
exists(Callable target |
this.(Call).getTarget() = target and
not target.(Virtualizable).isVirtual() and
alwaysNotNullCallable(target) and
not this.(QualifiableExpr).isConditional()
)
}
}
/** Holds if SSA definition `def` is never `null`. */
private predicate nonNullDef(Ssa::Definition v) {
v.(Ssa::ExplicitDefinition).getADefinition().getSource() instanceof NonNullExpr
private predicate nonNullDef(Ssa::ExplicitDefinition def) {
def.getADefinition().getSource() instanceof NonNullExpr
or
exists(AssignableDefinition ad | ad = v.(Ssa::ExplicitDefinition).getADefinition() |
exists(AssignableDefinition ad | ad = def.getADefinition() |
ad instanceof AssignableDefinitions::IsPatternDefinition
or
ad instanceof AssignableDefinitions::TypeCasePatternDefinition

Просмотреть файл

@ -0,0 +1,59 @@
/**
* Provides predicates for analyzing the return values of callables.
*/
import csharp
private import cil
private import semmle.code.csharp.dataflow.Nullness
private import semmle.code.cil.CallableReturns as CR
private predicate finalCallable(Callable c) {
not c.(Virtualizable).isVirtual() and
not exists(DeclarationWithGetSetAccessors p | c = p.getAnAccessor() and p.isVirtual())
}
/** Holds if callable `c` always returns null. */
predicate alwaysNullCallable(Callable c) {
finalCallable(c) and
(
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof AlwaysNullExpr)
)
}
/** Holds if callable `c` always returns a non-null value. */
predicate alwaysNotNullCallable(Callable c) {
finalCallable(c) and
(
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNotNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof NonNullExpr)
)
}
/** Holds if callable 'c' always throws an exception. */
predicate alwaysThrowsCallable(Callable c) {
finalCallable(c) and
(
forex(ControlFlow::Node pre | pre = c.getExitPoint().getAPredecessor() |
pre.getElement() instanceof ThrowElement
)
or
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysThrowsMethod(m))
)
}
/** Holds if callable `c` always throws exception `ex`. */
predicate alwaysThrowsException(Callable c, Class ex) {
finalCallable(c) and
(
forex(ControlFlow::Node pre | pre = c.getExitPoint().getAPredecessor() |
pre.getElement().(ThrowElement).getThrownExceptionType() = ex
)
or
exists(CIL::Method m, CIL::Type t | m.matchesHandle(c) |
CR::alwaysThrowsException(m, t) and t.matchesHandle(ex)
)
)
}

Просмотреть файл

@ -0,0 +1,78 @@
stubs
alwaysNull
| System.Object Dataflow.NullMethods.ReturnsNull2() | 0: ldarg.0, 1: call Dataflow.NullMethods.ReturnsNull, 2: ret |
| System.Object Dataflow.NullMethods.ReturnsNull() | 0: ldnull, 1: ret |
| System.Object Dataflow.NullMethods.ReturnsNullIndirect() | 0: ldarg.0, 1: call Dataflow.NullMethods.ReturnsNull, 2: ret |
| System.Object Dataflow.NullMethods.VirtualReturnsNull() | 0: ldnull, 1: ret |
| System.Object Dataflow.NullMethods.get_NullProperty() | 0: ldnull, 1: ret |
| System.Object Dataflow.NullMethods.get_VirtualNullProperty() | 0: ldnull, 1: ret |
| System.Object System.Collections.EmptyReadOnlyDictionaryInternal.get_Item(System.Object) | 0: ldarg.1, 1: brtrue.s 6:, 2: ldstr "key", 3: call System.SR.get_ArgumentNull_Key, 4: newobj System.ArgumentNullException..ctor, 5: throw, 6: ldnull, 7: ret |
alwaysNonNull
| System.ArgumentException System.ThrowHelper.GetAddingDuplicateWithKeyArgumentException(System.Object) |
| System.ArgumentException System.ThrowHelper.GetArgumentException(System.ExceptionResource) |
| System.ArgumentException System.ThrowHelper.GetArgumentException(System.ExceptionResource,System.ExceptionArgument) |
| System.ArgumentException System.ThrowHelper.GetWrongKeyTypeArgumentException(System.Object,System.Type) |
| System.ArgumentException System.ThrowHelper.GetWrongValueTypeArgumentException(System.Object,System.Type) |
| System.ArgumentNullException System.ThrowHelper.GetArgumentNullException(System.ExceptionArgument) |
| System.ArgumentOutOfRangeException System.ThrowHelper.GetArgumentOutOfRangeException(System.ExceptionArgument,System.ExceptionResource) |
| System.ArgumentOutOfRangeException System.ThrowHelper.GetArgumentOutOfRangeException(System.ExceptionArgument,System.Int32,System.ExceptionResource) |
| System.Exception System.ThrowHelper.GetArraySegmentCtorValidationFailedException(System.Array,System.Int32,System.Int32) |
| System.InvalidOperationException System.ThrowHelper.GetInvalidOperationException(System.ExceptionResource) |
| System.Object Dataflow.NonNullMethods.ReturnsNonNull2() |
| System.Object Dataflow.NonNullMethods.ReturnsNonNull() |
| System.Object Dataflow.NonNullMethods.ReturnsNonNullIndirect() |
| System.Object Dataflow.NonNullMethods.get_VirtualNonNull() |
| System.Object Dataflow.NonNullMethods.get_VirtualNonNullProperty() |
| System.String Dataflow.NonNullMethods.get_NonNullProperty2() |
| System.Text.Encoder System.Text.ASCIIEncoding.GetEncoder() |
| System.Text.Encoder System.Text.Encoding.GetEncoder() |
| System.Text.Encoder System.Text.EncodingNLS.GetEncoder() |
| System.Text.Encoder System.Text.UTF7Encoding.GetEncoder() |
| System.Text.Encoder System.Text.UTF8Encoding.GetEncoder() |
| System.Text.Encoder System.Text.UTF32Encoding.GetEncoder() |
| System.Text.Encoder System.Text.UnicodeEncoding.GetEncoder() |
alwaysThrows
| System.Object Dataflow.ThrowingMethods.AlwaysThrows() | System.InvalidOperationException | 0: newobj System.InvalidOperationException..ctor, 1: throw |
| System.Object Dataflow.ThrowingMethods.VirtualThrows() | System.Exception | 0: newobj System.Exception..ctor, 1: throw |
| System.Object Dataflow.ThrowingMethods.get_ThrowProperty() | System.Exception | 0: newobj System.Exception..ctor, 1: throw |
| System.Object Dataflow.ThrowingMethods.get_VirtualThrowProperty() | System.Exception | 0: newobj System.Exception..ctor, 1: throw |
| System.Object System.ValueTuple.get_Item(System.Int32) | System.IndexOutOfRangeException | 0: newobj System.IndexOutOfRangeException..ctor, 1: throw |
| System.Void System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(System.Object) | System.ArgumentException | 0: ldarg.0, 1: call System.ThrowHelper.GetAddingDuplicateWithKeyArgumentException, 2: throw |
| System.Void System.ThrowHelper.ThrowAggregateException(System.Collections.Generic.List<System.Exception>) | System.AggregateException | 0: ldarg.0, 1: newobj System.AggregateException..ctor, 2: throw |
| System.Void System.ThrowHelper.ThrowArgumentException(System.ExceptionResource) | System.ArgumentException | 0: ldarg.0, 1: call System.ThrowHelper.GetArgumentException, 2: throw |
| System.Void System.ThrowHelper.ThrowArgumentException(System.ExceptionResource,System.ExceptionArgument) | System.ArgumentException | 0: ldarg.0, 1: ldarg.1, 2: call System.ThrowHelper.GetArgumentException, 3: throw |
| System.Void System.ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType() | System.ArgumentException | 0: ldc.i4.s 31, 1: call System.ThrowHelper.GetArgumentException, 2: throw |
| System.Void System.ThrowHelper.ThrowArgumentException_DestinationTooShort() | System.ArgumentException | 0: call System.SR.get_Argument_DestinationTooShort, 1: newobj System.ArgumentException..ctor, 2: throw |
| System.Void System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument) | System.ArgumentNullException | 0: ldarg.0, 1: call System.ThrowHelper.GetArgumentNullException, 2: throw |
| System.Void System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument,System.ExceptionResource) | System.ArgumentNullException | 0: ldarg.0, 1: call System.ThrowHelper.GetArgumentName, 2: ldarg.1, 3: call System.ThrowHelper.GetResourceString, 4: newobj System.ArgumentNullException..ctor, 5: throw |
| System.Void System.ThrowHelper.ThrowArgumentNullException(System.ExceptionResource) | System.ArgumentNullException | 0: ldarg.0, 1: call System.ThrowHelper.GetResourceString, 2: newobj System.ArgumentNullException..ctor, 3: throw |
| System.Void System.ThrowHelper.ThrowArgumentOutOfRangeException() | System.ArgumentOutOfRangeException | 0: newobj System.ArgumentOutOfRangeException..ctor, 1: throw |
| System.Void System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument) | System.ArgumentOutOfRangeException | 0: ldarg.0, 1: call System.ThrowHelper.GetArgumentName, 2: newobj System.ArgumentOutOfRangeException..ctor, 3: throw |
| System.Void System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument,System.ExceptionResource) | System.ArgumentOutOfRangeException | 0: ldarg.0, 1: ldarg.1, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw |
| System.Void System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument,System.Int32,System.ExceptionResource) | System.ArgumentOutOfRangeException | 0: ldarg.0, 1: ldarg.1, 2: ldarg.2, 3: call System.ThrowHelper.GetArgumentOutOfRangeException, 4: throw |
| System.Void System.ThrowHelper.ThrowArgumentOutOfRange_IndexException() | System.ArgumentOutOfRangeException | 0: ldc.i4.s 31, 1: ldc.i4.s 31, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw |
| System.Void System.ThrowHelper.ThrowArraySegmentCtorValidationFailedExceptions(System.Array,System.Int32,System.Int32) | System.Exception | 0: ldarg.0, 1: ldarg.1, 2: ldarg.2, 3: call System.ThrowHelper.GetArraySegmentCtorValidationFailedException, 4: throw |
| System.Void System.ThrowHelper.ThrowArrayTypeMismatchException() | System.ArrayTypeMismatchException | 0: newobj System.ArrayTypeMismatchException..ctor, 1: throw |
| System.Void System.ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count() | System.ArgumentOutOfRangeException | 0: ldc.i4.s 31, 1: ldc.i4.s 31, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw |
| System.Void System.ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException() | System.ArgumentOutOfRangeException | 0: ldc.i4.s 31, 1: ldc.i4.4, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw |
| System.Void System.ThrowHelper.ThrowIndexOutOfRangeException() | System.IndexOutOfRangeException | 0: newobj System.IndexOutOfRangeException..ctor, 1: throw |
| System.Void System.ThrowHelper.ThrowInvalidOperationException(System.ExceptionResource) | System.InvalidOperationException | 0: ldarg.0, 1: call System.ThrowHelper.GetInvalidOperationException, 2: throw |
| System.Void System.ThrowHelper.ThrowInvalidOperationException(System.ExceptionResource,System.Exception) | System.InvalidOperationException | 0: ldarg.0, 1: call System.ThrowHelper.GetResourceString, 2: ldarg.1, 3: newobj System.InvalidOperationException..ctor, 4: throw |
| System.Void System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded() | System.InvalidOperationException | 0: ldc.i4.s 31, 1: call System.ThrowHelper.GetInvalidOperationException, 2: throw |
| System.Void System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion() | System.InvalidOperationException | 0: ldc.i4.s 31, 1: call System.ThrowHelper.GetInvalidOperationException, 2: throw |
| System.Void System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted() | System.InvalidOperationException | 0: ldc.i4.s 31, 1: call System.ThrowHelper.GetInvalidOperationException, 2: throw |
| System.Void System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen() | System.InvalidOperationException | 0: ldc.i4.s 31, 1: call System.ThrowHelper.GetInvalidOperationException, 2: throw |
| System.Void System.ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(System.Type) | System.ArgumentException | 0: call System.SR.get_Argument_InvalidTypeWithPointersNotSupported, 1: ldarg.0, 2: call System.SR.Format, 3: newobj System.ArgumentException..ctor, 4: throw |
| System.Void System.ThrowHelper.ThrowKeyNotFoundException() | System.Collections.Generic.KeyNotFoundException | 0: newobj System.Collections.Generic.KeyNotFoundException..ctor, 1: throw |
| System.Void System.ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum() | System.ArgumentOutOfRangeException | 0: ldc.i4.s 31, 1: ldc.i4.4, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw |
| System.Void System.ThrowHelper.ThrowNotSupportedException() | System.NotSupportedException | 0: newobj System.NotSupportedException..ctor, 1: throw |
| System.Void System.ThrowHelper.ThrowNotSupportedException(System.ExceptionResource) | System.NotSupportedException | 0: ldarg.0, 1: call System.ThrowHelper.GetResourceString, 2: newobj System.NotSupportedException..ctor, 3: throw |
| System.Void System.ThrowHelper.ThrowObjectDisposedException(System.ExceptionResource) | System.ObjectDisposedException | 0: ldnull, 1: ldarg.0, 2: call System.ThrowHelper.GetResourceString, 3: newobj System.ObjectDisposedException..ctor, 4: throw |
| System.Void System.ThrowHelper.ThrowObjectDisposedException(System.String,System.ExceptionResource) | System.ObjectDisposedException | 0: ldarg.0, 1: ldarg.1, 2: call System.ThrowHelper.GetResourceString, 3: newobj System.ObjectDisposedException..ctor, 4: throw |
| System.Void System.ThrowHelper.ThrowRankException(System.ExceptionResource) | System.RankException | 0: ldarg.0, 1: call System.ThrowHelper.GetResourceString, 2: newobj System.RankException..ctor, 3: throw |
| System.Void System.ThrowHelper.ThrowSecurityException(System.ExceptionResource) | System.Security.SecurityException | 0: ldarg.0, 1: call System.ThrowHelper.GetResourceString, 2: newobj System.Security.SecurityException..ctor, 3: throw |
| System.Void System.ThrowHelper.ThrowSerializationException(System.ExceptionResource) | System.Runtime.Serialization.SerializationException | 0: ldarg.0, 1: call System.ThrowHelper.GetResourceString, 2: newobj System.Runtime.Serialization.SerializationException..ctor, 3: throw |
| System.Void System.ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index() | System.ArgumentOutOfRangeException | 0: ldc.i4.s 31, 1: ldc.i4.s 31, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw |
| System.Void System.ThrowHelper.ThrowUnauthorizedAccessException(System.ExceptionResource) | System.UnauthorizedAccessException | 0: ldarg.0, 1: call System.ThrowHelper.GetResourceString, 2: newobj System.UnauthorizedAccessException..ctor, 3: throw |
| System.Void System.ThrowHelper.ThrowWrongKeyTypeArgumentException(System.Object,System.Type) | System.ArgumentException | 0: ldarg.0, 1: ldarg.1, 2: call System.ThrowHelper.GetWrongKeyTypeArgumentException, 3: throw |
| System.Void System.ThrowHelper.ThrowWrongValueTypeArgumentException(System.Object,System.Type) | System.ArgumentException | 0: ldarg.0, 1: ldarg.1, 2: call System.ThrowHelper.GetWrongValueTypeArgumentException, 3: throw |

Просмотреть файл

@ -0,0 +1,38 @@
import cil
import semmle.code.cil.CallableReturns
predicate relevantMethod(CIL::Method m) {
m.getName() = "GetEncoder" and not m.getDeclaringType().getName() = "OSEncoding"
or
m.getName() = "get_Item"
or
m.getDeclaringType().getName() = "ThrowHelper"
or
m.getLocation().(CIL::Assembly).getName() = "DataFlow"
}
// Check that the assembly hasn't been marked as a stub.
query predicate stubs(string str) {
exists(CIL::Assembly asm | CIL::assemblyIsStub(asm) | str = asm.toString())
}
query predicate alwaysNull(string s, string d) {
exists(CIL::Method m |
alwaysNullMethod(m) and
s = m.toStringWithTypes() and
relevantMethod(m) and
d = m.getImplementation().getDisassembly()
)
}
query predicate alwaysNonNull(string s) {
exists(CIL::Method m | alwaysNotNullMethod(m) and s = m.toStringWithTypes() and relevantMethod(m))
}
query predicate alwaysThrows(string s, string ex, string d) {
exists(CIL::Method m, CIL::Type t | alwaysThrowsException(m, t) and relevantMethod(m) |
s = m.toStringWithTypes() and
ex = t.toStringWithTypes() and
d = m.getImplementation().getDisassembly()
)
}

Просмотреть файл

@ -0,0 +1,2 @@
| dataflow.cs:57:9:57:18 | call to method DeadCode |
| dataflow.cs:65:9:65:18 | call to method DeadCode |

Просмотреть файл

@ -0,0 +1,6 @@
import csharp
query predicate deadCode(MethodCall c) {
c.getTarget().getName() = "DeadCode" and
not exists(ControlFlow::Node node | node.getElement() = c)
}

Просмотреть файл

@ -0,0 +1,176 @@
using System;
namespace Dataflow
{
public class NullMethods
{
public object ReturnsNull() => null;
public object ReturnsNull2()
{
var x = ReturnsNull();
return x;
}
// Does not necessarily return null because of virtual method call.
public object NotReturnsNull() => VirtualReturnsNull();
public object ReturnsNullIndirect() => ReturnsNull();
public virtual object VirtualReturnsNull() => null;
public object NullProperty { get => null; }
public virtual object VirtualNullProperty { get => null; }
}
public class NonNullMethods
{
public object ReturnsNonNull() => new object();
public object ReturnsNonNull2()
{
var x = ReturnsNonNull();
return x;
}
public object ReturnsNonNullIndirect() => ReturnsNonNull();
public object NonNullProperty { get => 1; }
public string NonNullProperty2 { get => "not null"; }
public virtual object VirtualNonNull { get => "not null"; }
public bool cond = false;
public string MaybeNull()
{
if (cond)
return null;
else
return "not null";
}
public string MaybeNull2()
{
return cond ? null : "not null";
}
public virtual object VirtualNonNullProperty { get => "non null"; }
}
public class ThrowingMethods
{
public static object AlwaysThrows() => throw new InvalidOperationException();
public object AlwaysThrowsIndirect() => AlwaysThrows();
public virtual object VirtualThrows() => throw new Exception();
public object ThrowProperty { get => throw new Exception(); }
public virtual object VirtualThrowProperty { get => throw new Exception(); }
}
public class DataFlow
{
public object Taint1(object x) => x;
public object Taint2(object x) => Taint5(x);
public string Taint3(string s)
{
var x = s;
Console.WriteLine(s);
return x;
}
public object Taint5(object x) => Taint6(x);
private object Taint6(object x) => x;
}
public class TaintFlow
{
public string Taint1(string a, string b) => a + b;
public int Taint2(int a, int b) => a + b;
public int Taint3(int a) => -a;
public string TaintIndirect(string a, string b) => Taint1(a, b);
}
public class Properties
{
public int TrivialProperty1 { get; set; }
int field;
public int TrivialProperty2
{
get => field;
set { field = value; }
}
}
public class ThisAssemblyIsNotAStub
{
public void F()
{
// Ensure that the assembly isn't tagged as a stub
// Need to bump the average instruction count.
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
}
}
}

Двоичные данные
csharp/ql/test/library-tests/cil/dataflow/DataFlow.dll Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -1,7 +1,17 @@
| dataflow.cs:16:18:16:26 | "tainted" | dataflow.cs:16:18:16:37 | call to method ToString |
| dataflow.cs:17:27:17:28 | 12 | dataflow.cs:17:18:17:29 | call to method Abs |
| dataflow.cs:18:27:18:27 | 2 | dataflow.cs:18:18:18:31 | call to method Max |
| dataflow.cs:18:30:18:30 | 3 | dataflow.cs:18:18:18:31 | call to method Max |
| dataflow.cs:20:45:20:53 | "tainted" | dataflow.cs:20:18:20:54 | call to method GetFullPath |
| dataflow.cs:27:44:27:46 | 1 | dataflow.cs:27:18:27:52 | call to method IEEERemainder |
| dataflow.cs:27:49:27:51 | 2 | dataflow.cs:27:18:27:52 | call to method IEEERemainder |
| dataflow.cs:18:18:18:26 | "tainted" | dataflow.cs:18:18:18:37 | call to method ToString |
| dataflow.cs:19:27:19:28 | 12 | dataflow.cs:19:18:19:29 | call to method Abs |
| dataflow.cs:20:27:20:27 | 2 | dataflow.cs:20:18:20:31 | call to method Max |
| dataflow.cs:20:30:20:30 | 3 | dataflow.cs:20:18:20:31 | call to method Max |
| dataflow.cs:22:45:22:53 | "tainted" | dataflow.cs:22:18:22:54 | call to method GetFullPath |
| dataflow.cs:29:44:29:46 | 1 | dataflow.cs:29:18:29:52 | call to method IEEERemainder |
| dataflow.cs:29:49:29:51 | 2 | dataflow.cs:29:18:29:52 | call to method IEEERemainder |
| dataflow.cs:40:34:40:37 | "d1" | dataflow.cs:40:18:40:38 | call to method Taint1 |
| dataflow.cs:41:34:41:37 | "d2" | dataflow.cs:41:18:41:38 | call to method Taint2 |
| dataflow.cs:42:34:42:37 | "d3" | dataflow.cs:42:18:42:38 | call to method Taint3 |
| dataflow.cs:46:28:46:32 | "t1a" | dataflow.cs:46:18:46:40 | call to method Taint1 |
| dataflow.cs:46:35:46:39 | "t1b" | dataflow.cs:46:18:46:40 | call to method Taint1 |
| dataflow.cs:49:35:49:38 | "t6" | dataflow.cs:49:18:49:45 | call to method TaintIndirect |
| dataflow.cs:49:41:49:44 | "t6" | dataflow.cs:49:18:49:45 | call to method TaintIndirect |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:89:24:89:51 | ... ? ... : ... |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:101:20:101:33 | call to method IndirectNull |
| dataflow.cs:102:23:102:26 | null | dataflow.cs:89:24:89:51 | ... ? ... : ... |

Просмотреть файл

@ -0,0 +1,32 @@
alwaysNull
| dataflow.cs:70:21:70:35 | default(...) |
| dataflow.cs:74:21:74:34 | call to method NullFunction |
| dataflow.cs:74:39:74:52 | call to method IndirectNull |
| dataflow.cs:78:21:78:45 | call to method ReturnsNull |
| dataflow.cs:79:21:79:46 | call to method ReturnsNull2 |
| dataflow.cs:80:21:80:44 | access to property NullProperty |
| dataflow.cs:89:31:89:44 | call to method NullFunction |
alwaysNotNull
| dataflow.cs:71:24:71:35 | default(...) |
| dataflow.cs:72:27:72:30 | this access |
| dataflow.cs:72:27:72:40 | call to method GetType |
| dataflow.cs:73:30:73:33 | true |
| dataflow.cs:73:30:73:44 | call to method ToString |
| dataflow.cs:74:21:74:34 | this access |
| dataflow.cs:74:39:74:52 | this access |
| dataflow.cs:77:27:77:52 | object creation of type NullMethods |
| dataflow.cs:78:21:78:31 | access to local variable nullMethods |
| dataflow.cs:79:21:79:31 | access to local variable nullMethods |
| dataflow.cs:80:21:80:31 | access to local variable nullMethods |
| dataflow.cs:83:23:83:51 | object creation of type NonNullMethods |
| dataflow.cs:84:24:84:30 | access to local variable nonNull |
| dataflow.cs:84:24:84:47 | call to method ReturnsNonNull |
| dataflow.cs:85:24:85:30 | access to local variable nonNull |
| dataflow.cs:85:24:85:55 | call to method ReturnsNonNullIndirect |
| dataflow.cs:86:24:86:30 | access to local variable nonNull |
| dataflow.cs:89:24:89:27 | this access |
| dataflow.cs:89:31:89:44 | this access |
| dataflow.cs:89:48:89:51 | this access |
| dataflow.cs:90:24:90:34 | access to local variable nullMethods |
| dataflow.cs:91:24:91:34 | access to local variable nullMethods |
| dataflow.cs:92:26:92:32 | access to local variable nonNull |

Просмотреть файл

@ -0,0 +1,10 @@
import csharp
import semmle.code.csharp.dataflow.Nullness
query predicate alwaysNull(AlwaysNullExpr expr) {
expr.getEnclosingCallable().getName() = "Nullness"
}
query predicate alwaysNotNull(NonNullExpr expr) {
expr.getEnclosingCallable().getName() = "Nullness"
}

Просмотреть файл

@ -1,13 +1,28 @@
| dataflow.cs:12:18:12:22 | "123" | dataflow.cs:12:18:12:37 | call to method CompareTo |
| dataflow.cs:12:34:12:36 | "b" | dataflow.cs:12:18:12:37 | call to method CompareTo |
| dataflow.cs:16:18:16:26 | "tainted" | dataflow.cs:16:18:16:37 | call to method ToString |
| dataflow.cs:17:27:17:28 | 12 | dataflow.cs:17:18:17:29 | call to method Abs |
| dataflow.cs:18:27:18:27 | 2 | dataflow.cs:18:18:18:31 | call to method Max |
| dataflow.cs:18:30:18:30 | 3 | dataflow.cs:18:18:18:31 | call to method Max |
| dataflow.cs:20:45:20:53 | "tainted" | dataflow.cs:20:18:20:54 | call to method GetFullPath |
| dataflow.cs:24:37:24:37 | 1 | dataflow.cs:24:18:24:56 | call to method DivRem |
| dataflow.cs:24:40:24:40 | 2 | dataflow.cs:24:18:24:56 | call to method DivRem |
| dataflow.cs:27:44:27:46 | 1 | dataflow.cs:27:18:27:52 | call to method IEEERemainder |
| dataflow.cs:27:49:27:51 | 2 | dataflow.cs:27:18:27:52 | call to method IEEERemainder |
| dataflow.cs:30:60:30:60 | 1 | dataflow.cs:30:18:30:80 | call to method DivRem |
| dataflow.cs:30:63:30:63 | 2 | dataflow.cs:30:18:30:80 | call to method DivRem |
| dataflow.cs:11:18:11:22 | "123" | dataflow.cs:11:18:11:37 | call to method CompareTo |
| dataflow.cs:11:34:11:36 | "b" | dataflow.cs:11:18:11:37 | call to method CompareTo |
| dataflow.cs:18:18:18:26 | "tainted" | dataflow.cs:18:18:18:37 | call to method ToString |
| dataflow.cs:19:27:19:28 | 12 | dataflow.cs:19:18:19:29 | call to method Abs |
| dataflow.cs:20:27:20:27 | 2 | dataflow.cs:20:18:20:31 | call to method Max |
| dataflow.cs:20:30:20:30 | 3 | dataflow.cs:20:18:20:31 | call to method Max |
| dataflow.cs:22:45:22:53 | "tainted" | dataflow.cs:22:18:22:54 | call to method GetFullPath |
| dataflow.cs:26:37:26:37 | 1 | dataflow.cs:26:18:26:56 | call to method DivRem |
| dataflow.cs:26:40:26:40 | 2 | dataflow.cs:26:18:26:56 | call to method DivRem |
| dataflow.cs:29:44:29:46 | 1 | dataflow.cs:29:18:29:52 | call to method IEEERemainder |
| dataflow.cs:29:49:29:51 | 2 | dataflow.cs:29:18:29:52 | call to method IEEERemainder |
| dataflow.cs:32:60:32:60 | 1 | dataflow.cs:32:18:32:80 | call to method DivRem |
| dataflow.cs:32:63:32:63 | 2 | dataflow.cs:32:18:32:80 | call to method DivRem |
| dataflow.cs:40:34:40:37 | "d1" | dataflow.cs:40:18:40:38 | call to method Taint1 |
| dataflow.cs:41:34:41:37 | "d2" | dataflow.cs:41:18:41:38 | call to method Taint2 |
| dataflow.cs:42:34:42:37 | "d3" | dataflow.cs:42:18:42:38 | call to method Taint3 |
| dataflow.cs:46:28:46:32 | "t1a" | dataflow.cs:46:18:46:40 | call to method Taint1 |
| dataflow.cs:46:35:46:39 | "t1b" | dataflow.cs:46:18:46:40 | call to method Taint1 |
| dataflow.cs:47:28:47:28 | 2 | dataflow.cs:47:18:47:32 | call to method Taint2 |
| dataflow.cs:47:31:47:31 | 3 | dataflow.cs:47:18:47:32 | call to method Taint2 |
| dataflow.cs:48:28:48:28 | 1 | dataflow.cs:48:18:48:29 | call to method Taint3 |
| dataflow.cs:49:35:49:38 | "t6" | dataflow.cs:49:18:49:45 | call to method TaintIndirect |
| dataflow.cs:49:41:49:44 | "t6" | dataflow.cs:49:18:49:45 | call to method TaintIndirect |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:74:21:74:52 | ... ?? ... |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:89:24:89:51 | ... ? ... : ... |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:101:20:101:33 | call to method IndirectNull |
| dataflow.cs:102:23:102:26 | null | dataflow.cs:74:21:74:52 | ... ?? ... |
| dataflow.cs:102:23:102:26 | null | dataflow.cs:89:24:89:51 | ... ? ... : ... |

Просмотреть файл

@ -1,3 +1,5 @@
| Dataflow.Properties.TrivialProperty1 |
| Dataflow.Properties.TrivialProperty2 |
| System.Collections.DictionaryEntry.Key |
| System.Collections.DictionaryEntry.Value |
| System.Reflection.AssemblyName.CodeBase |

Просмотреть файл

@ -5,4 +5,6 @@ where
prop.getDeclaringType().hasQualifiedName("System.Reflection.AssemblyName")
or
prop.getDeclaringType().hasQualifiedName("System.Collections.DictionaryEntry")
or
prop.getDeclaringType().hasQualifiedName("Dataflow.Properties")
select prop.getQualifiedName()

Просмотреть файл

@ -6,12 +6,14 @@ class Test
{
static void Main(string[] args)
{
// Indirect call to method
var c1 = "abc".Contains("a"); // Calls string.IndexOf()
var c2 = "123".CompareTo("b"); // Calls string.Compare()
var c3 = Tuple.Create("c", "d", "e"); // Calls Tuple constructor
}
void DataFlowThroughFramework()
{
// Dataflow through call
var f1 = "tainted".ToString();
var f2 = Math.Abs(12);
@ -30,4 +32,74 @@ class Test
var m1 = System.Math.DivRem(Math.Abs(-1), Math.Max(1, 2), out remainder);
var m2 = "tainted".ToString().Contains("t");
}
void DataFlowThroughAssembly()
{
// Dataflow through test assembly
var dataflow = new Dataflow.DataFlow();
var d1 = dataflow.Taint1("d1");
var d2 = dataflow.Taint2("d2");
var d3 = dataflow.Taint3("d3");
// Taint tracking
var tt = new Dataflow.TaintFlow();
var t1 = tt.Taint1("t1a", "t1b");
var t2 = tt.Taint2(2, 3);
var t3 = tt.Taint3(1);
var t4 = tt.TaintIndirect("t6", "t6");
}
void DeadCode() { }
void CilAlwaysThrows()
{
System.Reflection.Assembly.LoadFrom("", null, System.Configuration.Assemblies.AssemblyHashAlgorithm.SHA1); // Throws NotSupportedException
DeadCode();
}
void Throw() => throw new InvalidCastException();
void CsAlwaysThrows()
{
Throw();
DeadCode();
}
void Nullness()
{
var @null = default(object);
var nonNull1 = default(int);
var nullFromCil = this.GetType().DeclaringMethod;
var nonNullFromCil = true.ToString();
var null2 = NullFunction() ?? IndirectNull();
// Null from dataflow assembly
var nullMethods = new Dataflow.NullMethods();
var null3 = nullMethods.ReturnsNull(); // Null
var null4 = nullMethods.ReturnsNull2();
var null5 = nullMethods.NullProperty;
// NotNull
var nonNull = new Dataflow.NonNullMethods();
var nonNull2 = nonNull.ReturnsNonNull();
var nonNull3 = nonNull.ReturnsNonNullIndirect();
var nonNull4 = nonNull.NonNullProperty;
// The following are not always null:
var notNull1 = cond ? NullFunction() : this;
var notNull2 = nullMethods.VirtualReturnsNull();
var notNull3 = nullMethods.VirtualNullProperty;
var notNonNull = nonNull.VirtualNonNull;
}
object IndirectNull() => null;
bool cond;
object NullFunction()
{
object x = IndirectNull();
if (cond) x = null;
return x;
}
}

Просмотреть файл

@ -31,11 +31,11 @@
| C:/dev/projects/Sandbox/PortablePdb/Class1.cs:10:4:10:19 | 24: br.s 25: |
| C:/dev/projects/Sandbox/PortablePdb/Class1.cs:11:3:11:4 | 25: ldloc.3 |
| C:/dev/projects/Sandbox/PortablePdb/Class1.cs:11:3:11:4 | 26: ret |
| EmbeddedPdb, Version=1.0.0.0, Culture=neutral | 0: ldarg.0 |
| EmbeddedPdb, Version=1.0.0.0, Culture=neutral | 1: call System.Object..ctor |
| EmbeddedPdb, Version=1.0.0.0, Culture=neutral | 2: nop |
| EmbeddedPdb, Version=1.0.0.0, Culture=neutral | 3: ret |
| PortablePdb, Version=1.0.0.0, Culture=neutral | 0: ldarg.0 |
| PortablePdb, Version=1.0.0.0, Culture=neutral | 1: call System.Object..ctor |
| PortablePdb, Version=1.0.0.0, Culture=neutral | 2: nop |
| PortablePdb, Version=1.0.0.0, Culture=neutral | 3: ret |
| EmbeddedPdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | 0: ldarg.0 |
| EmbeddedPdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | 1: call System.Object..ctor |
| EmbeddedPdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | 2: nop |
| EmbeddedPdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | 3: ret |
| PortablePdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | 0: ldarg.0 |
| PortablePdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | 1: call System.Object..ctor |
| PortablePdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | 2: nop |
| PortablePdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | 3: ret |

Просмотреть файл

@ -1,4 +1,4 @@
| System.Int32 EmbeddedPdb.Class1.Method() | C:/dev/projects/Sandbox/EmbeddedPdb/Class1.cs:6:3:6:4 | true |
| System.Int32 EmbeddedPdb.Class1.Method() | EmbeddedPdb, Version=1.0.0.0, Culture=neutral | false |
| System.Int32 EmbeddedPdb.Class1.Method() | EmbeddedPdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | false |
| System.Int32 PortablePdb.Class1.Factorial(System.Int32) | C:/dev/projects/Sandbox/PortablePdb/Class1.cs:6:3:6:4 | true |
| System.Int32 PortablePdb.Class1.Factorial(System.Int32) | PortablePdb, Version=1.0.0.0, Culture=neutral | false |
| System.Int32 PortablePdb.Class1.Factorial(System.Int32) | PortablePdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | false |

Просмотреть файл

@ -0,0 +1,2 @@
| EmbeddedPdb.dll:0:0:0:0 | EmbeddedPdb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null |
| PdbOnly.dll:0:0:0:0 | PdbOnly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null |

Просмотреть файл

@ -0,0 +1,5 @@
import cil::CIL
from Assembly asm
where assemblyIsStub(asm)
select asm

Просмотреть файл

@ -0,0 +1 @@
// semmle-extractor-options: --cil

Просмотреть файл

@ -952,6 +952,8 @@
| D.cs:212:18:212:18 | access to local variable n | null | D.cs:211:20:211:23 | null | null |
| D.cs:212:18:212:26 | ... == ... | false | D.cs:212:18:212:18 | access to local variable n | non-null |
| D.cs:212:18:212:26 | ... == ... | true | D.cs:212:18:212:18 | access to local variable n | null |
| D.cs:212:18:212:45 | ... ? ... : ... | non-null | D.cs:212:18:212:26 | ... == ... | true |
| D.cs:212:18:212:45 | ... ? ... : ... | non-null | D.cs:212:30:212:41 | object creation of type Object | non-null |
| D.cs:212:18:212:45 | ... ? ... : ... | null | D.cs:212:18:212:26 | ... == ... | false |
| D.cs:212:18:212:45 | ... ? ... : ... | null | D.cs:212:45:212:45 | access to local variable n | null |
| D.cs:212:45:212:45 | access to local variable n | non-null | D.cs:211:20:211:23 | null | non-null |

Просмотреть файл

@ -496,7 +496,11 @@ module DataFlow {
override string getPropertyName() { result = odp.getPropertyName() }
override Node getRhs() {
odp.getAPropertyAttribute().writes(_, "value", result)
// not using `CallToObjectDefineProperty::getAPropertyAttribute` for performance reasons
exists(ObjectLiteralNode propdesc |
propdesc.flowsTo(odp.getPropertyDescriptor()) and
propdesc.hasPropertyWrite("value", result)
)
}
override ControlFlowNode getWriteNode() { result = odp.getAstNode() }

Просмотреть файл

@ -50,6 +50,8 @@ ClassObject simple_types(Object obj) {
obj.getOrigin() instanceof Module and result = theModuleType()
or
result = builtin_object_type(obj)
or
obj = unknownValue() and result = theUnknownType()
}
private ClassObject comprehension(Expr e) {

Просмотреть файл

@ -1237,7 +1237,7 @@ library module TaintFlowImplementation {
)
|
not Filters::isinstance(test.getTest(), _, var.getSourceVariable().getAUse()) and
not test.getTest() = var.getSourceVariable().getAUse()
not boolean_filter(test.getTest(), var.getSourceVariable().getAUse())
or
exists(ControlFlowNode c, ClassObject cls |
Filters::isinstance(test.getTest(), c, var.getSourceVariable().getAUse())
@ -1248,10 +1248,42 @@ library module TaintFlowImplementation {
test.getSense() = false and not kind.getClass().getAnImproperSuperType() = cls
)
or
test.getTest() = var.getSourceVariable().getAUse() and kind.booleanValue() = test.getSense()
test.getSense() = test_evaluates(test.getTest(), var.getSourceVariable().getAUse(), kind)
)
}
/** Gets the operand of a unary `not` expression. */
private ControlFlowNode not_operand(ControlFlowNode expr) {
expr.(UnaryExprNode).getNode().getOp() instanceof Not and
result = expr.(UnaryExprNode).getOperand()
}
/** Holds if `test` is the test in a branch and `use` is that test
* with all the `not` prefixes removed.
*/
private predicate boolean_filter(ControlFlowNode test, ControlFlowNode use) {
any(PyEdgeRefinement ref).getTest() = test and
(
use = test
or
exists(ControlFlowNode notuse |
boolean_filter(test, notuse) and
use = not_operand(notuse)
)
)
}
/** Gets the boolean value that `test` evaluates to when `use` is tainted with `kind`
* and `test` and `use` are part of a test in a branch.
*/
private boolean test_evaluates(ControlFlowNode test, ControlFlowNode use, TaintKind kind) {
boolean_filter(_, use) and
kind.taints(use) and
test = use and result = kind.booleanValue()
or
result = test_evaluates(not_operand(test), use, kind).booleanNot()
}
pragma [noinline]
predicate tainted_argument(ArgumentRefinement def, CallContext context, TaintedNode origin) {
tainted_var(def.getInput(), context, origin)

Просмотреть файл

@ -3,6 +3,10 @@
*
* This should be considered an advance feature. Modifying the points-to analysis
* can cause queries to give strange and misleading results, if not done with care.
*
* WARNING:
* This module interacts with the internals of points-to analysis and
* the classes here are more likely to change than the rest of the library.
*/
import python
@ -34,6 +38,18 @@ abstract class CustomPointsToOriginFact extends CustomPointsToFact {
}
/* Custom points-to fact with inferred class */
abstract class CustomPointsToObjectFact extends CustomPointsToFact {
abstract predicate pointsTo(Object value);
override predicate pointsTo(Context context, Object value, ClassObject cls, ControlFlowNode origin) {
this.pointsTo(value) and cls = simple_types(value) and origin = this and context.appliesTo(this)
}
}
/** INTERNAL -- Do not use */
abstract class CustomPointsToAttribute extends Object {

Просмотреть файл

@ -1,10 +1,12 @@
| test.py:4:1:4:3 | ControlFlowNode for one | int 1 |
| test.py:5:1:5:3 | ControlFlowNode for two | int 2 |
| test.py:8:1:8:1 | ControlFlowNode for IntegerLiteral | int 1 |
| test.py:8:1:8:7 | ControlFlowNode for Tuple | Tuple |
| test.py:8:1:8:11 | ControlFlowNode for Tuple | Tuple |
| test.py:8:3:8:3 | ControlFlowNode for IntegerLiteral | int 2 |
| test.py:8:5:8:5 | ControlFlowNode for IntegerLiteral | int 3 |
| test.py:8:7:8:7 | ControlFlowNode for IntegerLiteral | int 4 |
| test.py:8:9:8:9 | ControlFlowNode for IntegerLiteral | int 5 |
| test.py:8:11:8:11 | ControlFlowNode for IntegerLiteral | int 6 |
| test.py:10:1:10:2 | ControlFlowNode for a3 | int 3 |
| test.py:10:6:10:7 | ControlFlowNode for Tuple | Tuple |
| test.py:10:6:10:13 | ControlFlowNode for Attribute | int 3 |
@ -13,3 +15,5 @@
| test.py:11:6:11:15 | ControlFlowNode for Attribute | int 4 |
| test.py:13:1:13:2 | ControlFlowNode for a3 | int 3 |
| test.py:14:1:14:2 | ControlFlowNode for a4 | int 4 |
| test.py:16:1:16:4 | ControlFlowNode for five | int 5 |
| test.py:17:1:17:3 | ControlFlowNode for six | int 6 |

Просмотреть файл

@ -38,6 +38,19 @@ class AttributeExtension extends CustomPointsToAttribute {
}
class NoClassExtension extends CustomPointsToObjectFact {
NoClassExtension() { this = this }
override predicate pointsTo(Object value) {
this.(NameNode).getId() = "five" and value.(NumericObject).intValue() = 5
or
this.(NameNode).getId() = "six" and value.(NumericObject).intValue() = 6
}
}
from ControlFlowNode f, Object o
where f.getLocation().getFile().getBaseName() = "test.py" and f.refersTo(o)
select f, o.toString()

Просмотреть файл

@ -5,10 +5,13 @@ one
two
#Make sure values exist in DB
1,2,3,4
1,2,3,4,5,6
a3 = ().three
a4 = False.four
a3
a4
five
six

Просмотреть файл

@ -334,3 +334,35 @@ class OsCommand extends TaintSink {
}
}
class Falsey extends TaintKind {
Falsey() { this = "falsey" }
override boolean booleanValue() {
result = false
}
}
class FalseySource extends TaintSource {
FalseySource() {
this.(NameNode).getId() = "FALSEY"
}
override predicate isSourceOf(TaintKind kind) {
kind instanceof Falsey
}
override string toString() {
result = "falsey.source"
}
}

Просмотреть файл

@ -0,0 +1,184 @@
| carrier.py:4 | ParameterDefinition | carrier.py:4 | Taint explicit.carrier | arg |
| carrier.py:4 | ParameterDefinition | carrier.py:4 | Taint simple.test | arg |
| carrier.py:5 | AttributeAssignment 'attr'(self_0) | carrier.py:5 | Attribute 'attr' taint explicit.carrier | self |
| carrier.py:5 | AttributeAssignment 'attr'(self_0) | carrier.py:5 | Attribute 'attr' taint simple.test | self |
| carrier.py:13 | ParameterDefinition | carrier.py:13 | Attribute 'attr' taint simple.test | arg |
| carrier.py:13 | ParameterDefinition | carrier.py:13 | Taint explicit.carrier | arg |
| carrier.py:17 | ImplicitCarrier() | carrier.py:17 | Attribute 'attr' taint simple.test | ImplicitCarrier() |
| carrier.py:21 | TAINT_CARRIER_SOURCE | carrier.py:21 | Taint explicit.carrier | TAINT_CARRIER_SOURCE |
| carrier.py:22 | MethodCallsiteRefinement(c_0) | carrier.py:21 | Taint explicit.carrier | TAINT_CARRIER_SOURCE |
| carrier.py:25 | hub() | carrier.py:25 | Attribute 'attr' taint simple.test | hub() |
| carrier.py:29 | hub() | carrier.py:29 | Taint explicit.carrier | hub() |
| carrier.py:30 | MethodCallsiteRefinement(c_0) | carrier.py:29 | Taint explicit.carrier | hub() |
| carrier.py:33 | ImplicitCarrier() | carrier.py:33 | Attribute 'attr' taint explicit.carrier | ImplicitCarrier() |
| carrier.py:34 | Attribute | carrier.py:34 | Taint explicit.carrier | Attribute |
| carrier.py:35 | MethodCallsiteRefinement(x_0) | carrier.py:34 | Taint explicit.carrier | Attribute |
| deep.py:2 | ParameterDefinition | deep.py:2 | Taint simple.test | arg |
| deep.py:5 | ParameterDefinition | deep.py:5 | Taint simple.test | arg |
| deep.py:6 | ArgumentRefinement(arg_0) | deep.py:5 | Taint simple.test | arg |
| deep.py:8 | ParameterDefinition | deep.py:8 | Taint simple.test | arg |
| deep.py:9 | ArgumentRefinement(arg_0) | deep.py:8 | Taint simple.test | arg |
| deep.py:11 | ParameterDefinition | deep.py:11 | Taint simple.test | arg |
| deep.py:12 | ArgumentRefinement(arg_0) | deep.py:11 | Taint simple.test | arg |
| deep.py:14 | ParameterDefinition | deep.py:14 | Taint simple.test | arg |
| deep.py:15 | ArgumentRefinement(arg_0) | deep.py:14 | Taint simple.test | arg |
| deep.py:17 | ParameterDefinition | deep.py:17 | Taint simple.test | arg |
| deep.py:18 | ArgumentRefinement(arg_0) | deep.py:17 | Taint simple.test | arg |
| deep.py:20 | f6() | deep.py:20 | Taint simple.test | f6() |
| module.py:3 | SOURCE | module.py:3 | Taint simple.test | SOURCE |
| rockpaperscissors.py:3 | ParameterDefinition | rockpaperscissors.py:3 | Taint scissors | arg |
| rockpaperscissors.py:6 | ParameterDefinition | rockpaperscissors.py:6 | Taint paper | arg |
| rockpaperscissors.py:6 | ParameterDefinition | rockpaperscissors.py:6 | Taint rock | arg |
| rockpaperscissors.py:6 | ParameterDefinition | rockpaperscissors.py:6 | Taint scissors | arg |
| rockpaperscissors.py:9 | ParameterDefinition | rockpaperscissors.py:9 | Taint paper | arg |
| rockpaperscissors.py:9 | ParameterDefinition | rockpaperscissors.py:9 | Taint scissors | arg |
| rockpaperscissors.py:19 | ROCK | rockpaperscissors.py:19 | Taint rock | ROCK |
| rockpaperscissors.py:20 | Attribute() | rockpaperscissors.py:20 | Taint scissors | Attribute() |
| rockpaperscissors.py:20 | MethodCallsiteRefinement(x_0) | rockpaperscissors.py:19 | Taint rock | ROCK |
| rockpaperscissors.py:21 | ArgumentRefinement(y_0) | rockpaperscissors.py:20 | Taint scissors | Attribute() |
| rockpaperscissors.py:24 | ROCK | rockpaperscissors.py:24 | Taint rock | ROCK |
| rockpaperscissors.py:25 | Attribute() | rockpaperscissors.py:25 | Taint paper | Attribute() |
| rockpaperscissors.py:25 | MethodCallsiteRefinement(x_0) | rockpaperscissors.py:24 | Taint rock | ROCK |
| rockpaperscissors.py:26 | ArgumentRefinement(y_0) | rockpaperscissors.py:25 | Taint paper | Attribute() |
| rockpaperscissors.py:29 | SCISSORS | rockpaperscissors.py:29 | Taint scissors | SCISSORS |
| rockpaperscissors.py:30 | Attribute() | rockpaperscissors.py:30 | Taint paper | Attribute() |
| rockpaperscissors.py:30 | MethodCallsiteRefinement(x_0) | rockpaperscissors.py:29 | Taint scissors | SCISSORS |
| rockpaperscissors.py:31 | ArgumentRefinement(x_1) | rockpaperscissors.py:29 | Taint scissors | SCISSORS |
| rockpaperscissors.py:32 | ArgumentRefinement(y_0) | rockpaperscissors.py:30 | Taint paper | Attribute() |
| sanitizer.py:3 | ParameterDefinition | sanitizer.py:3 | Taint Command injection | arg |
| sanitizer.py:3 | ParameterDefinition | sanitizer.py:3 | Taint SQL injection | arg |
| sanitizer.py:5 | ParameterDefinition | sanitizer.py:5 | Taint Command injection | arg |
| sanitizer.py:5 | ParameterDefinition | sanitizer.py:5 | Taint SQL injection | arg |
| sanitizer.py:8 | phi(x_3, x_5) | sanitizer.py:9 | Taint Command injection | user_input() |
| sanitizer.py:8 | phi(x_3, x_5) | sanitizer.py:9 | Taint SQL injection | user_input() |
| sanitizer.py:9 | user_input() | sanitizer.py:9 | Taint Command injection | user_input() |
| sanitizer.py:9 | user_input() | sanitizer.py:9 | Taint SQL injection | user_input() |
| sanitizer.py:10 | ArgumentRefinement(x_0) | sanitizer.py:9 | Taint Command injection | user_input() |
| sanitizer.py:10 | ArgumentRefinement(x_0) | sanitizer.py:9 | Taint SQL injection | user_input() |
| sanitizer.py:11 | ArgumentRefinement(x_2) | sanitizer.py:9 | Taint Command injection | user_input() |
| sanitizer.py:11 | Pi(x_1) [true] | sanitizer.py:9 | Taint Command injection | user_input() |
| sanitizer.py:13 | ArgumentRefinement(x_4) | sanitizer.py:9 | Taint Command injection | user_input() |
| sanitizer.py:13 | ArgumentRefinement(x_4) | sanitizer.py:9 | Taint SQL injection | user_input() |
| sanitizer.py:13 | Pi(x_1) [false] | sanitizer.py:9 | Taint Command injection | user_input() |
| sanitizer.py:13 | Pi(x_1) [false] | sanitizer.py:9 | Taint SQL injection | user_input() |
| sanitizer.py:15 | phi(x_3, x_5) | sanitizer.py:16 | Taint Command injection | user_input() |
| sanitizer.py:15 | phi(x_3, x_5) | sanitizer.py:16 | Taint SQL injection | user_input() |
| sanitizer.py:16 | user_input() | sanitizer.py:16 | Taint Command injection | user_input() |
| sanitizer.py:16 | user_input() | sanitizer.py:16 | Taint SQL injection | user_input() |
| sanitizer.py:17 | ArgumentRefinement(x_0) | sanitizer.py:16 | Taint Command injection | user_input() |
| sanitizer.py:17 | ArgumentRefinement(x_0) | sanitizer.py:16 | Taint SQL injection | user_input() |
| sanitizer.py:18 | ArgumentRefinement(x_2) | sanitizer.py:16 | Taint SQL injection | user_input() |
| sanitizer.py:18 | Pi(x_1) [true] | sanitizer.py:16 | Taint SQL injection | user_input() |
| sanitizer.py:20 | ArgumentRefinement(x_4) | sanitizer.py:16 | Taint Command injection | user_input() |
| sanitizer.py:20 | ArgumentRefinement(x_4) | sanitizer.py:16 | Taint SQL injection | user_input() |
| sanitizer.py:20 | Pi(x_1) [false] | sanitizer.py:16 | Taint Command injection | user_input() |
| sanitizer.py:20 | Pi(x_1) [false] | sanitizer.py:16 | Taint SQL injection | user_input() |
| sanitizer.py:23 | phi(x_3, x_5) | sanitizer.py:24 | Taint Command injection | user_input() |
| sanitizer.py:23 | phi(x_3, x_5) | sanitizer.py:24 | Taint SQL injection | user_input() |
| sanitizer.py:24 | user_input() | sanitizer.py:24 | Taint Command injection | user_input() |
| sanitizer.py:24 | user_input() | sanitizer.py:24 | Taint SQL injection | user_input() |
| sanitizer.py:25 | ArgumentRefinement(x_0) | sanitizer.py:24 | Taint Command injection | user_input() |
| sanitizer.py:25 | ArgumentRefinement(x_0) | sanitizer.py:24 | Taint SQL injection | user_input() |
| sanitizer.py:26 | ArgumentRefinement(x_2) | sanitizer.py:24 | Taint Command injection | user_input() |
| sanitizer.py:26 | ArgumentRefinement(x_2) | sanitizer.py:24 | Taint SQL injection | user_input() |
| sanitizer.py:26 | Pi(x_1) [true] | sanitizer.py:24 | Taint Command injection | user_input() |
| sanitizer.py:26 | Pi(x_1) [true] | sanitizer.py:24 | Taint SQL injection | user_input() |
| sanitizer.py:28 | ArgumentRefinement(x_4) | sanitizer.py:24 | Taint Command injection | user_input() |
| sanitizer.py:28 | ArgumentRefinement(x_4) | sanitizer.py:24 | Taint SQL injection | user_input() |
| sanitizer.py:28 | Pi(x_1) [false] | sanitizer.py:24 | Taint Command injection | user_input() |
| sanitizer.py:28 | Pi(x_1) [false] | sanitizer.py:24 | Taint SQL injection | user_input() |
| sanitizer.py:30 | phi(x_3, x_5) | sanitizer.py:31 | Taint Command injection | user_input() |
| sanitizer.py:30 | phi(x_3, x_5) | sanitizer.py:31 | Taint SQL injection | user_input() |
| sanitizer.py:31 | user_input() | sanitizer.py:31 | Taint Command injection | user_input() |
| sanitizer.py:31 | user_input() | sanitizer.py:31 | Taint SQL injection | user_input() |
| sanitizer.py:32 | ArgumentRefinement(x_0) | sanitizer.py:31 | Taint Command injection | user_input() |
| sanitizer.py:32 | ArgumentRefinement(x_0) | sanitizer.py:31 | Taint SQL injection | user_input() |
| sanitizer.py:33 | ArgumentRefinement(x_2) | sanitizer.py:31 | Taint Command injection | user_input() |
| sanitizer.py:33 | ArgumentRefinement(x_2) | sanitizer.py:31 | Taint SQL injection | user_input() |
| sanitizer.py:33 | Pi(x_1) [true] | sanitizer.py:31 | Taint Command injection | user_input() |
| sanitizer.py:33 | Pi(x_1) [true] | sanitizer.py:31 | Taint SQL injection | user_input() |
| sanitizer.py:35 | ArgumentRefinement(x_4) | sanitizer.py:31 | Taint Command injection | user_input() |
| sanitizer.py:35 | ArgumentRefinement(x_4) | sanitizer.py:31 | Taint SQL injection | user_input() |
| sanitizer.py:35 | Pi(x_1) [false] | sanitizer.py:31 | Taint Command injection | user_input() |
| sanitizer.py:35 | Pi(x_1) [false] | sanitizer.py:31 | Taint SQL injection | user_input() |
| test.py:6 | SOURCE | test.py:6 | Taint simple.test | SOURCE |
| test.py:7 | ArgumentRefinement(s_0) | test.py:6 | Taint simple.test | SOURCE |
| test.py:12 | ParameterDefinition | test.py:12 | Taint simple.test | arg |
| test.py:13 | ArgumentRefinement(arg_0) | test.py:12 | Taint simple.test | arg |
| test.py:16 | source() | test.py:16 | Taint simple.test | source() |
| test.py:17 | ArgumentRefinement(t_0) | test.py:16 | Taint simple.test | source() |
| test.py:20 | SOURCE | test.py:20 | Taint simple.test | SOURCE |
| test.py:21 | ArgumentRefinement(t_0) | test.py:20 | Taint simple.test | SOURCE |
| test.py:24 | source() | test.py:24 | Taint simple.test | source() |
| test.py:25 | ArgumentRefinement(t_0) | test.py:24 | Taint simple.test | source() |
| test.py:31 | SOURCE | test.py:31 | Taint simple.test | SOURCE |
| test.py:37 | SOURCE | test.py:37 | Taint simple.test | SOURCE |
| test.py:41 | ArgumentRefinement(t_0) | test.py:37 | Taint simple.test | SOURCE |
| test.py:46 | ParameterDefinition | test.py:46 | Taint simple.test | arg |
| test.py:47 | ArgumentRefinement(arg_0) | test.py:46 | Taint simple.test | arg |
| test.py:49 | ParameterDefinition | test.py:49 | Taint simple.test | arg |
| test.py:49 | phi(arg_0, arg_1) | test.py:49 | Taint simple.test | arg |
| test.py:51 | ArgumentRefinement(arg_0) | test.py:49 | Taint simple.test | arg |
| test.py:54 | source2() | test.py:54 | Taint simple.test | source2() |
| test.py:55 | ArgumentRefinement(t_0) | test.py:54 | Taint simple.test | source2() |
| test.py:62 | SOURCE | test.py:62 | Taint simple.test | SOURCE |
| test.py:63 | phi(t_0, t_1) | test.py:62 | Taint simple.test | SOURCE |
| test.py:67 | SOURCE | test.py:67 | Taint simple.test | SOURCE |
| test.py:70 | phi(t_0, t_1) | test.py:67 | Taint simple.test | SOURCE |
| test.py:72 | ParameterDefinition | test.py:72 | Attribute 'x' taint simple.test | arg |
| test.py:72 | ParameterDefinition | test.py:72 | Taint basic.custom | arg |
| test.py:72 | ParameterDefinition | test.py:72 | Taint simple.test | arg |
| test.py:76 | SOURCE | test.py:76 | Taint simple.test | SOURCE |
| test.py:77 | hub() | test.py:77 | Taint simple.test | hub() |
| test.py:78 | ArgumentRefinement(t_1) | test.py:77 | Taint simple.test | hub() |
| test.py:85 | ImportExpr | test.py:85 | Attribute 'dangerous' taint simple.test | ImportExpr |
| test.py:87 | ScopeEntryDefinition | test.py:85 | Attribute 'dangerous' taint simple.test | ImportExpr |
| test.py:88 | Attribute | test.py:88 | Taint simple.test | Attribute |
| test.py:89 | ArgumentRefinement(t_0) | test.py:88 | Taint simple.test | Attribute |
| test.py:91 | ScopeEntryDefinition | test.py:85 | Attribute 'dangerous' taint simple.test | ImportExpr |
| test.py:95 | ScopeEntryDefinition | test.py:85 | Attribute 'dangerous' taint simple.test | ImportExpr |
| test.py:99 | ScopeEntryDefinition | test.py:85 | Attribute 'dangerous' taint simple.test | ImportExpr |
| test.py:100 | Attribute() | test.py:100 | Taint simple.test | Attribute() |
| test.py:101 | ArgumentRefinement(t_0) | test.py:100 | Taint simple.test | Attribute() |
| test.py:105 | ParameterDefinition | test.py:105 | Attribute 'x' taint simple.test | arg |
| test.py:108 | ScopeEntryDefinition | test.py:85 | Attribute 'dangerous' taint simple.test | ImportExpr |
| test.py:110 | AttributeAssignment 'x'(t_0) | test.py:110 | Attribute 'x' taint simple.test | t |
| test.py:113 | ScopeEntryDefinition | test.py:85 | Attribute 'dangerous' taint simple.test | ImportExpr |
| test.py:115 | AttributeAssignment 'x'(t_0) | test.py:115 | Attribute 'x' taint simple.test | t |
| test.py:116 | hub() | test.py:116 | Attribute 'x' taint simple.test | hub() |
| test.py:117 | ArgumentRefinement(t_2) | test.py:116 | Attribute 'x' taint simple.test | hub() |
| test.py:120 | CUSTOM_SOURCE | test.py:120 | Taint basic.custom | CUSTOM_SOURCE |
| test.py:121 | hub() | test.py:121 | Taint basic.custom | hub() |
| test.py:122 | ArgumentRefinement(t_1) | test.py:121 | Taint basic.custom | hub() |
| test.py:126 | CUSTOM_SOURCE | test.py:126 | Taint basic.custom | CUSTOM_SOURCE |
| test.py:128 | SOURCE | test.py:128 | Taint simple.test | SOURCE |
| test.py:130 | ArgumentRefinement(t_0) | test.py:126 | Taint basic.custom | CUSTOM_SOURCE |
| test.py:132 | ArgumentRefinement(t_2) | test.py:128 | Taint simple.test | SOURCE |
| test.py:136 | CUSTOM_SOURCE | test.py:136 | Taint basic.custom | CUSTOM_SOURCE |
| test.py:138 | SOURCE | test.py:138 | Taint simple.test | SOURCE |
| test.py:140 | ArgumentRefinement(t_2) | test.py:138 | Taint simple.test | SOURCE |
| test.py:142 | ArgumentRefinement(t_0) | test.py:136 | Taint basic.custom | CUSTOM_SOURCE |
| test.py:146 | CUSTOM_SOURCE | test.py:146 | Taint basic.custom | CUSTOM_SOURCE |
| test.py:148 | SOURCE | test.py:148 | Taint simple.test | SOURCE |
| test.py:149 | TAINT_FROM_ARG() | test.py:149 | Taint basic.custom | TAINT_FROM_ARG() |
| test.py:151 | ArgumentRefinement(t_1) | test.py:149 | Taint basic.custom | TAINT_FROM_ARG() |
| test.py:155 | ImportMember | test.py:155 | Taint simple.test | ImportMember |
| test.py:156 | ArgumentRefinement(unsafe_0) | test.py:155 | Taint simple.test | ImportMember |
| test.py:159 | with | test.py:159 | Taint simple.test | SOURCE |
| test.py:160 | ArgumentRefinement(t_0) | test.py:159 | Taint simple.test | SOURCE |
| test.py:163 | SOURCE | test.py:163 | Taint simple.test | SOURCE |
| test.py:168 | List | test.py:168 | Taint [simple.test] | List |
| test.py:169 | Dict | test.py:169 | Taint {simple.test} | Dict |
| test.py:170 | ArgumentRefinement(l_0) | test.py:168 | Taint [simple.test] | List |
| test.py:171 | ArgumentRefinement(d_0) | test.py:169 | Taint {simple.test} | Dict |
| test.py:174 | ArgumentRefinement(l_1) | test.py:168 | Taint [simple.test] | List |
| test.py:174 | list() | test.py:174 | Taint [simple.test] | list() |
| test.py:175 | ArgumentRefinement(d_1) | test.py:169 | Taint {simple.test} | Dict |
| test.py:175 | dict() | test.py:175 | Taint {simple.test} | dict() |
| test.py:178 | SOURCE | test.py:178 | Taint simple.test | SOURCE |
| test.py:180 | ArgumentRefinement(t_1) | test.py:178 | Taint simple.test | SOURCE |
| test.py:180 | Pi(t_0) [true] | test.py:178 | Taint simple.test | SOURCE |
| test.py:183 | SingleSuccessorGuard(t_2) [false] | test.py:178 | Taint simple.test | SOURCE |
| test.py:186 | ArgumentRefinement(t_3) | test.py:178 | Taint simple.test | SOURCE |
| test.py:189 | FALSEY | test.py:189 | Taint falsey | FALSEY |
| test.py:191 | Pi(t_0) [true] | test.py:189 | Taint falsey | FALSEY |

Просмотреть файл

@ -0,0 +1,9 @@
import python
import semmle.python.security.TaintTest
import TaintLib
from EssaDefinition defn, TaintedNode n
where TaintFlowTest::tainted_def(defn, _, n)
select
defn.getLocation().toString(), defn.getRepresentation(), n.getLocation().toString(), n.getTrackedValue(), n.getNode().getNode().toString()

Просмотреть файл

@ -94,6 +94,8 @@
| Taint explicit.carrier | carrier.py:33 | TAINT_CARRIER_SOURCE | |
| Taint explicit.carrier | carrier.py:34 | Attribute | |
| Taint explicit.carrier | carrier.py:35 | x | |
| Taint falsey | test.py:189 | FALSEY | |
| Taint falsey | test.py:190 | t | |
| Taint paper | rockpaperscissors.py:6 | arg | rockpaperscissors.py:32 |
| Taint paper | rockpaperscissors.py:9 | arg | rockpaperscissors.py:26 |
| Taint paper | rockpaperscissors.py:25 | Attribute() | |

Просмотреть файл

@ -41,3 +41,4 @@
| test.py:168 | SOURCE | simple.test |
| test.py:169 | SOURCE | simple.test |
| test.py:178 | SOURCE | simple.test |
| test.py:189 | FALSEY | falsey |

Просмотреть файл

@ -82,6 +82,7 @@
| Taint explicit.carrier | carrier.py:33 | TAINT_CARRIER_SOURCE | | --> | Taint explicit.carrier | carrier.py:4 | arg | carrier.py:33 |
| Taint explicit.carrier | carrier.py:34 | Attribute | | --> | Taint explicit.carrier | carrier.py:35 | x | |
| Taint explicit.carrier | carrier.py:35 | x | | --> | Taint simple.test | carrier.py:35 | Attribute() | |
| Taint falsey | test.py:189 | FALSEY | | --> | Taint falsey | test.py:190 | t | |
| Taint paper | rockpaperscissors.py:25 | Attribute() | | --> | Taint paper | rockpaperscissors.py:26 | y | |
| Taint paper | rockpaperscissors.py:26 | y | | --> | Taint paper | rockpaperscissors.py:9 | arg | rockpaperscissors.py:26 |
| Taint paper | rockpaperscissors.py:30 | Attribute() | | --> | Taint paper | rockpaperscissors.py:32 | y | |

Просмотреть файл

@ -182,3 +182,5 @@
| test.py:180 | t_2 | test.py:178 | Taint simple.test | SOURCE |
| test.py:183 | t_3 | test.py:178 | Taint simple.test | SOURCE |
| test.py:186 | t_4 | test.py:178 | Taint simple.test | SOURCE |
| test.py:189 | t_0 | test.py:189 | Taint falsey | FALSEY |
| test.py:191 | t_1 | test.py:189 | Taint falsey | FALSEY |

Просмотреть файл

@ -184,3 +184,9 @@ def test_truth():
SINK(t)
else:
SINK(t)
def test_early_exit():
t = FALSEY
if not t:
return
t

Просмотреть файл

@ -10,6 +10,7 @@ edges
| functions_test.py:298:21:298:21 | empty mutable value | functions_test.py:293:21:293:21 | empty mutable value |
| functions_test.py:300:26:300:26 | empty mutable value | functions_test.py:301:8:301:8 | empty mutable value |
| functions_test.py:300:26:300:26 | empty mutable value | functions_test.py:303:12:303:12 | empty mutable value |
| functions_test.py:305:21:305:25 | empty mutable value | functions_test.py:306:12:306:16 | empty mutable value |
parents
| functions_test.py:290:25:290:25 | empty mutable value | functions_test.py:297:25:297:25 | empty mutable value |
| functions_test.py:291:5:291:5 | empty mutable value | functions_test.py:297:25:297:25 | empty mutable value |

Просмотреть файл

@ -302,3 +302,8 @@ def guarded_modification(z=[]):
z.append(0)
return z
def issue1143(expr, param=[]):
if not param:
return result
for i in param:
param.remove(i) # Mutation here