зеркало из https://github.com/github/codeql.git
Merge branch 'master' into moremsalloc
This commit is contained in:
Коммит
bdd6965d1b
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче