Merge branch 'master' into fp2762

This commit is contained in:
Geoffrey White
2020-05-19 11:43:50 +01:00
112 changed files with 6436 additions and 1075 deletions

View File

@@ -3,6 +3,7 @@
## General improvements
* Support for the following frameworks and libraries has been improved:
- [express](https://www.npmjs.com/package/express)
- [fstream](https://www.npmjs.com/package/fstream)
- [jGrowl](https://github.com/stanlemon/jGrowl)
- [jQuery](https://jquery.com/)
@@ -24,10 +25,14 @@
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Less results | This query now recognizes additional safe patterns of doing URL redirects. |
| Client-side cross-site scripting (`js/xss`) | Less results | This query now recognizes additional safe strings based on URLs. |
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
| Expression has no effect (`js/useless-expression`) | Less results | This query no longer flags an expression when that expression is the only content of the containing file. |
| Unknown directive (`js/unknown-directive`) | Less results | This query no longer flags directives generated by the Babel compiler. |
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving NoSQL code operators are now recognized. |
| Zip Slip (`js/zipslip`) | More results | This query now recognizes zip-slip vulnerabilities involving links. |
| Zip Slip (`js/zipslip`) | More results | This query now recognizes additional vulnerabilities. |
## Changes to libraries

View File

@@ -6,9 +6,13 @@ private import semmle.code.cpp.dataflow.EscapesTree
/**
* A C/C++ access expression. This refers to a function, variable, or enum constant.
*/
abstract class Access extends Expr, NameQualifiableElement {
class Access extends Expr, NameQualifiableElement, @access {
// As `@access` is a union type containing `@routineexpr` (which describes function accesses
// that are called), we need to exclude function calls.
Access() { this instanceof @routineexpr implies not iscall(underlyingElement(this), _) }
/** Gets the accessed function, variable, or enum constant. */
abstract Declaration getTarget();
Declaration getTarget() { none() } // overridden in subclasses
override predicate mayBeImpure() { none() }

View File

@@ -7,7 +7,7 @@ private import semmle.code.cpp.internal.ResolveClass
* Instances of this class are not present in the main AST which is navigated by parent/child links. Instead,
* instances of this class are attached to nodes in the main AST via special conversion links.
*/
abstract class Conversion extends Expr {
class Conversion extends Expr, @conversion {
/** Gets the expression being converted. */
Expr getExpr() { result.getConversion() = this }

View File

@@ -14,12 +14,8 @@ private newtype TOperand =
not Construction::isInCycle(useInstr) and
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
useInstr.getOpcode().hasOperand(tag)
} or
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -27,6 +23,57 @@ private newtype TOperand =
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/**
* Base class for all register operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class RegisterOperandBase extends TRegisterOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the register operand with the specified parameters.
*/
private RegisterOperandBase registerOperand(
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
) {
result = TRegisterOperand(useInstr, tag, defInstr)
}
/**
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
* will eventually use for this purpose.
*/
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
result = TNonPhiMemoryOperand(useInstr, tag)
}
/**
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class PhiOperandBase extends TPhiOperand {
abstract string toString();
}
/**
* Returns the Phi operand with the specified parameters.
*/
private PhiOperandBase phiOperand(
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
@@ -165,8 +212,8 @@ class Operand extends TOperand {
*/
class MemoryOperand extends Operand {
MemoryOperand() {
this = TNonPhiMemoryOperand(_, _, _, _) or
this = TPhiOperand(_, _, _, _)
this instanceof NonPhiMemoryOperandBase or
this instanceof PhiOperandBase
}
/**
@@ -200,18 +247,15 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
this = TRegisterOperand(useInstr, tag, defInstr) or
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
this = registerOperand(useInstr, tag, _) or
this = nonPhiMemoryOperand(useInstr, tag)
}
final override Instruction getUse() { result = useInstr }
final override Instruction getAnyDef() { result = defInstr }
final override string getDumpLabel() { result = tag.getLabel() }
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -222,8 +266,15 @@ class NonPhiOperand extends Operand {
/**
* An operand that consumes a register (non-memory) result.
*/
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
override RegisterOperandTag tag;
Instruction defInstr;
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
@@ -231,13 +282,25 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
}
}
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
final override Overlap getDefinitionOverlap() { result = overlap }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() {
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
}
}
class TypedOperand extends NonPhiMemoryOperand {
@@ -254,8 +317,6 @@ class TypedOperand extends NonPhiMemoryOperand {
*/
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() { result = "Address" }
}
/**
@@ -264,8 +325,6 @@ class AddressOperand extends RegisterOperand {
*/
class BufferSizeOperand extends RegisterOperand {
override BufferSizeOperandTag tag;
override string toString() { result = "BufferSize" }
}
/**
@@ -274,8 +333,6 @@ class BufferSizeOperand extends RegisterOperand {
*/
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() { result = "Load" }
}
/**
@@ -283,8 +340,6 @@ class LoadOperand extends TypedOperand {
*/
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() { result = "StoreValue" }
}
/**
@@ -292,8 +347,6 @@ class StoreValueOperand extends RegisterOperand {
*/
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() { result = "Unary" }
}
/**
@@ -301,8 +354,6 @@ class UnaryOperand extends RegisterOperand {
*/
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() { result = "Left" }
}
/**
@@ -310,8 +361,6 @@ class LeftOperand extends RegisterOperand {
*/
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() { result = "Right" }
}
/**
@@ -319,8 +368,6 @@ class RightOperand extends RegisterOperand {
*/
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() { result = "Condition" }
}
/**
@@ -328,8 +375,6 @@ class ConditionOperand extends RegisterOperand {
*/
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() { result = "CallTarget" }
}
/**
@@ -347,8 +392,6 @@ class ArgumentOperand extends RegisterOperand {
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() { result = "ThisArgument" }
}
/**
@@ -356,34 +399,27 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() { result = argIndex }
final int getIndex() { result = tag.getArgIndex() }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override string toString() { result = "SideEffect" }
}
/**
* An operand of a `PhiInstruction`.
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() { result = "Phi" }
@@ -413,8 +449,6 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() { result = "ChiTotal" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
@@ -424,7 +458,5 @@ class ChiTotalOperand extends NonPhiMemoryOperand {
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() { result = "ChiPartial" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -221,7 +221,9 @@ PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
result = TPositionalArgumentOperand(argIndex)
}
class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
abstract class ChiOperandTag extends MemoryOperandTag { }
class ChiTotalOperandTag extends ChiOperandTag, TChiTotalOperand {
final override string toString() { result = "ChiTotal" }
final override int getSortOrder() { result = 13 }
@@ -231,7 +233,7 @@ class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
ChiTotalOperandTag chiTotalOperand() { result = TChiTotalOperand() }
class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand {
class ChiPartialOperandTag extends ChiOperandTag, TChiPartialOperand {
final override string toString() { result = "ChiPartial" }
final override int getSortOrder() { result = 14 }

View File

@@ -14,12 +14,8 @@ private newtype TOperand =
not Construction::isInCycle(useInstr) and
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
useInstr.getOpcode().hasOperand(tag)
} or
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -27,6 +23,57 @@ private newtype TOperand =
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/**
* Base class for all register operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class RegisterOperandBase extends TRegisterOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the register operand with the specified parameters.
*/
private RegisterOperandBase registerOperand(
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
) {
result = TRegisterOperand(useInstr, tag, defInstr)
}
/**
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
* will eventually use for this purpose.
*/
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
result = TNonPhiMemoryOperand(useInstr, tag)
}
/**
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class PhiOperandBase extends TPhiOperand {
abstract string toString();
}
/**
* Returns the Phi operand with the specified parameters.
*/
private PhiOperandBase phiOperand(
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
@@ -165,8 +212,8 @@ class Operand extends TOperand {
*/
class MemoryOperand extends Operand {
MemoryOperand() {
this = TNonPhiMemoryOperand(_, _, _, _) or
this = TPhiOperand(_, _, _, _)
this instanceof NonPhiMemoryOperandBase or
this instanceof PhiOperandBase
}
/**
@@ -200,18 +247,15 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
this = TRegisterOperand(useInstr, tag, defInstr) or
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
this = registerOperand(useInstr, tag, _) or
this = nonPhiMemoryOperand(useInstr, tag)
}
final override Instruction getUse() { result = useInstr }
final override Instruction getAnyDef() { result = defInstr }
final override string getDumpLabel() { result = tag.getLabel() }
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -222,8 +266,15 @@ class NonPhiOperand extends Operand {
/**
* An operand that consumes a register (non-memory) result.
*/
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
override RegisterOperandTag tag;
Instruction defInstr;
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
@@ -231,13 +282,25 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
}
}
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
final override Overlap getDefinitionOverlap() { result = overlap }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() {
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
}
}
class TypedOperand extends NonPhiMemoryOperand {
@@ -254,8 +317,6 @@ class TypedOperand extends NonPhiMemoryOperand {
*/
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() { result = "Address" }
}
/**
@@ -264,8 +325,6 @@ class AddressOperand extends RegisterOperand {
*/
class BufferSizeOperand extends RegisterOperand {
override BufferSizeOperandTag tag;
override string toString() { result = "BufferSize" }
}
/**
@@ -274,8 +333,6 @@ class BufferSizeOperand extends RegisterOperand {
*/
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() { result = "Load" }
}
/**
@@ -283,8 +340,6 @@ class LoadOperand extends TypedOperand {
*/
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() { result = "StoreValue" }
}
/**
@@ -292,8 +347,6 @@ class StoreValueOperand extends RegisterOperand {
*/
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() { result = "Unary" }
}
/**
@@ -301,8 +354,6 @@ class UnaryOperand extends RegisterOperand {
*/
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() { result = "Left" }
}
/**
@@ -310,8 +361,6 @@ class LeftOperand extends RegisterOperand {
*/
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() { result = "Right" }
}
/**
@@ -319,8 +368,6 @@ class RightOperand extends RegisterOperand {
*/
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() { result = "Condition" }
}
/**
@@ -328,8 +375,6 @@ class ConditionOperand extends RegisterOperand {
*/
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() { result = "CallTarget" }
}
/**
@@ -347,8 +392,6 @@ class ArgumentOperand extends RegisterOperand {
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() { result = "ThisArgument" }
}
/**
@@ -356,34 +399,27 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() { result = argIndex }
final int getIndex() { result = tag.getArgIndex() }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override string toString() { result = "SideEffect" }
}
/**
* An operand of a `PhiInstruction`.
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() { result = "Phi" }
@@ -413,8 +449,6 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() { result = "ChiTotal" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
@@ -424,7 +458,5 @@ class ChiTotalOperand extends NonPhiMemoryOperand {
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() { result = "ChiPartial" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -14,12 +14,8 @@ private newtype TOperand =
not Construction::isInCycle(useInstr) and
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
useInstr.getOpcode().hasOperand(tag)
} or
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -27,6 +23,57 @@ private newtype TOperand =
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/**
* Base class for all register operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class RegisterOperandBase extends TRegisterOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the register operand with the specified parameters.
*/
private RegisterOperandBase registerOperand(
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
) {
result = TRegisterOperand(useInstr, tag, defInstr)
}
/**
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
* will eventually use for this purpose.
*/
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
result = TNonPhiMemoryOperand(useInstr, tag)
}
/**
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class PhiOperandBase extends TPhiOperand {
abstract string toString();
}
/**
* Returns the Phi operand with the specified parameters.
*/
private PhiOperandBase phiOperand(
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
@@ -165,8 +212,8 @@ class Operand extends TOperand {
*/
class MemoryOperand extends Operand {
MemoryOperand() {
this = TNonPhiMemoryOperand(_, _, _, _) or
this = TPhiOperand(_, _, _, _)
this instanceof NonPhiMemoryOperandBase or
this instanceof PhiOperandBase
}
/**
@@ -200,18 +247,15 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
this = TRegisterOperand(useInstr, tag, defInstr) or
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
this = registerOperand(useInstr, tag, _) or
this = nonPhiMemoryOperand(useInstr, tag)
}
final override Instruction getUse() { result = useInstr }
final override Instruction getAnyDef() { result = defInstr }
final override string getDumpLabel() { result = tag.getLabel() }
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -222,8 +266,15 @@ class NonPhiOperand extends Operand {
/**
* An operand that consumes a register (non-memory) result.
*/
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
override RegisterOperandTag tag;
Instruction defInstr;
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
@@ -231,13 +282,25 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
}
}
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
final override Overlap getDefinitionOverlap() { result = overlap }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() {
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
}
}
class TypedOperand extends NonPhiMemoryOperand {
@@ -254,8 +317,6 @@ class TypedOperand extends NonPhiMemoryOperand {
*/
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() { result = "Address" }
}
/**
@@ -264,8 +325,6 @@ class AddressOperand extends RegisterOperand {
*/
class BufferSizeOperand extends RegisterOperand {
override BufferSizeOperandTag tag;
override string toString() { result = "BufferSize" }
}
/**
@@ -274,8 +333,6 @@ class BufferSizeOperand extends RegisterOperand {
*/
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() { result = "Load" }
}
/**
@@ -283,8 +340,6 @@ class LoadOperand extends TypedOperand {
*/
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() { result = "StoreValue" }
}
/**
@@ -292,8 +347,6 @@ class StoreValueOperand extends RegisterOperand {
*/
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() { result = "Unary" }
}
/**
@@ -301,8 +354,6 @@ class UnaryOperand extends RegisterOperand {
*/
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() { result = "Left" }
}
/**
@@ -310,8 +361,6 @@ class LeftOperand extends RegisterOperand {
*/
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() { result = "Right" }
}
/**
@@ -319,8 +368,6 @@ class RightOperand extends RegisterOperand {
*/
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() { result = "Condition" }
}
/**
@@ -328,8 +375,6 @@ class ConditionOperand extends RegisterOperand {
*/
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() { result = "CallTarget" }
}
/**
@@ -347,8 +392,6 @@ class ArgumentOperand extends RegisterOperand {
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() { result = "ThisArgument" }
}
/**
@@ -356,34 +399,27 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() { result = argIndex }
final int getIndex() { result = tag.getArgIndex() }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override string toString() { result = "SideEffect" }
}
/**
* An operand of a `PhiInstruction`.
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() { result = "Phi" }
@@ -413,8 +449,6 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() { result = "ChiTotal" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
@@ -424,7 +458,5 @@ class ChiTotalOperand extends NonPhiMemoryOperand {
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() { result = "ChiPartial" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -14,3 +14,4 @@ private import implementations.Strdup
private import implementations.Strftime
private import implementations.StdString
private import implementations.Swap
private import implementations.GetDelim

View File

@@ -0,0 +1,40 @@
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.FlowSource
/**
* The standard functions `getdelim`, `getwdelim` and the glibc variant `__getdelim`.
*/
class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction, RemoteFlowFunction {
GetDelimFunction() { hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) }
override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) {
i.isParameter(3) and o.isParameterDeref(0)
}
override predicate parameterNeverEscapes(int index) { index = [0, 1, 3] }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate parameterIsAlwaysReturned(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = [0, 1] and
buffer = false and
mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 3 and buffer = false
}
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(0) and
description = "String read by " + this.getName()
}
}

View File

@@ -1143,6 +1143,13 @@ conversionkinds(
int kind: int ref
);
@conversion = @cast
| @array_to_pointer
| @parexpr
| @reference_to
| @ref_indirect
;
/*
case @funbindexpr.kind of
0 = @normal_call // a normal call
@@ -1800,6 +1807,8 @@ lambda_capture(
@addressable = @function | @variable ;
@accessible = @addressable | @enumconstant ;
@access = @varaccess | @routineexpr ;
fold(
int expr: @foldexpr ref,
string operator: string ref,

View File

@@ -1524,7 +1524,7 @@
</e>
<e>
<k>seconds</k>
<v>12697</v>
<v>12094</v>
</e>
</columnsizes>
<dependencies>
@@ -1570,17 +1570,17 @@
<b>
<a>2</a>
<b>3</b>
<v>21</v>
<v>10</v>
</b>
<b>
<a>3</a>
<b>4</b>
<v>2478</v>
<v>2675</v>
</b>
<b>
<a>4</a>
<b>5</b>
<v>7028</v>
<v>6842</v>
</b>
</bs>
</hist>
@@ -1626,8 +1626,8 @@
<budget>12</budget>
<bs>
<b>
<a>1158</a>
<b>1159</b>
<a>1103</a>
<b>1104</b>
<v>10</v>
</b>
</bs>
@@ -1679,18 +1679,18 @@
<v>10</v>
</b>
<b>
<a>14</a>
<b>15</b>
<a>13</a>
<b>14</b>
<v>10</v>
</b>
<b>
<a>565</a>
<b>566</b>
<a>579</a>
<b>580</b>
<v>10</v>
</b>
<b>
<a>693</a>
<b>694</b>
<a>670</a>
<b>671</b>
<v>10</v>
</b>
</bs>
@@ -1707,22 +1707,22 @@
<b>
<a>1</a>
<b>2</b>
<v>8859</v>
<v>7949</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>2313</v>
<v>2401</v>
</b>
<b>
<a>3</a>
<b>5</b>
<v>1107</v>
<b>4</b>
<v>932</v>
</b>
<b>
<a>5</a>
<b>614</b>
<v>416</v>
<a>4</a>
<b>627</b>
<v>811</v>
</b>
</bs>
</hist>
@@ -1738,7 +1738,7 @@
<b>
<a>1</a>
<b>2</b>
<v>12697</v>
<v>12094</v>
</b>
</bs>
</hist>
@@ -1754,17 +1754,17 @@
<b>
<a>1</a>
<b>2</b>
<v>11403</v>
<v>10285</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>1271</v>
<v>1798</v>
</b>
<b>
<a>3</a>
<b>5</b>
<v>21</v>
<b>4</b>
<v>10</v>
</b>
</bs>
</hist>
@@ -2143,7 +2143,7 @@
</e>
<e>
<k>cpu_seconds</k>
<v>7927</v>
<v>8157</v>
</e>
<e>
<k>elapsed_seconds</k>
@@ -2193,17 +2193,17 @@
<b>
<a>1</a>
<b>2</b>
<v>6820</v>
<v>7160</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>778</v>
<v>756</v>
</b>
<b>
<a>3</a>
<b>8</b>
<v>328</v>
<b>6</b>
<v>241</v>
</b>
</bs>
</hist>
@@ -2219,12 +2219,12 @@
<b>
<a>1</a>
<b>2</b>
<v>7587</v>
<v>7675</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>339</v>
<v>482</v>
</b>
</bs>
</hist>
@@ -2240,66 +2240,66 @@
<b>
<a>1</a>
<b>2</b>
<v>10</v>
<v>32</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>21</v>
<v>10</v>
</b>
<b>
<a>3</a>
<b>4</b>
<v>21</v>
<v>32</v>
</b>
<b>
<a>4</a>
<b>5</b>
<v>21</v>
</b>
<b>
<a>10</a>
<b>11</b>
<v>21</v>
</b>
<b>
<a>18</a>
<b>19</b>
<a>7</a>
<b>8</b>
<v>10</v>
</b>
<b>
<a>37</a>
<b>38</b>
<a>8</a>
<b>9</b>
<v>10</v>
</b>
<b>
<a>51</a>
<b>52</b>
<a>21</a>
<b>22</b>
<v>10</v>
</b>
<b>
<a>62</a>
<b>63</b>
<a>26</a>
<b>27</b>
<v>10</v>
</b>
<b>
<a>99</a>
<b>100</b>
<a>31</a>
<b>32</b>
<v>10</v>
</b>
<b>
<a>158</a>
<b>159</b>
<a>104</a>
<b>105</b>
<v>10</v>
</b>
<b>
<a>170</a>
<b>171</b>
<a>137</a>
<b>138</b>
<v>10</v>
</b>
<b>
<a>237</a>
<b>238</b>
<a>144</a>
<b>145</b>
<v>10</v>
</b>
<b>
<a>173</a>
<b>174</b>
<v>10</v>
</b>
<b>
<a>206</a>
<b>207</b>
<v>10</v>
</b>
</bs>
@@ -2316,66 +2316,66 @@
<b>
<a>1</a>
<b>2</b>
<v>10</v>
<v>32</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>21</v>
<v>10</v>
</b>
<b>
<a>3</a>
<b>4</b>
<v>21</v>
<v>32</v>
</b>
<b>
<a>4</a>
<b>5</b>
<v>21</v>
</b>
<b>
<a>10</a>
<b>11</b>
<v>21</v>
</b>
<b>
<a>18</a>
<b>19</b>
<a>7</a>
<b>8</b>
<v>10</v>
</b>
<b>
<a>35</a>
<b>36</b>
<a>8</a>
<b>9</b>
<v>10</v>
</b>
<b>
<a>50</a>
<b>51</b>
<a>21</a>
<b>22</b>
<v>10</v>
</b>
<b>
<a>59</a>
<b>60</b>
<a>25</a>
<b>26</b>
<v>10</v>
</b>
<b>
<a>74</a>
<b>75</b>
<a>29</a>
<b>30</b>
<v>10</v>
</b>
<b>
<a>144</a>
<b>145</b>
<a>84</a>
<b>85</b>
<v>10</v>
</b>
<b>
<a>162</a>
<b>163</b>
<a>122</a>
<b>123</b>
<v>10</v>
</b>
<b>
<a>173</a>
<b>174</b>
<a>132</a>
<b>133</b>
<v>10</v>
</b>
<b>
<a>150</a>
<b>151</b>
<v>10</v>
</b>
<b>
<a>196</a>
<b>197</b>
<v>10</v>
</b>
</bs>

View File

@@ -591,3 +591,13 @@
| taint.cpp:463:6:463:6 | 0 | taint.cpp:471:7:471:7 | y | |
| taint.cpp:468:7:468:7 | ref arg x | taint.cpp:470:7:470:7 | x | |
| taint.cpp:468:10:468:10 | ref arg y | taint.cpp:471:7:471:7 | y | |
| taint.cpp:480:26:480:32 | source1 | taint.cpp:483:28:483:34 | source1 | |
| taint.cpp:481:15:481:21 | 0 | taint.cpp:483:12:483:15 | line | |
| taint.cpp:481:15:481:21 | 0 | taint.cpp:485:7:485:10 | line | |
| taint.cpp:482:9:482:9 | n | taint.cpp:483:19:483:19 | n | |
| taint.cpp:483:11:483:15 | ref arg & ... | taint.cpp:483:12:483:15 | line [inner post update] | |
| taint.cpp:483:11:483:15 | ref arg & ... | taint.cpp:485:7:485:10 | line | |
| taint.cpp:483:12:483:15 | line | taint.cpp:483:11:483:15 | & ... | |
| taint.cpp:483:18:483:19 | ref arg & ... | taint.cpp:483:19:483:19 | n [inner post update] | |
| taint.cpp:483:19:483:19 | n | taint.cpp:483:18:483:19 | & ... | |
| taint.cpp:483:28:483:34 | source1 | taint.cpp:483:11:483:15 | ref arg & ... | TAINT |

View File

@@ -470,3 +470,17 @@ void test_swop() {
sink(x); // clean [FALSE POSITIVE]
sink(y); // tainted
}
// --- getdelim ---
struct FILE;
int getdelim(char ** lineptr, size_t * n, int delimiter, FILE *stream);
void test_getdelim(FILE* source1) {
char* line = nullptr;
size_t n;
getdelim(&line, &n, '\n', source1);
sink(line);
}

View File

@@ -67,3 +67,4 @@
| taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source |
| taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source |
| taint.cpp:471:7:471:7 | y | taint.cpp:462:6:462:11 | call to source |
| taint.cpp:485:7:485:10 | line | taint.cpp:480:26:480:32 | source1 |

View File

@@ -28,3 +28,4 @@
| taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source |
| taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source |
| taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source |
| taint.cpp:485:7:485:10 | line | taint.cpp:480:26:480:32 | source1 |

View File

@@ -1,7 +1,6 @@
missingOperand
unexpectedOperand
duplicateOperand
| ssa.cpp:301:27:301:30 | ReturnIndirection: argv | Instruction has 2 operands with tag 'SideEffect' in function '$@'. | ssa.cpp:301:5:301:8 | IR: main | int main(int, char**) |
missingPhiOperand
missingOperandType
duplicateChiOperand

View File

@@ -1480,7 +1480,7 @@ ssa.cpp:
# 304| r304_5(char) = Load : &:r304_4, ~m303_8
# 304| r304_6(int) = Convert : r304_5
# 304| m304_7(int) = Store : &:r304_1, r304_6
# 301| v301_12(void) = ReturnIndirection[argv] : &:r301_10, ~m303_11, m303_11
# 301| v301_12(void) = ReturnIndirection[argv] : &:r301_10, m303_11
# 301| r301_13(glval<int>) = VariableAddress[#return] :
# 301| v301_14(void) = ReturnValue : &:r301_13, m304_7
# 301| v301_15(void) = AliasedUse : ~m303_8

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add union types for casts and accesses
compatibility: full

View File

@@ -1,7 +1,7 @@
/**
* @name Invalid format string
* @description Using a format string with an incorrect format causes a 'System.FormatException'.
* @kind problem
* @kind path-problem
* @problem.severity error
* @precision high
* @id cs/invalid-format-string
@@ -11,7 +11,8 @@
import csharp
import semmle.code.csharp.frameworks.Format
import FormatFlow
from FormatCall s, InvalidFormatString src
where src = s.getAFormatSource()
select src, "Invalid format string used in $@ formatting call.", s, "this"
from FormatCall s, InvalidFormatString src, PathNode source, PathNode sink
where hasFlowPath(src, source, s, sink)
select src, source, sink, "Invalid format string used in $@ formatting call.", s, "this"

View File

@@ -1,7 +1,7 @@
/**
* @name Missing format argument
* @description Supplying too few arguments to a format string causes a 'System.FormatException'.
* @kind problem
* @kind path-problem
* @problem.severity error
* @precision high
* @id cs/format-argument-missing
@@ -11,11 +11,14 @@
import csharp
import semmle.code.csharp.frameworks.Format
import FormatFlow
from FormatCall format, ValidFormatString src, int used, int supplied
from
FormatCall format, ValidFormatString src, int used, int supplied, PathNode source, PathNode sink
where
src = format.getAFormatSource() and
hasFlowPath(src, source, format, sink) and
used = src.getAnInsert() and
supplied = format.getSuppliedArguments() and
used >= supplied
select format, "Argument '{" + used + "}' has not been supplied to $@ format string.", src, "this"
select format, source, sink, "Argument '{" + used + "}' has not been supplied to $@ format string.",
src, "this"

View File

@@ -1,7 +1,7 @@
/**
* @name Unused format argument
* @description Supplying more arguments than are required for a format string may indicate an error in the format string.
* @kind problem
* @kind path-problem
* @problem.severity warning
* @precision high
* @id cs/format-argument-unused
@@ -11,11 +11,12 @@
import csharp
import semmle.code.csharp.frameworks.Format
import FormatFlow
from FormatCall format, int unused, ValidFormatString src
from FormatCall format, int unused, ValidFormatString src, PathNode source, PathNode sink
where
src = format.getAFormatSource() and
hasFlowPath(src, source, format, sink) and
unused = format.getAnUnusedArgument(src) and
not src.getValue() = ""
select format, "The $@ ignores $@.", src, "format string", format.getSuppliedExpr(unused),
"this supplied value"
select format, source, sink, "The $@ ignores $@.", src, "format string",
format.getSuppliedExpr(unused), "this supplied value"

View File

@@ -250,7 +250,7 @@ private module Gvn {
private class LeafType extends Type {
LeafType() {
not exists(this.getAChild()) and
not this instanceof Unification::GenericType and
not this instanceof MethodTypeParameter and
not this instanceof DynamicType
}
@@ -267,7 +267,9 @@ private module Gvn {
gvnConstructedCons(_, _, _, head, tail)
}
private ConstructedGvnTypeList gvnConstructed(Type t, Unification::CompoundTypeKind k, int i) {
private ConstructedGvnTypeList gvnConstructed(
Unification::GenericType t, Unification::CompoundTypeKind k, int i
) {
result = TConstructedGvnTypeNil(k) and
i = -1 and
k = Unification::getTypeKind(t)
@@ -278,14 +280,17 @@ private module Gvn {
}
pragma[noinline]
private GvnType gvnTypeChild(Type t, int i) { result = getGlobalValueNumber(t.getChild(i)) }
private GvnType gvnTypeArgument(Unification::GenericType t, int i) {
result = getGlobalValueNumber(t.getArgument(i))
}
pragma[noinline]
private predicate gvnConstructedCons(
Type t, Unification::CompoundTypeKind k, int i, GvnType head, ConstructedGvnTypeList tail
Unification::GenericType t, Unification::CompoundTypeKind k, int i, GvnType head,
ConstructedGvnTypeList tail
) {
tail = gvnConstructed(t, k, i - 1) and
head = gvnTypeChild(t, i)
head = gvnTypeArgument(t, i)
}
/** Gets the global value number for a given type. */
@@ -319,6 +324,8 @@ private module Gvn {
}
private class ConstructedGvnTypeList extends TConstructedGvnTypeList {
Unification::CompoundTypeKind getKind() { this = gvnConstructed(_, result, _) }
private int length() {
this = TConstructedGvnTypeNil(_) and result = -1
or
@@ -338,17 +345,47 @@ private module Gvn {
)
}
/**
* Gets a textual representation of this constructed type, restricted
* to the prefix `t` of the underlying source declaration type.
*
* The `toString()` calculation needs to be split up into prefixes, in
* order to apply the type arguments correctly. For example, a source
* declaration type `A<>.B.C<,>` applied to types `int, string, bool`
* needs to be printed as `A<int>.B.C<string,bool>`.
*/
language[monotonicAggregates]
private string toStringConstructed(Unification::GenericType t) {
t = this.getKind().getConstructedSourceDeclaration().getGenericDeclaringType*() and
exists(int offset, int children, string name, string nameArgs |
offset = t.getNumberOfDeclaringArguments() and
children = t.getNumberOfArgumentsSelf() and
name = Unification::getNameNested(t) and
if children = 0
then nameArgs = name
else
exists(string offsetArgs |
offsetArgs =
concat(int i |
i in [offset .. offset + children - 1]
|
this.getArg(i).toString(), "," order by i
) and
nameArgs = name.prefix(name.length() - children - 1) + "<" + offsetArgs + ">"
)
|
offset = 0 and result = nameArgs
or
result = this.toStringConstructed(t.getGenericDeclaringType()) + "." + nameArgs
)
}
language[monotonicAggregates]
string toString() {
exists(Unification::CompoundTypeKind k, string args |
this = gvnConstructed(_, k, _) and
args =
concat(int i |
i in [0 .. k.getNumberOfTypeParameters() - 1]
|
this.getArg(i).toString(), "," order by i
) and
result = k.toString(args)
exists(Unification::CompoundTypeKind k | k = this.getKind() |
result = k.toStringBuiltin(this.getArg(0).toString())
or
result = this.toStringConstructed(k.getConstructedSourceDeclaration())
)
}

View File

@@ -10,9 +10,75 @@ private import Caching
* equal modulo identity conversions and type parameters.
*/
module Gvn {
/**
* Gets the name of type `t`, including the enclosing type of `t` as a qualifier,
* but only if the enclosing type is not a `GenericType`.
*/
string getNameNested(Type t) {
if not t instanceof NestedType or t.(NestedType).getDeclaringType() instanceof GenericType
then result = t.getName()
else result = getNameNested(t.(NestedType).getDeclaringType()) + "." + t.getName()
}
/**
* A generic type. This is either a type with a type parameter, a type with
* a type argument, or a nested type with a generic enclosing type.
*
* In this class, type parameters and type arguments are collectively referred
* to as "arguments".
*/
class GenericType extends Type {
GenericType() {
exists(this.getChild(0))
or
this.(NestedType).getDeclaringType() instanceof GenericType
}
/** Gets the generic containing type, if any. */
GenericType getGenericDeclaringType() { result = this.(NestedType).getDeclaringType() }
/**
* Gets the number of arguments of the generic containing type, or 0 if there
* is no generic containing type.
*/
int getNumberOfDeclaringArguments() {
result = this.getGenericDeclaringType().getNumberOfArguments()
or
not exists(this.getGenericDeclaringType()) and result = 0
}
/** Gets the number of arguments of this type, not taking nested types into account. */
int getNumberOfArgumentsSelf() { result = count(int i | exists(this.getChild(i)) and i >= 0) }
/** Gets the number of arguments of this type, taking nested types into account. */
int getNumberOfArguments() {
result = this.getNumberOfDeclaringArguments() + this.getNumberOfArgumentsSelf()
}
/** Gets the `i`th argument of this type, taking nested types into account. */
Type getArgument(int i) {
result = this.getGenericDeclaringType().getArgument(i)
or
exists(int offset |
offset = this.getNumberOfDeclaringArguments() and
result = this.getChild(i - offset) and
i >= offset
)
}
/** Gets a textual representation of this type, taking nested types into account. */
string toStringNested() {
exists(string name | name = getNameNested(this) |
result = this.getGenericDeclaringType().toStringNested() + "." + name
or
not exists(this.getGenericDeclaringType()) and result = name
)
}
}
private class LeafType extends Type {
LeafType() {
not exists(this.getAChild()) and
not this instanceof GenericType and
not this instanceof TypeParameter and
not this instanceof DynamicType
}
@@ -28,14 +94,22 @@ module Gvn {
or
this = TArrayTypeKind(_, _) and result = 1
or
exists(UnboundGenericType ugt | this = TConstructedType(ugt) |
result = ugt.getNumberOfTypeParameters()
exists(GenericType t | this = TConstructedType(t.getSourceDeclaration()) |
result = t.getNumberOfArguments()
)
}
/** Gets a textual representation of this kind when applied to arguments `args`. */
/** Gets the source declaration type that this kind corresponds to, if any. */
GenericType getConstructedSourceDeclaration() { this = TConstructedType(result) }
/**
* Gets a textual representation of this kind when applied to arguments `args`.
*
* This predicate is restricted to built-in generics (pointers, nullables, and
* arrays).
*/
bindingset[args]
string toString(string args) {
string toStringBuiltin(string args) {
this = TPointerTypeKind() and result = args + "*"
or
this = TNullableTypeKind() and result = args + "?"
@@ -43,14 +117,14 @@ module Gvn {
exists(int rnk | this = TArrayTypeKind(_, rnk) |
result = args + "[" + concat(int i | i in [0 .. rnk - 2] | ",") + "]"
)
or
exists(UnboundGenericType ugt | this = TConstructedType(ugt) |
result = ugt.getNameWithoutBrackets() + "<" + args + ">"
)
}
/** Gets a textual representation of this kind. */
string toString() { result = toString("") }
string toString() {
result = this.toStringBuiltin("")
or
result = this.getConstructedSourceDeclaration().toStringNested()
}
/** Gets the location of this kind. */
Location getLocation() { result instanceof EmptyLocation }
@@ -64,11 +138,9 @@ module Gvn {
or
t = any(ArrayType at | result = TArrayTypeKind(at.getDimension(), at.getRank()))
or
result = TConstructedType(t.(ConstructedType).getUnboundGeneric())
result = TConstructedType(t.getSourceDeclaration())
or
result = TConstructedType(t.(TupleType).getUnderlyingType().getUnboundGeneric())
or
result = TConstructedType(t)
result = TConstructedType(t.(TupleType).getUnderlyingType().getSourceDeclaration())
}
/**
@@ -107,7 +179,7 @@ module Gvn {
override CompoundTypeKind getKind() { result = l.getKind() }
}
private ConstructedGvnTypeList gvnConstructed(Type t, CompoundTypeKind k, int i) {
private ConstructedGvnTypeList gvnConstructed(GenericType t, CompoundTypeKind k, int i) {
result = TConstructedGvnTypeNil(k) and
i = -1 and
k = getTypeKind(t)
@@ -118,14 +190,16 @@ module Gvn {
}
pragma[noinline]
private GvnType gvnTypeChild(Type t, int i) { result = getGlobalValueNumber(t.getChild(i)) }
private GvnType gvnTypeArgument(GenericType t, int i) {
result = getGlobalValueNumber(t.getArgument(i))
}
pragma[noinline]
private predicate gvnConstructedCons(
Type t, CompoundTypeKind k, int i, GvnType head, ConstructedGvnTypeList tail
GenericType t, CompoundTypeKind k, int i, GvnType head, ConstructedGvnTypeList tail
) {
tail = gvnConstructed(t, k, i - 1) and
head = gvnTypeChild(t, i)
head = gvnTypeArgument(t, i)
}
private class ConstructedGvnTypeList extends TConstructedGvnTypeList {
@@ -150,17 +224,47 @@ module Gvn {
)
}
/**
* Gets a textual representation of this constructed type, restricted
* to the prefix `t` of the underlying source declaration type.
*
* The `toString()` calculation needs to be split up into prefixes, in
* order to apply the type arguments correctly. For example, a source
* declaration type `A<>.B.C<,>` applied to types `int, string, bool`
* needs to be printed as `A<int>.B.C<string,bool>`.
*/
language[monotonicAggregates]
private string toStringConstructed(GenericType t) {
t = this.getKind().getConstructedSourceDeclaration().getGenericDeclaringType*() and
exists(int offset, int children, string name, string nameArgs |
offset = t.getNumberOfDeclaringArguments() and
children = t.getNumberOfArgumentsSelf() and
name = getNameNested(t) and
if children = 0
then nameArgs = name
else
exists(string offsetArgs |
offsetArgs =
concat(int i |
i in [offset .. offset + children - 1]
|
this.getArg(i).toString(), "," order by i
) and
nameArgs = name.prefix(name.length() - children - 1) + "<" + offsetArgs + ">"
)
|
offset = 0 and result = nameArgs
or
result = this.toStringConstructed(t.getGenericDeclaringType()) + "." + nameArgs
)
}
language[monotonicAggregates]
string toString() {
exists(CompoundTypeKind k, string args |
k = this.getKind() and
args =
concat(int i |
i in [0 .. k.getNumberOfTypeParameters() - 1]
|
this.getArg(i).toString(), "," order by i
) and
result = k.toString(args)
exists(CompoundTypeKind k | k = this.getKind() |
result = k.toStringBuiltin(this.getArg(0).toString())
or
result = this.toStringConstructed(k.getConstructedSourceDeclaration())
)
}
@@ -366,7 +470,12 @@ module Gvn {
TArrayTypeKind(int dim, int rnk) {
exists(ArrayType at | dim = at.getDimension() and rnk = at.getRank())
} or
TConstructedType(UnboundGenericType ugt) { exists(ugt.getATypeParameter()) }
TConstructedType(GenericType sourceDecl) {
sourceDecl = any(GenericType t).getSourceDeclaration() and
not sourceDecl instanceof PointerType and
not sourceDecl instanceof NullableType and
not sourceDecl instanceof ArrayType
}
cached
newtype TGvnType =

View File

@@ -173,7 +173,7 @@ class InvalidFormatString extends StringLiteral {
}
/** Provides a dataflow configuration for format strings. */
private module FormatFlow {
module FormatFlow {
private import semmle.code.csharp.dataflow.DataFlow
private class FormatConfiguration extends DataFlow2::Configuration {
@@ -186,12 +186,21 @@ private module FormatFlow {
}
}
predicate hasFlow(StringLiteral lit, Expr format) {
exists(DataFlow::Node n1, DataFlow::Node n2, FormatConfiguration conf |
n1.asExpr() = lit and n2.asExpr() = format
|
conf.hasFlow(n1, n2)
)
query predicate nodes = DataFlow2::PathGraph::nodes/3;
query predicate edges = DataFlow2::PathGraph::edges/2;
class PathNode = DataFlow2::PathNode;
/**
* Holds if there is flow from string literal `lit` to the format string in
* `call`. `litNode` and `formatNode` are the corresponding data-flow path
* nodes.
*/
predicate hasFlowPath(StringLiteral lit, PathNode litNode, FormatCall call, PathNode formatNode) {
litNode.getNode().asExpr() = lit and
formatNode.getNode().asExpr() = call.getFormatExpr() and
any(FormatConfiguration conf).hasFlowPath(litNode, formatNode)
}
}
@@ -218,10 +227,12 @@ class FormatCall extends MethodCall {
}
/**
* DEPRECATED: Use `FormatFlow::hasFlowPath()` instead.
*
* Gets a format string. Global data flow analysis is applied to retrieve all
* sources that can reach this method call.
*/
StringLiteral getAFormatSource() { FormatFlow::hasFlow(result, this.getFormatExpr()) }
deprecated StringLiteral getAFormatSource() { FormatFlow::hasFlowPath(result, _, this, _) }
/**
* Gets the number of supplied arguments (excluding the format string and format
@@ -245,7 +256,7 @@ class FormatCall extends MethodCall {
/** Gets a supplied argument that is not used in the format string `src`. */
int getAnUnusedArgument(ValidFormatString src) {
result = this.getASuppliedArgument() and
src = this.getAFormatSource() and
FormatFlow::hasFlowPath(src, _, this, _) and
not result = src.getAnInsert()
}
}

View File

@@ -221,7 +221,9 @@ PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
result = TPositionalArgumentOperand(argIndex)
}
class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
abstract class ChiOperandTag extends MemoryOperandTag { }
class ChiTotalOperandTag extends ChiOperandTag, TChiTotalOperand {
final override string toString() { result = "ChiTotal" }
final override int getSortOrder() { result = 13 }
@@ -231,7 +233,7 @@ class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
ChiTotalOperandTag chiTotalOperand() { result = TChiTotalOperand() }
class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand {
class ChiPartialOperandTag extends ChiOperandTag, TChiPartialOperand {
final override string toString() { result = "ChiPartial" }
final override int getSortOrder() { result = 14 }

View File

@@ -14,12 +14,8 @@ private newtype TOperand =
not Construction::isInCycle(useInstr) and
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
useInstr.getOpcode().hasOperand(tag)
} or
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -27,6 +23,57 @@ private newtype TOperand =
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/**
* Base class for all register operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class RegisterOperandBase extends TRegisterOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the register operand with the specified parameters.
*/
private RegisterOperandBase registerOperand(
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
) {
result = TRegisterOperand(useInstr, tag, defInstr)
}
/**
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
* will eventually use for this purpose.
*/
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
result = TNonPhiMemoryOperand(useInstr, tag)
}
/**
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class PhiOperandBase extends TPhiOperand {
abstract string toString();
}
/**
* Returns the Phi operand with the specified parameters.
*/
private PhiOperandBase phiOperand(
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
@@ -165,8 +212,8 @@ class Operand extends TOperand {
*/
class MemoryOperand extends Operand {
MemoryOperand() {
this = TNonPhiMemoryOperand(_, _, _, _) or
this = TPhiOperand(_, _, _, _)
this instanceof NonPhiMemoryOperandBase or
this instanceof PhiOperandBase
}
/**
@@ -200,18 +247,15 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
this = TRegisterOperand(useInstr, tag, defInstr) or
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
this = registerOperand(useInstr, tag, _) or
this = nonPhiMemoryOperand(useInstr, tag)
}
final override Instruction getUse() { result = useInstr }
final override Instruction getAnyDef() { result = defInstr }
final override string getDumpLabel() { result = tag.getLabel() }
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -222,8 +266,15 @@ class NonPhiOperand extends Operand {
/**
* An operand that consumes a register (non-memory) result.
*/
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
override RegisterOperandTag tag;
Instruction defInstr;
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
@@ -231,13 +282,25 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
}
}
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
final override Overlap getDefinitionOverlap() { result = overlap }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() {
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
}
}
class TypedOperand extends NonPhiMemoryOperand {
@@ -254,8 +317,6 @@ class TypedOperand extends NonPhiMemoryOperand {
*/
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() { result = "Address" }
}
/**
@@ -264,8 +325,6 @@ class AddressOperand extends RegisterOperand {
*/
class BufferSizeOperand extends RegisterOperand {
override BufferSizeOperandTag tag;
override string toString() { result = "BufferSize" }
}
/**
@@ -274,8 +333,6 @@ class BufferSizeOperand extends RegisterOperand {
*/
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() { result = "Load" }
}
/**
@@ -283,8 +340,6 @@ class LoadOperand extends TypedOperand {
*/
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() { result = "StoreValue" }
}
/**
@@ -292,8 +347,6 @@ class StoreValueOperand extends RegisterOperand {
*/
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() { result = "Unary" }
}
/**
@@ -301,8 +354,6 @@ class UnaryOperand extends RegisterOperand {
*/
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() { result = "Left" }
}
/**
@@ -310,8 +361,6 @@ class LeftOperand extends RegisterOperand {
*/
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() { result = "Right" }
}
/**
@@ -319,8 +368,6 @@ class RightOperand extends RegisterOperand {
*/
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() { result = "Condition" }
}
/**
@@ -328,8 +375,6 @@ class ConditionOperand extends RegisterOperand {
*/
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() { result = "CallTarget" }
}
/**
@@ -347,8 +392,6 @@ class ArgumentOperand extends RegisterOperand {
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() { result = "ThisArgument" }
}
/**
@@ -356,34 +399,27 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() { result = argIndex }
final int getIndex() { result = tag.getArgIndex() }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override string toString() { result = "SideEffect" }
}
/**
* An operand of a `PhiInstruction`.
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() { result = "Phi" }
@@ -413,8 +449,6 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() { result = "ChiTotal" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
@@ -424,7 +458,5 @@ class ChiTotalOperand extends NonPhiMemoryOperand {
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() { result = "ChiPartial" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -14,12 +14,8 @@ private newtype TOperand =
not Construction::isInCycle(useInstr) and
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
useInstr.getOpcode().hasOperand(tag)
} or
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -27,6 +23,57 @@ private newtype TOperand =
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/**
* Base class for all register operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class RegisterOperandBase extends TRegisterOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the register operand with the specified parameters.
*/
private RegisterOperandBase registerOperand(
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
) {
result = TRegisterOperand(useInstr, tag, defInstr)
}
/**
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
* will eventually use for this purpose.
*/
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
result = TNonPhiMemoryOperand(useInstr, tag)
}
/**
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class PhiOperandBase extends TPhiOperand {
abstract string toString();
}
/**
* Returns the Phi operand with the specified parameters.
*/
private PhiOperandBase phiOperand(
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
@@ -165,8 +212,8 @@ class Operand extends TOperand {
*/
class MemoryOperand extends Operand {
MemoryOperand() {
this = TNonPhiMemoryOperand(_, _, _, _) or
this = TPhiOperand(_, _, _, _)
this instanceof NonPhiMemoryOperandBase or
this instanceof PhiOperandBase
}
/**
@@ -200,18 +247,15 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
this = TRegisterOperand(useInstr, tag, defInstr) or
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
this = registerOperand(useInstr, tag, _) or
this = nonPhiMemoryOperand(useInstr, tag)
}
final override Instruction getUse() { result = useInstr }
final override Instruction getAnyDef() { result = defInstr }
final override string getDumpLabel() { result = tag.getLabel() }
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -222,8 +266,15 @@ class NonPhiOperand extends Operand {
/**
* An operand that consumes a register (non-memory) result.
*/
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
override RegisterOperandTag tag;
Instruction defInstr;
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() { result = defInstr }
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
@@ -231,13 +282,25 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
}
}
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
final override Overlap getDefinitionOverlap() { result = overlap }
final override string toString() { result = tag.toString() }
final override Instruction getAnyDef() {
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
}
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
pragma[noinline]
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
}
}
class TypedOperand extends NonPhiMemoryOperand {
@@ -254,8 +317,6 @@ class TypedOperand extends NonPhiMemoryOperand {
*/
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() { result = "Address" }
}
/**
@@ -264,8 +325,6 @@ class AddressOperand extends RegisterOperand {
*/
class BufferSizeOperand extends RegisterOperand {
override BufferSizeOperandTag tag;
override string toString() { result = "BufferSize" }
}
/**
@@ -274,8 +333,6 @@ class BufferSizeOperand extends RegisterOperand {
*/
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() { result = "Load" }
}
/**
@@ -283,8 +340,6 @@ class LoadOperand extends TypedOperand {
*/
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() { result = "StoreValue" }
}
/**
@@ -292,8 +347,6 @@ class StoreValueOperand extends RegisterOperand {
*/
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() { result = "Unary" }
}
/**
@@ -301,8 +354,6 @@ class UnaryOperand extends RegisterOperand {
*/
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() { result = "Left" }
}
/**
@@ -310,8 +361,6 @@ class LeftOperand extends RegisterOperand {
*/
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() { result = "Right" }
}
/**
@@ -319,8 +368,6 @@ class RightOperand extends RegisterOperand {
*/
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() { result = "Condition" }
}
/**
@@ -328,8 +375,6 @@ class ConditionOperand extends RegisterOperand {
*/
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() { result = "CallTarget" }
}
/**
@@ -347,8 +392,6 @@ class ArgumentOperand extends RegisterOperand {
*/
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() { result = "ThisArgument" }
}
/**
@@ -356,34 +399,27 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() { result = argIndex }
final int getIndex() { result = tag.getArgIndex() }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override string toString() { result = "SideEffect" }
}
/**
* An operand of a `PhiInstruction`.
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() { result = "Phi" }
@@ -413,8 +449,6 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() { result = "ChiTotal" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
@@ -424,7 +458,5 @@ class ChiTotalOperand extends NonPhiMemoryOperand {
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() { result = "ChiPartial" }
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -32,17 +32,17 @@ edges
| Types.cs:74:9:74:9 | access to local variable d : D | Types.cs:16:30:16:30 | this : D |
| Types.cs:77:22:77:22 | a : C | Types.cs:79:18:79:25 | SSA def(b) : C |
| Types.cs:79:18:79:25 | SSA def(b) : C | Types.cs:80:18:80:18 | access to local variable b |
| Types.cs:90:22:90:22 | e : E2 | Types.cs:92:26:92:26 | access to parameter e : E2 |
| Types.cs:92:13:92:16 | [post] this access [Field] : E2 | Types.cs:93:13:93:16 | this access [Field] : E2 |
| Types.cs:92:26:92:26 | access to parameter e : E2 | Types.cs:92:13:92:16 | [post] this access [Field] : E2 |
| Types.cs:93:13:93:16 | this access [Field] : E2 | Types.cs:113:34:113:34 | this [Field] : E2 |
| Types.cs:110:25:110:32 | object creation of type E2 : E2 | Types.cs:90:22:90:22 | e : E2 |
| Types.cs:113:34:113:34 | this [Field] : E2 | Types.cs:115:22:115:25 | this access [Field] : E2 |
| Types.cs:115:22:115:25 | this access [Field] : E2 | Types.cs:115:22:115:31 | access to field Field |
| Types.cs:90:22:90:22 | e : Types.E<D>.E2 | Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 |
| Types.cs:92:13:92:16 | [post] this access [Field] : Types.E<D>.E2 | Types.cs:93:13:93:16 | this access [Field] : Types.E<D>.E2 |
| Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 | Types.cs:92:13:92:16 | [post] this access [Field] : Types.E<D>.E2 |
| Types.cs:93:13:93:16 | this access [Field] : Types.E<D>.E2 | Types.cs:113:34:113:34 | this [Field] : Types.E<D>.E2 |
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | Types.cs:90:22:90:22 | e : Types.E<D>.E2 |
| Types.cs:113:34:113:34 | this [Field] : Types.E<D>.E2 | Types.cs:115:22:115:25 | this access [Field] : Types.E<D>.E2 |
| Types.cs:115:22:115:25 | this access [Field] : Types.E<D>.E2 | Types.cs:115:22:115:31 | access to field Field |
| Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:122:30:122:30 | access to local variable a : A |
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | Types.cs:123:30:123:31 | access to local variable e2 : E2 |
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 |
| Types.cs:122:30:122:30 | access to local variable a : A | Types.cs:122:22:122:31 | call to method Through |
| Types.cs:123:30:123:31 | access to local variable e2 : E2 | Types.cs:123:22:123:32 | call to method Through |
| Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 | Types.cs:123:22:123:32 | call to method Through |
nodes
| Types.cs:7:21:7:25 | this : D | semmle.label | this : D |
| Types.cs:7:32:7:35 | this access : D | semmle.label | this access : D |
@@ -86,20 +86,20 @@ nodes
| Types.cs:77:22:77:22 | a : C | semmle.label | a : C |
| Types.cs:79:18:79:25 | SSA def(b) : C | semmle.label | SSA def(b) : C |
| Types.cs:80:18:80:18 | access to local variable b | semmle.label | access to local variable b |
| Types.cs:90:22:90:22 | e : E2 | semmle.label | e : E2 |
| Types.cs:92:13:92:16 | [post] this access [Field] : E2 | semmle.label | [post] this access [Field] : E2 |
| Types.cs:92:26:92:26 | access to parameter e : E2 | semmle.label | access to parameter e : E2 |
| Types.cs:93:13:93:16 | this access [Field] : E2 | semmle.label | this access [Field] : E2 |
| Types.cs:110:25:110:32 | object creation of type E2 : E2 | semmle.label | object creation of type E2 : E2 |
| Types.cs:113:34:113:34 | this [Field] : E2 | semmle.label | this [Field] : E2 |
| Types.cs:115:22:115:25 | this access [Field] : E2 | semmle.label | this access [Field] : E2 |
| Types.cs:90:22:90:22 | e : Types.E<D>.E2 | semmle.label | e : Types.E<D>.E2 |
| Types.cs:92:13:92:16 | [post] this access [Field] : Types.E<D>.E2 | semmle.label | [post] this access [Field] : Types.E<D>.E2 |
| Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 | semmle.label | access to parameter e : Types.E<D>.E2 |
| Types.cs:93:13:93:16 | this access [Field] : Types.E<D>.E2 | semmle.label | this access [Field] : Types.E<D>.E2 |
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | semmle.label | object creation of type E2 : Types.E<D>.E2 |
| Types.cs:113:34:113:34 | this [Field] : Types.E<D>.E2 | semmle.label | this [Field] : Types.E<D>.E2 |
| Types.cs:115:22:115:25 | this access [Field] : Types.E<D>.E2 | semmle.label | this access [Field] : Types.E<D>.E2 |
| Types.cs:115:22:115:31 | access to field Field | semmle.label | access to field Field |
| Types.cs:120:25:120:31 | object creation of type A : A | semmle.label | object creation of type A : A |
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | semmle.label | object creation of type E2 : E2 |
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | semmle.label | object creation of type E2 : Types.E<D>.E2 |
| Types.cs:122:22:122:31 | call to method Through | semmle.label | call to method Through |
| Types.cs:122:30:122:30 | access to local variable a : A | semmle.label | access to local variable a : A |
| Types.cs:123:22:123:32 | call to method Through | semmle.label | call to method Through |
| Types.cs:123:30:123:31 | access to local variable e2 : E2 | semmle.label | access to local variable e2 : E2 |
| Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 | semmle.label | access to local variable e2 : Types.E<D>.E2 |
#select
| Types.cs:23:12:23:18 | object creation of type C : C | Types.cs:50:18:50:18 | access to local variable c | Types.cs:50:18:50:18 | access to local variable c | $@ | Types.cs:50:18:50:18 | access to local variable c | access to local variable c |
| Types.cs:25:12:25:18 | object creation of type C : C | Types.cs:63:33:63:36 | (...) ... | Types.cs:63:33:63:36 | (...) ... | $@ | Types.cs:63:33:63:36 | (...) ... | (...) ... |
@@ -115,6 +115,6 @@ nodes
| Types.cs:39:12:39:18 | object creation of type D : D | Types.cs:69:52:69:52 | access to parameter x | Types.cs:69:52:69:52 | access to parameter x | $@ | Types.cs:69:52:69:52 | access to parameter x | access to parameter x |
| Types.cs:40:12:40:18 | object creation of type D : D | Types.cs:16:42:16:45 | this access | Types.cs:16:42:16:45 | this access | $@ | Types.cs:16:42:16:45 | this access | this access |
| Types.cs:43:20:43:23 | null : null | Types.cs:44:14:44:14 | access to local variable o | Types.cs:44:14:44:14 | access to local variable o | $@ | Types.cs:44:14:44:14 | access to local variable o | access to local variable o |
| Types.cs:110:25:110:32 | object creation of type E2 : E2 | Types.cs:115:22:115:31 | access to field Field | Types.cs:115:22:115:31 | access to field Field | $@ | Types.cs:115:22:115:31 | access to field Field | access to field Field |
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | Types.cs:115:22:115:31 | access to field Field | Types.cs:115:22:115:31 | access to field Field | $@ | Types.cs:115:22:115:31 | access to field Field | access to field Field |
| Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:122:22:122:31 | call to method Through | Types.cs:122:22:122:31 | call to method Through | $@ | Types.cs:122:22:122:31 | call to method Through | call to method Through |
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | Types.cs:123:22:123:32 | call to method Through | Types.cs:123:22:123:32 | call to method Through | $@ | Types.cs:123:22:123:32 | call to method Through | call to method Through |
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | Types.cs:123:22:123:32 | call to method Through | Types.cs:123:22:123:32 | call to method Through | $@ | Types.cs:123:22:123:32 | call to method Through | call to method Through |

View File

@@ -27,3 +27,4 @@
| overrides.cs:268:29:268:36 | Property | overrides.cs:216:13:216:20 | Property |
| overrides.cs:269:29:269:32 | Item | overrides.cs:217:13:217:16 | Item |
| overrides.cs:270:44:270:48 | Event | overrides.cs:218:28:218:32 | Event |
| overrides.cs:284:25:284:28 | M | overrides.cs:279:18:279:21 | M |

View File

@@ -9,3 +9,4 @@
| overrides.cs:249:22:249:25 | M | overrides.cs:247:11:247:12 | A6 | overrides.cs:162:11:162:14 | M | overrides.cs:160:22:160:26 | I2<Object[]> |
| overrides.cs:259:27:259:30 | M | overrides.cs:257:11:257:12 | A8 | overrides.cs:223:26:223:29 | M | overrides.cs:221:11:221:12 | A1 |
| overrides.cs:267:27:267:30 | M | overrides.cs:265:11:265:12 | A9 | overrides.cs:223:26:223:29 | M | overrides.cs:221:11:221:12 | A1 |
| overrides.cs:284:25:284:28 | M | overrides.cs:282:15:282:17 | A10 | overrides.cs:279:18:279:21 | M | overrides.cs:277:19:277:20 | I6 |

View File

@@ -47,3 +47,4 @@
| overrides.G2.M<S>(string, S) | overrides.G.M<S>(string, S) | overrides |
| overrides.G.M<S>(string, S) | overrides.I2<String>.M<S>(string, S) | implements |
| overrides.H<>.M<S>(TA, S) | overrides.I2<TA>.M<S>(TA, S) | implements |
| overrides.Outer<>.A10.M<T>(Inner) | overrides.Outer<>.I6.M<T>(Inner) | implements |

View File

@@ -269,6 +269,23 @@ namespace overrides
public override int this[int x] { get { return x; } } // overrides A2.Item
public override event EventHandler Event; // overrides A2.Event
}
class Outer<T>
{
class Inner { }
interface I6
{
void M<T>(Outer<T>.Inner x);
}
class A10
{
public void M<T>(Outer<T>.Inner x) { } // implements I6.M (via A11)
}
class A11 : A10, I6 { }
}
}
// semmle-extractor-options: /r:System.Dynamic.Runtime.dll /r:System.Linq.Expressions.dll

View File

@@ -1,6 +1,7 @@
interface I1 { }
struct S1 { } struct S2 { }
struct S1 { }
struct S2 { }
class C0 { }
class C1<T1> { }
@@ -31,3 +32,19 @@ class Tuples<T8, T9>
static (T8, T9) t4;
static (T8 a, T9 b) t5 = t4;
}
class Nested<T10>
{
class NestedA<T11> { }
class NestedB
{
public class NestedC<T12> { }
}
Nested<int>.NestedA<string> x1;
Nested<string>.NestedA<int> x2;
Nested<int>.NestedB x3;
Nested<string>.NestedB x4;
Nested<int>.NestedB.NestedC<bool> x5;
Nested<string>.NestedB.NestedC<decimal> x6;
}

View File

@@ -1,298 +1,378 @@
constrainedTypeParameterSubsumes
| Unification.cs:7:10:7:11 | T2 | Unification.cs:3:8:3:9 | S1 |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:3:22:3:23 | S2 |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:7:10:7:11 | T2 |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:11:25:11:27 | T6d |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:1:11:1:12 | I1 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:5:7:5:8 | C0 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<S1> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<S2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<C1<S1>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<C2<S1>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<C2<S2>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:10:8:11 | T3 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:9:7:9:12 | C4<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:9:7:9:12 | C4<C1<C0>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:9:10:9:11 | T4 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:10:7:10:12 | C5<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:10:7:10:12 | C5<C2<S1>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:10:10:10:11 | T5 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:7:11:28 | C6<,,,> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:7:11:28 | C6<C1<S1>,C2<S1>,C3<C2<S1>>,S1> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:7:11:28 | C6<C2<S2>,C2<S2>,C3<C2<S2>>,S2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:7:11:28 | C6<C2<S2>,Tm,C3<Tm>,S2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:10:11:12 | T6a |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:15:11:17 | T6b |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:20:11:22 | T6c |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:13:7:13:24 | ConstructSomeTypes |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:23:12:23:13 | Tm |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:26:7:26:20 | Tuples<,> |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:9:10:9:11 | T4 |
| Unification.cs:10:10:10:11 | T5 | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:10:10:10:11 | T5 | Unification.cs:10:10:10:11 | T5 |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<S1> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<S2> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:9:10:9:11 | T4 |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:10:10:10:11 | T5 |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:11:10:11:12 | T6a |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:11:15:11:17 | T6b |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:23:12:23:13 | Tm |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:10:10:10:11 | T5 |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:11:15:11:17 | T6b |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:23:12:23:13 | Tm |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<C1<S1>> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<C2<S1>> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<C2<S2>> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:11:20:11:22 | T6c |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:3:8:3:9 | S1 |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:3:22:3:23 | S2 |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:7:10:7:11 | T2 |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:11:25:11:27 | T6d |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:23:12:23:13 | Tm | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:23:12:23:13 | Tm | Unification.cs:23:12:23:13 | Tm |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:3:8:3:9 | S1 |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:4:8:4:9 | S2 |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:8:10:8:11 | T2 |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:12:25:12:27 | T6d |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:1:11:1:12 | I1 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:6:7:6:8 | C0 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<S1> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<S2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<C1<S1>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<C2<S1>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<C2<S2>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:10:9:11 | T3 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:10:7:10:12 | C4<C1<C0>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:10:7:10:12 | C4<T4> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:10:10:10:11 | T4 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:11:7:11:12 | C5<C2<S1>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:11:7:11:12 | C5<T5> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:11:10:11:11 | T5 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:7:12:28 | C6<C1<S1>, C2<S1>, C3<C2<S1>>, S1> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:7:12:28 | C6<C2<S2>, C2<S2>, C3<C2<S2>>, S2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:7:12:28 | C6<C2<S2>, Tm, C3<Tm>, S2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:10:12:12 | T6a |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:15:12:17 | T6b |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:20:12:22 | T6c |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:14:7:14:24 | ConstructSomeTypes |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:24:12:24:13 | Tm |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:27:7:27:20 | Tuples<T8, T9> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:36:7:36:17 | Nested<Int32> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:36:7:36:17 | Nested<String> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:36:7:36:17 | Nested<T10> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:39:11:39:17 | Nested<>.NestedB |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:39:11:39:17 | Nested<Int32>.NestedB |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:39:11:39:17 | Nested<String>.NestedB |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:10:10:10:11 | T4 |
| Unification.cs:11:10:11:11 | T5 | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:11:10:11:11 | T5 | Unification.cs:11:10:11:11 | T5 |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<S1> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<S2> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:10:10:10:11 | T4 |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:11:10:11:11 | T5 |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:12:10:12:12 | T6a |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:12:15:12:17 | T6b |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:24:12:24:13 | Tm |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:11:10:11:11 | T5 |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:12:15:12:17 | T6b |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:24:12:24:13 | Tm |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<C1<S1>> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<C2<S1>> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<C2<S2>> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:12:20:12:22 | T6c |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:3:8:3:9 | S1 |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:4:8:4:9 | S2 |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:8:10:8:11 | T2 |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:12:25:12:27 | T6d |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:24:12:24:13 | Tm | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:24:12:24:13 | Tm | Unification.cs:24:12:24:13 | Tm |
constrainedTypeParameterSubsumptionImpliesUnification
constrainedTypeParameterUnifiable
| Unification.cs:7:10:7:11 | T2 | Unification.cs:3:8:3:9 | S1 |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:3:22:3:23 | S2 |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:7:10:7:11 | T2 |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:11:25:11:27 | T6d |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:7:10:7:11 | T2 | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:1:11:1:12 | I1 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:5:7:5:8 | C0 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<S1> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<S2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<C1<S1>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<C2<S1>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<C2<S2>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:8:10:8:11 | T3 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:9:7:9:12 | C4<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:9:7:9:12 | C4<C1<C0>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:9:10:9:11 | T4 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:10:7:10:12 | C5<> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:10:7:10:12 | C5<C2<S1>> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:10:10:10:11 | T5 |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:7:11:28 | C6<,,,> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:7:11:28 | C6<C1<S1>,C2<S1>,C3<C2<S1>>,S1> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:7:11:28 | C6<C2<S2>,C2<S2>,C3<C2<S2>>,S2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:7:11:28 | C6<C2<S2>,Tm,C3<Tm>,S2> |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:10:11:12 | T6a |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:15:11:17 | T6b |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:11:20:11:22 | T6c |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:13:7:13:24 | ConstructSomeTypes |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:23:12:23:13 | Tm |
| Unification.cs:8:10:8:11 | T3 | Unification.cs:26:7:26:20 | Tuples<,> |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:9:10:9:11 | T4 |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:11:10:11:12 | T6a |
| Unification.cs:9:10:9:11 | T4 | Unification.cs:11:15:11:17 | T6b |
| Unification.cs:10:10:10:11 | T5 | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:10:10:10:11 | T5 | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:10:10:10:11 | T5 | Unification.cs:10:10:10:11 | T5 |
| Unification.cs:10:10:10:11 | T5 | Unification.cs:11:15:11:17 | T6b |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<S1> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<S2> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:9:10:9:11 | T4 |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:10:10:10:11 | T5 |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:11:10:11:12 | T6a |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:11:15:11:17 | T6b |
| Unification.cs:11:10:11:12 | T6a | Unification.cs:23:12:23:13 | Tm |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:10:10:10:11 | T5 |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:11:15:11:17 | T6b |
| Unification.cs:11:15:11:17 | T6b | Unification.cs:23:12:23:13 | Tm |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<C1<S1>> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<C2<S1>> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<C2<S2>> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:11:20:11:22 | T6c | Unification.cs:11:20:11:22 | T6c |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:3:8:3:9 | S1 |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:3:22:3:23 | S2 |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:7:10:7:11 | T2 |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:11:25:11:27 | T6d |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:11:25:11:27 | T6d | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:23:12:23:13 | Tm | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:23:12:23:13 | Tm | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:23:12:23:13 | Tm | Unification.cs:23:12:23:13 | Tm |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:3:8:3:9 | S1 |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:4:8:4:9 | S2 |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:8:10:8:11 | T2 |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:12:25:12:27 | T6d |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:8:10:8:11 | T2 | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:1:11:1:12 | I1 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:6:7:6:8 | C0 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<S1> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<S2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<C1<S1>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<C2<S1>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<C2<S2>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:9:10:9:11 | T3 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:10:7:10:12 | C4<C1<C0>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:10:7:10:12 | C4<T4> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:10:10:10:11 | T4 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:11:7:11:12 | C5<C2<S1>> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:11:7:11:12 | C5<T5> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:11:10:11:11 | T5 |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:7:12:28 | C6<C1<S1>, C2<S1>, C3<C2<S1>>, S1> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:7:12:28 | C6<C2<S2>, C2<S2>, C3<C2<S2>>, S2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:7:12:28 | C6<C2<S2>, Tm, C3<Tm>, S2> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:10:12:12 | T6a |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:15:12:17 | T6b |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:12:20:12:22 | T6c |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:14:7:14:24 | ConstructSomeTypes |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:24:12:24:13 | Tm |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:27:7:27:20 | Tuples<T8, T9> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:36:7:36:17 | Nested<Int32> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:36:7:36:17 | Nested<String> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:36:7:36:17 | Nested<T10> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:39:11:39:17 | Nested<>.NestedB |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:39:11:39:17 | Nested<Int32>.NestedB |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:39:11:39:17 | Nested<String>.NestedB |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> |
| Unification.cs:9:10:9:11 | T3 | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:10:10:10:11 | T4 |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:12:10:12:12 | T6a |
| Unification.cs:10:10:10:11 | T4 | Unification.cs:12:15:12:17 | T6b |
| Unification.cs:11:10:11:11 | T5 | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:11:10:11:11 | T5 | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:11:10:11:11 | T5 | Unification.cs:11:10:11:11 | T5 |
| Unification.cs:11:10:11:11 | T5 | Unification.cs:12:15:12:17 | T6b |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<S1> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<S2> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:10:10:10:11 | T4 |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:11:10:11:11 | T5 |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:12:10:12:12 | T6a |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:12:15:12:17 | T6b |
| Unification.cs:12:10:12:12 | T6a | Unification.cs:24:12:24:13 | Tm |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:11:10:11:11 | T5 |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:12:15:12:17 | T6b |
| Unification.cs:12:15:12:17 | T6b | Unification.cs:24:12:24:13 | Tm |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<C1<S1>> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<C2<S1>> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<C2<S2>> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:12:20:12:22 | T6c | Unification.cs:12:20:12:22 | T6c |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:3:8:3:9 | S1 |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:4:8:4:9 | S2 |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:8:10:8:11 | T2 |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:12:25:12:27 | T6d |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:12:25:12:27 | T6d | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:24:12:24:13 | Tm | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:24:12:24:13 | Tm | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:24:12:24:13 | Tm | Unification.cs:24:12:24:13 | Tm |
subsumes
| Unification.cs:6:7:6:12 | C1<> | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:6:7:6:12 | C1<> | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:6:7:6:12 | C1<> | Unification.cs:6:7:6:12 | C1<S1> |
| Unification.cs:6:7:6:12 | C1<> | Unification.cs:6:7:6:12 | C1<S2> |
| Unification.cs:6:7:6:12 | C1<> | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:6:7:6:12 | C1<> | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:6:7:6:12 | C1<C0> | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:6:7:6:12 | C1<S1> | Unification.cs:6:7:6:12 | C1<S1> |
| Unification.cs:6:7:6:12 | C1<S2> | Unification.cs:6:7:6:12 | C1<S2> |
| Unification.cs:6:7:6:12 | C1<T2> | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:6:7:6:12 | C1<T2> | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:6:7:6:12 | C1<T2> | Unification.cs:6:7:6:12 | C1<S1> |
| Unification.cs:6:7:6:12 | C1<T2> | Unification.cs:6:7:6:12 | C1<S2> |
| Unification.cs:6:7:6:12 | C1<T2> | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:6:7:6:12 | C1<T2> | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:6:7:6:12 | C1<T6d> | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:6:7:6:12 | C1<T6d> | Unification.cs:6:7:6:12 | C1<C0> |
| Unification.cs:6:7:6:12 | C1<T6d> | Unification.cs:6:7:6:12 | C1<S1> |
| Unification.cs:6:7:6:12 | C1<T6d> | Unification.cs:6:7:6:12 | C1<S2> |
| Unification.cs:6:7:6:12 | C1<T6d> | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:6:7:6:12 | C1<T6d> | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:7:7:7:12 | C2<> | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:7:7:7:12 | C2<> | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:7:7:7:12 | C2<> | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:7:7:7:12 | C2<S1> | Unification.cs:7:7:7:12 | C2<S1> |
| Unification.cs:7:7:7:12 | C2<S2> | Unification.cs:7:7:7:12 | C2<S2> |
| Unification.cs:8:7:8:12 | C3<> | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:8:7:8:12 | C3<> | Unification.cs:8:7:8:12 | C3<C1<S1>> |
| Unification.cs:8:7:8:12 | C3<> | Unification.cs:8:7:8:12 | C3<C2<S1>> |
| Unification.cs:8:7:8:12 | C3<> | Unification.cs:8:7:8:12 | C3<C2<S2>> |
| Unification.cs:8:7:8:12 | C3<> | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:8:7:8:12 | C3<> | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:8:7:8:12 | C3<C1<S1>> | Unification.cs:8:7:8:12 | C3<C1<S1>> |
| Unification.cs:8:7:8:12 | C3<C2<S1>> | Unification.cs:8:7:8:12 | C3<C2<S1>> |
| Unification.cs:8:7:8:12 | C3<C2<S2>> | Unification.cs:8:7:8:12 | C3<C2<S2>> |
| Unification.cs:8:7:8:12 | C3<T6b> | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:8:7:8:12 | C3<T6b> | Unification.cs:8:7:8:12 | C3<C1<S1>> |
| Unification.cs:8:7:8:12 | C3<T6b> | Unification.cs:8:7:8:12 | C3<C2<S1>> |
| Unification.cs:8:7:8:12 | C3<T6b> | Unification.cs:8:7:8:12 | C3<C2<S2>> |
| Unification.cs:8:7:8:12 | C3<T6b> | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:8:7:8:12 | C3<T6b> | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:8:7:8:12 | C3<Tm> | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:8:7:8:12 | C3<Tm> | Unification.cs:8:7:8:12 | C3<C1<S1>> |
| Unification.cs:8:7:8:12 | C3<Tm> | Unification.cs:8:7:8:12 | C3<C2<S1>> |
| Unification.cs:8:7:8:12 | C3<Tm> | Unification.cs:8:7:8:12 | C3<C2<S2>> |
| Unification.cs:8:7:8:12 | C3<Tm> | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:8:7:8:12 | C3<Tm> | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:9:7:9:12 | C4<> | Unification.cs:9:7:9:12 | C4<> |
| Unification.cs:9:7:9:12 | C4<> | Unification.cs:9:7:9:12 | C4<C1<C0>> |
| Unification.cs:9:7:9:12 | C4<C1<C0>> | Unification.cs:9:7:9:12 | C4<C1<C0>> |
| Unification.cs:10:7:10:12 | C5<> | Unification.cs:10:7:10:12 | C5<> |
| Unification.cs:10:7:10:12 | C5<> | Unification.cs:10:7:10:12 | C5<C2<S1>> |
| Unification.cs:10:7:10:12 | C5<C2<S1>> | Unification.cs:10:7:10:12 | C5<C2<S1>> |
| Unification.cs:11:7:11:28 | C6<,,,> | Unification.cs:11:7:11:28 | C6<,,,> |
| Unification.cs:11:7:11:28 | C6<,,,> | Unification.cs:11:7:11:28 | C6<C1<S1>,C2<S1>,C3<C2<S1>>,S1> |
| Unification.cs:11:7:11:28 | C6<,,,> | Unification.cs:11:7:11:28 | C6<C2<S2>,C2<S2>,C3<C2<S2>>,S2> |
| Unification.cs:11:7:11:28 | C6<,,,> | Unification.cs:11:7:11:28 | C6<C2<S2>,Tm,C3<Tm>,S2> |
| Unification.cs:11:7:11:28 | C6<C1<S1>,C2<S1>,C3<C2<S1>>,S1> | Unification.cs:11:7:11:28 | C6<C1<S1>,C2<S1>,C3<C2<S1>>,S1> |
| Unification.cs:11:7:11:28 | C6<C2<S2>,C2<S2>,C3<C2<S2>>,S2> | Unification.cs:11:7:11:28 | C6<C2<S2>,C2<S2>,C3<C2<S2>>,S2> |
| Unification.cs:11:7:11:28 | C6<C2<S2>,Tm,C3<Tm>,S2> | Unification.cs:11:7:11:28 | C6<C2<S2>,C2<S2>,C3<C2<S2>>,S2> |
| Unification.cs:11:7:11:28 | C6<C2<S2>,Tm,C3<Tm>,S2> | Unification.cs:11:7:11:28 | C6<C2<S2>,Tm,C3<Tm>,S2> |
| Unification.cs:26:7:26:20 | Tuples<,> | Unification.cs:26:7:26:20 | Tuples<,> |
| Unification.cs:28:12:28:20 | (T8,Int32) | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:28:12:28:20 | (T8,Int32) | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:29:12:29:24 | (String,Int32) | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:30:12:30:23 | (String,T9) | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:30:12:30:23 | (String,T9) | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:31:12:31:19 | (T8,T9) | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:31:12:31:19 | (T8,T9) | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:31:12:31:19 | (T8,T9) | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:31:12:31:19 | (T8,T9) | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:31:12:31:19 | (T8,T9) | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:32:12:32:23 | (T8,T9) | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:32:12:32:23 | (T8,T9) | Unification.cs:29:12:29:24 | (String,Int32) |
| Unification.cs:32:12:32:23 | (T8,T9) | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:32:12:32:23 | (T8,T9) | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:32:12:32:23 | (T8,T9) | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:7:7:7:12 | C1<C0> | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:7:7:7:12 | C1<S1> | Unification.cs:7:7:7:12 | C1<S1> |
| Unification.cs:7:7:7:12 | C1<S2> | Unification.cs:7:7:7:12 | C1<S2> |
| Unification.cs:7:7:7:12 | C1<T1> | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:7:7:7:12 | C1<T1> | Unification.cs:7:7:7:12 | C1<S1> |
| Unification.cs:7:7:7:12 | C1<T1> | Unification.cs:7:7:7:12 | C1<S2> |
| Unification.cs:7:7:7:12 | C1<T1> | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:7:7:7:12 | C1<T1> | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:7:7:7:12 | C1<T1> | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:7:7:7:12 | C1<T2> | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:7:7:7:12 | C1<T2> | Unification.cs:7:7:7:12 | C1<S1> |
| Unification.cs:7:7:7:12 | C1<T2> | Unification.cs:7:7:7:12 | C1<S2> |
| Unification.cs:7:7:7:12 | C1<T2> | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:7:7:7:12 | C1<T2> | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:7:7:7:12 | C1<T2> | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:7:7:7:12 | C1<T6d> | Unification.cs:7:7:7:12 | C1<C0> |
| Unification.cs:7:7:7:12 | C1<T6d> | Unification.cs:7:7:7:12 | C1<S1> |
| Unification.cs:7:7:7:12 | C1<T6d> | Unification.cs:7:7:7:12 | C1<S2> |
| Unification.cs:7:7:7:12 | C1<T6d> | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:7:7:7:12 | C1<T6d> | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:7:7:7:12 | C1<T6d> | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:8:7:8:12 | C2<S1> | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:8:7:8:12 | C2<S2> | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:8:7:8:12 | C2<T2> | Unification.cs:8:7:8:12 | C2<S1> |
| Unification.cs:8:7:8:12 | C2<T2> | Unification.cs:8:7:8:12 | C2<S2> |
| Unification.cs:8:7:8:12 | C2<T2> | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:9:7:9:12 | C3<C1<S1>> | Unification.cs:9:7:9:12 | C3<C1<S1>> |
| Unification.cs:9:7:9:12 | C3<C2<S1>> | Unification.cs:9:7:9:12 | C3<C2<S1>> |
| Unification.cs:9:7:9:12 | C3<C2<S2>> | Unification.cs:9:7:9:12 | C3<C2<S2>> |
| Unification.cs:9:7:9:12 | C3<T3> | Unification.cs:9:7:9:12 | C3<C1<S1>> |
| Unification.cs:9:7:9:12 | C3<T3> | Unification.cs:9:7:9:12 | C3<C2<S1>> |
| Unification.cs:9:7:9:12 | C3<T3> | Unification.cs:9:7:9:12 | C3<C2<S2>> |
| Unification.cs:9:7:9:12 | C3<T3> | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:9:7:9:12 | C3<T3> | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:9:7:9:12 | C3<T3> | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:9:7:9:12 | C3<T6b> | Unification.cs:9:7:9:12 | C3<C1<S1>> |
| Unification.cs:9:7:9:12 | C3<T6b> | Unification.cs:9:7:9:12 | C3<C2<S1>> |
| Unification.cs:9:7:9:12 | C3<T6b> | Unification.cs:9:7:9:12 | C3<C2<S2>> |
| Unification.cs:9:7:9:12 | C3<T6b> | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:9:7:9:12 | C3<T6b> | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:9:7:9:12 | C3<T6b> | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:9:7:9:12 | C3<Tm> | Unification.cs:9:7:9:12 | C3<C1<S1>> |
| Unification.cs:9:7:9:12 | C3<Tm> | Unification.cs:9:7:9:12 | C3<C2<S1>> |
| Unification.cs:9:7:9:12 | C3<Tm> | Unification.cs:9:7:9:12 | C3<C2<S2>> |
| Unification.cs:9:7:9:12 | C3<Tm> | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:9:7:9:12 | C3<Tm> | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:9:7:9:12 | C3<Tm> | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:10:7:10:12 | C4<C1<C0>> | Unification.cs:10:7:10:12 | C4<C1<C0>> |
| Unification.cs:10:7:10:12 | C4<T4> | Unification.cs:10:7:10:12 | C4<C1<C0>> |
| Unification.cs:10:7:10:12 | C4<T4> | Unification.cs:10:7:10:12 | C4<T4> |
| Unification.cs:11:7:11:12 | C5<C2<S1>> | Unification.cs:11:7:11:12 | C5<C2<S1>> |
| Unification.cs:11:7:11:12 | C5<T5> | Unification.cs:11:7:11:12 | C5<C2<S1>> |
| Unification.cs:11:7:11:12 | C5<T5> | Unification.cs:11:7:11:12 | C5<T5> |
| Unification.cs:12:7:12:28 | C6<C1<S1>, C2<S1>, C3<C2<S1>>, S1> | Unification.cs:12:7:12:28 | C6<C1<S1>, C2<S1>, C3<C2<S1>>, S1> |
| Unification.cs:12:7:12:28 | C6<C2<S2>, C2<S2>, C3<C2<S2>>, S2> | Unification.cs:12:7:12:28 | C6<C2<S2>, C2<S2>, C3<C2<S2>>, S2> |
| Unification.cs:12:7:12:28 | C6<C2<S2>, Tm, C3<Tm>, S2> | Unification.cs:12:7:12:28 | C6<C2<S2>, C2<S2>, C3<C2<S2>>, S2> |
| Unification.cs:12:7:12:28 | C6<C2<S2>, Tm, C3<Tm>, S2> | Unification.cs:12:7:12:28 | C6<C2<S2>, Tm, C3<Tm>, S2> |
| Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> | Unification.cs:12:7:12:28 | C6<C1<S1>, C2<S1>, C3<C2<S1>>, S1> |
| Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> | Unification.cs:12:7:12:28 | C6<C2<S2>, C2<S2>, C3<C2<S2>>, S2> |
| Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> | Unification.cs:12:7:12:28 | C6<C2<S2>, Tm, C3<Tm>, S2> |
| Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> | Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> |
| Unification.cs:27:7:27:20 | Tuples<T8, T9> | Unification.cs:27:7:27:20 | Tuples<T8, T9> |
| Unification.cs:29:12:29:20 | (T8, int) | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:29:12:29:20 | (T8, int) | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:30:12:30:24 | (string, int) | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:31:12:31:23 | (string, T9) | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:31:12:31:23 | (string, T9) | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:32:12:32:19 | (T8, T9) | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:32:12:32:19 | (T8, T9) | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:32:12:32:19 | (T8, T9) | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:32:12:32:19 | (T8, T9) | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:32:12:32:19 | (T8, T9) | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:33:12:33:23 | (T8, T9) | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:33:12:33:23 | (T8, T9) | Unification.cs:30:12:30:24 | (string, int) |
| Unification.cs:33:12:33:23 | (T8, T9) | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:33:12:33:23 | (T8, T9) | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:33:12:33:23 | (T8, T9) | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:36:7:36:17 | Nested<Int32> | Unification.cs:36:7:36:17 | Nested<Int32> |
| Unification.cs:36:7:36:17 | Nested<String> | Unification.cs:36:7:36:17 | Nested<String> |
| Unification.cs:36:7:36:17 | Nested<T10> | Unification.cs:36:7:36:17 | Nested<Int32> |
| Unification.cs:36:7:36:17 | Nested<T10> | Unification.cs:36:7:36:17 | Nested<String> |
| Unification.cs:36:7:36:17 | Nested<T10> | Unification.cs:36:7:36:17 | Nested<T10> |
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> |
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> |
| Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> |
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> |
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> |
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> |
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> |
| Unification.cs:39:11:39:17 | Nested<>.NestedB | Unification.cs:39:11:39:17 | Nested<>.NestedB |
| Unification.cs:39:11:39:17 | Nested<>.NestedB | Unification.cs:39:11:39:17 | Nested<Int32>.NestedB |
| Unification.cs:39:11:39:17 | Nested<>.NestedB | Unification.cs:39:11:39:17 | Nested<String>.NestedB |
| Unification.cs:39:11:39:17 | Nested<Int32>.NestedB | Unification.cs:39:11:39:17 | Nested<Int32>.NestedB |
| Unification.cs:39:11:39:17 | Nested<String>.NestedB | Unification.cs:39:11:39:17 | Nested<String>.NestedB |
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> |
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> |
| Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> |
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> |
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> |
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> |
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> |
subsumptionImpliesUnification
unifiable
| Unification.cs:6:7:6:12 | C1<C0> | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:6:7:6:12 | C1<C0> | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:6:7:6:12 | C1<C0> | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:6:7:6:12 | C1<S1> | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:6:7:6:12 | C1<S1> | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:6:7:6:12 | C1<S1> | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:6:7:6:12 | C1<S2> | Unification.cs:6:7:6:12 | C1<> |
| Unification.cs:6:7:6:12 | C1<S2> | Unification.cs:6:7:6:12 | C1<T2> |
| Unification.cs:6:7:6:12 | C1<S2> | Unification.cs:6:7:6:12 | C1<T6d> |
| Unification.cs:7:7:7:12 | C2<S1> | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:7:7:7:12 | C2<S2> | Unification.cs:7:7:7:12 | C2<> |
| Unification.cs:8:7:8:12 | C3<C1<S1>> | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:8:7:8:12 | C3<C1<S1>> | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:8:7:8:12 | C3<C1<S1>> | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:8:7:8:12 | C3<C2<S1>> | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:8:7:8:12 | C3<C2<S1>> | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:8:7:8:12 | C3<C2<S1>> | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:8:7:8:12 | C3<C2<S2>> | Unification.cs:8:7:8:12 | C3<> |
| Unification.cs:8:7:8:12 | C3<C2<S2>> | Unification.cs:8:7:8:12 | C3<T6b> |
| Unification.cs:8:7:8:12 | C3<C2<S2>> | Unification.cs:8:7:8:12 | C3<Tm> |
| Unification.cs:9:7:9:12 | C4<C1<C0>> | Unification.cs:9:7:9:12 | C4<> |
| Unification.cs:10:7:10:12 | C5<C2<S1>> | Unification.cs:10:7:10:12 | C5<> |
| Unification.cs:11:7:11:28 | C6<C1<S1>,C2<S1>,C3<C2<S1>>,S1> | Unification.cs:11:7:11:28 | C6<,,,> |
| Unification.cs:11:7:11:28 | C6<C2<S2>,C2<S2>,C3<C2<S2>>,S2> | Unification.cs:11:7:11:28 | C6<,,,> |
| Unification.cs:11:7:11:28 | C6<C2<S2>,C2<S2>,C3<C2<S2>>,S2> | Unification.cs:11:7:11:28 | C6<C2<S2>,Tm,C3<Tm>,S2> |
| Unification.cs:11:7:11:28 | C6<C2<S2>,Tm,C3<Tm>,S2> | Unification.cs:11:7:11:28 | C6<,,,> |
| Unification.cs:28:12:28:20 | (T8,Int32) | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:28:12:28:20 | (T8,Int32) | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:28:12:28:20 | (T8,Int32) | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:29:12:29:24 | (String,Int32) | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:29:12:29:24 | (String,Int32) | Unification.cs:30:12:30:23 | (String,T9) |
| Unification.cs:29:12:29:24 | (String,Int32) | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:29:12:29:24 | (String,Int32) | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:30:12:30:23 | (String,T9) | Unification.cs:28:12:28:20 | (T8,Int32) |
| Unification.cs:30:12:30:23 | (String,T9) | Unification.cs:31:12:31:19 | (T8,T9) |
| Unification.cs:30:12:30:23 | (String,T9) | Unification.cs:32:12:32:23 | (T8,T9) |
| Unification.cs:7:7:7:12 | C1<C0> | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:7:7:7:12 | C1<C0> | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:7:7:7:12 | C1<C0> | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:7:7:7:12 | C1<S1> | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:7:7:7:12 | C1<S1> | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:7:7:7:12 | C1<S1> | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:7:7:7:12 | C1<S2> | Unification.cs:7:7:7:12 | C1<T1> |
| Unification.cs:7:7:7:12 | C1<S2> | Unification.cs:7:7:7:12 | C1<T2> |
| Unification.cs:7:7:7:12 | C1<S2> | Unification.cs:7:7:7:12 | C1<T6d> |
| Unification.cs:8:7:8:12 | C2<S1> | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:8:7:8:12 | C2<S2> | Unification.cs:8:7:8:12 | C2<T2> |
| Unification.cs:9:7:9:12 | C3<C1<S1>> | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:9:7:9:12 | C3<C1<S1>> | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:9:7:9:12 | C3<C1<S1>> | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:9:7:9:12 | C3<C2<S1>> | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:9:7:9:12 | C3<C2<S1>> | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:9:7:9:12 | C3<C2<S1>> | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:9:7:9:12 | C3<C2<S2>> | Unification.cs:9:7:9:12 | C3<T3> |
| Unification.cs:9:7:9:12 | C3<C2<S2>> | Unification.cs:9:7:9:12 | C3<T6b> |
| Unification.cs:9:7:9:12 | C3<C2<S2>> | Unification.cs:9:7:9:12 | C3<Tm> |
| Unification.cs:10:7:10:12 | C4<C1<C0>> | Unification.cs:10:7:10:12 | C4<T4> |
| Unification.cs:11:7:11:12 | C5<C2<S1>> | Unification.cs:11:7:11:12 | C5<T5> |
| Unification.cs:12:7:12:28 | C6<C1<S1>, C2<S1>, C3<C2<S1>>, S1> | Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> |
| Unification.cs:12:7:12:28 | C6<C2<S2>, C2<S2>, C3<C2<S2>>, S2> | Unification.cs:12:7:12:28 | C6<C2<S2>, Tm, C3<Tm>, S2> |
| Unification.cs:12:7:12:28 | C6<C2<S2>, C2<S2>, C3<C2<S2>>, S2> | Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> |
| Unification.cs:12:7:12:28 | C6<C2<S2>, Tm, C3<Tm>, S2> | Unification.cs:12:7:12:28 | C6<T6a, T6b, T6c, T6d> |
| Unification.cs:29:12:29:20 | (T8, int) | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:29:12:29:20 | (T8, int) | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:29:12:29:20 | (T8, int) | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:30:12:30:24 | (string, int) | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:30:12:30:24 | (string, int) | Unification.cs:31:12:31:23 | (string, T9) |
| Unification.cs:30:12:30:24 | (string, int) | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:30:12:30:24 | (string, int) | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:31:12:31:23 | (string, T9) | Unification.cs:29:12:29:20 | (T8, int) |
| Unification.cs:31:12:31:23 | (string, T9) | Unification.cs:32:12:32:19 | (T8, T9) |
| Unification.cs:31:12:31:23 | (string, T9) | Unification.cs:33:12:33:23 | (T8, T9) |
| Unification.cs:36:7:36:17 | Nested<Int32> | Unification.cs:36:7:36:17 | Nested<T10> |
| Unification.cs:36:7:36:17 | Nested<String> | Unification.cs:36:7:36:17 | Nested<T10> |
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<String> | Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<Int32>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<Int32> | Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> |
| Unification.cs:38:11:38:22 | Nested<String>.NestedA<T11> | Unification.cs:38:11:38:22 | Nested<>.NestedA<T11> |
| Unification.cs:39:11:39:17 | Nested<Int32>.NestedB | Unification.cs:39:11:39:17 | Nested<>.NestedB |
| Unification.cs:39:11:39:17 | Nested<String>.NestedB | Unification.cs:39:11:39:17 | Nested<>.NestedB |
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<Boolean> | Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<Int32>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<Decimal> | Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> |
| Unification.cs:41:22:41:33 | Nested<String>.NestedB.NestedC<T12> | Unification.cs:41:22:41:33 | Nested<>.NestedB.NestedC<T12> |

View File

@@ -1,10 +1,19 @@
import semmle.code.csharp.Unification
class InterestingType extends Type {
class InterestingType extends @type {
InterestingType() {
this.fromSource() or
this.(Type).fromSource() or
this.(TupleType).getAChild() instanceof InterestingType
}
string toString() {
result = this.(Type).getQualifiedNameWithTypes()
or
not exists(this.(Type).getQualifiedNameWithTypes()) and
result = this.(Type).toStringWithTypes()
}
Location getLocation() { result = this.(Type).getLocation() }
}
query predicate constrainedTypeParameterSubsumes(InterestingType tp, InterestingType t) {
@@ -12,9 +21,7 @@ query predicate constrainedTypeParameterSubsumes(InterestingType tp, Interesting
}
// Should be empty
query predicate constrainedTypeParameterSubsumptionImpliesUnification(
InterestingType tp, InterestingType t
) {
query predicate constrainedTypeParameterSubsumptionImpliesUnification(Type tp, Type t) {
tp.(Unification::ConstrainedTypeParameter).subsumes(t) and
not tp.(Unification::ConstrainedTypeParameter).unifiable(t)
}

View File

@@ -1,42 +1,99 @@
| FormatInvalid.cs:27:24:27:28 | "{ 0}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:27:9:27:32 | call to method Format | this |
| FormatInvalid.cs:30:24:30:31 | "{0,--1}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:30:9:30:35 | call to method Format | this |
| FormatInvalid.cs:33:24:33:30 | "{0:{}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:33:9:33:34 | call to method Format | this |
| FormatInvalid.cs:39:27:39:33 | "{{0}-{1}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:39:9:39:40 | call to method Format | this |
| FormatInvalid.cs:42:27:42:28 | "{0}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:42:9:42:35 | call to method Format | this |
| FormatInvalid.cs:45:24:45:32 | "{foo{0}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:45:9:45:36 | call to method Format | this |
| FormatInvalid.cs:51:24:51:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:51:9:51:29 | call to method Format | this |
| FormatInvalid.cs:75:24:75:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:75:9:75:29 | call to method Format | this |
| FormatInvalid.cs:76:24:76:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:76:9:76:30 | call to method Format | this |
| FormatInvalid.cs:77:28:77:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:77:9:77:34 | call to method Format | this |
| FormatInvalid.cs:78:24:78:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:78:9:78:32 | call to method Format | this |
| FormatInvalid.cs:79:24:79:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:79:9:79:35 | call to method Format | this |
| FormatInvalid.cs:80:24:80:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:80:9:80:38 | call to method Format | this |
| FormatInvalid.cs:82:26:82:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:82:9:82:31 | call to method AppendFormat | this |
| FormatInvalid.cs:83:26:83:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:83:9:83:32 | call to method AppendFormat | this |
| FormatInvalid.cs:84:30:84:31 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:84:9:84:36 | call to method AppendFormat | this |
| FormatInvalid.cs:85:26:85:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:85:9:85:34 | call to method AppendFormat | this |
| FormatInvalid.cs:86:26:86:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:86:9:86:37 | call to method AppendFormat | this |
| FormatInvalid.cs:87:26:87:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:87:9:87:40 | call to method AppendFormat | this |
| FormatInvalid.cs:89:28:89:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:89:9:89:33 | call to method WriteLine | this |
| FormatInvalid.cs:90:28:90:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:90:9:90:34 | call to method WriteLine | this |
| FormatInvalid.cs:91:28:91:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:91:9:91:36 | call to method WriteLine | this |
| FormatInvalid.cs:92:28:92:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:92:9:92:39 | call to method WriteLine | this |
| FormatInvalid.cs:93:28:93:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:93:9:93:42 | call to method WriteLine | this |
| FormatInvalid.cs:95:23:95:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:95:9:95:28 | call to method WriteLine | this |
| FormatInvalid.cs:96:23:96:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:96:9:96:29 | call to method WriteLine | this |
| FormatInvalid.cs:97:23:97:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:97:9:97:31 | call to method WriteLine | this |
| FormatInvalid.cs:98:23:98:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:98:9:98:34 | call to method WriteLine | this |
| FormatInvalid.cs:99:23:99:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:99:9:99:37 | call to method WriteLine | this |
| FormatInvalid.cs:101:45:101:46 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:101:9:101:51 | call to method WriteLine | this |
| FormatInvalid.cs:102:46:102:47 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:102:9:102:51 | call to method TraceError | this |
| FormatInvalid.cs:103:52:103:53 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:103:9:103:57 | call to method TraceInformation | this |
| FormatInvalid.cs:104:48:104:49 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:104:9:104:53 | call to method TraceWarning | this |
| FormatInvalid.cs:105:30:105:31 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:105:9:105:35 | call to method TraceInformation | this |
| FormatInvalid.cs:107:24:107:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:107:9:107:29 | call to method Write | this |
| FormatInvalid.cs:108:24:108:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:108:9:108:32 | call to method Write | this |
| FormatInvalid.cs:109:24:109:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:109:9:109:35 | call to method Write | this |
| FormatInvalid.cs:110:24:110:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:110:9:110:38 | call to method Write | this |
| FormatInvalid.cs:115:57:115:58 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:115:9:115:63 | call to method Assert | this |
| FormatInvalid.cs:116:19:116:20 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:116:9:116:24 | call to method Write | this |
| FormatInvalid.cs:117:41:117:42 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:117:9:117:47 | call to method Print | this |
| FormatInvalidBad.cs:7:41:7:44 | "class {0} { }" | Invalid format string used in $@ formatting call. | FormatInvalidBad.cs:7:16:7:45 | call to method Format | this |
nodes
| FormatInvalid.cs:9:23:9:27 | "{0}" | semmle.label | "{0}" |
| FormatInvalid.cs:12:23:12:29 | "{0,1}" | semmle.label | "{0,1}" |
| FormatInvalid.cs:15:23:15:31 | "{0, 1}" | semmle.label | "{0, 1}" |
| FormatInvalid.cs:18:23:18:30 | "{0,-1}" | semmle.label | "{0,-1}" |
| FormatInvalid.cs:21:23:21:33 | "{0:0.000}" | semmle.label | "{0:0.000}" |
| FormatInvalid.cs:24:23:24:39 | "{0, -10 :0.000}" | semmle.label | "{0, -10 :0.000}" |
| FormatInvalid.cs:27:23:27:28 | "{ 0}" | semmle.label | "{ 0}" |
| FormatInvalid.cs:30:23:30:31 | "{0,--1}" | semmle.label | "{0,--1}" |
| FormatInvalid.cs:33:23:33:30 | "{0:{}}" | semmle.label | "{0:{}}" |
| FormatInvalid.cs:36:23:36:26 | "%d" | semmle.label | "%d" |
| FormatInvalid.cs:39:23:39:33 | "{{0}-{1}}" | semmle.label | "{{0}-{1}}" |
| FormatInvalid.cs:42:23:42:28 | "{0}}" | semmle.label | "{0}}" |
| FormatInvalid.cs:45:23:45:32 | "{foo{0}}" | semmle.label | "{foo{0}}" |
| FormatInvalid.cs:48:23:48:31 | "{{sdc}}" | semmle.label | "{{sdc}}" |
| FormatInvalid.cs:51:23:51:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:54:23:54:42 | "new {0} ({1} => {{" | semmle.label | "new {0} ({1} => {{" |
| FormatInvalid.cs:57:23:57:26 | "{{" | semmle.label | "{{" |
| FormatInvalid.cs:58:23:58:30 | "{{{{}}" | semmle.label | "{{{{}}" |
| FormatInvalid.cs:75:23:75:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:76:23:76:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:77:27:77:29 | "}" | semmle.label | "}" |
| FormatInvalid.cs:78:23:78:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:79:23:79:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:80:23:80:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:82:25:82:27 | "}" | semmle.label | "}" |
| FormatInvalid.cs:83:25:83:27 | "}" | semmle.label | "}" |
| FormatInvalid.cs:84:29:84:31 | "}" | semmle.label | "}" |
| FormatInvalid.cs:85:25:85:27 | "}" | semmle.label | "}" |
| FormatInvalid.cs:86:25:86:27 | "}" | semmle.label | "}" |
| FormatInvalid.cs:87:25:87:27 | "}" | semmle.label | "}" |
| FormatInvalid.cs:89:27:89:29 | "}" | semmle.label | "}" |
| FormatInvalid.cs:90:27:90:29 | "}" | semmle.label | "}" |
| FormatInvalid.cs:91:27:91:29 | "}" | semmle.label | "}" |
| FormatInvalid.cs:92:27:92:29 | "}" | semmle.label | "}" |
| FormatInvalid.cs:93:27:93:29 | "}" | semmle.label | "}" |
| FormatInvalid.cs:95:22:95:24 | "}" | semmle.label | "}" |
| FormatInvalid.cs:96:22:96:24 | "}" | semmle.label | "}" |
| FormatInvalid.cs:97:22:97:24 | "}" | semmle.label | "}" |
| FormatInvalid.cs:98:22:98:24 | "}" | semmle.label | "}" |
| FormatInvalid.cs:99:22:99:24 | "}" | semmle.label | "}" |
| FormatInvalid.cs:101:44:101:46 | "}" | semmle.label | "}" |
| FormatInvalid.cs:102:45:102:47 | "}" | semmle.label | "}" |
| FormatInvalid.cs:103:51:103:53 | "}" | semmle.label | "}" |
| FormatInvalid.cs:104:47:104:49 | "}" | semmle.label | "}" |
| FormatInvalid.cs:105:29:105:31 | "}" | semmle.label | "}" |
| FormatInvalid.cs:107:23:107:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:108:23:108:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:109:23:109:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:110:23:110:25 | "}" | semmle.label | "}" |
| FormatInvalid.cs:115:56:115:58 | "}" | semmle.label | "}" |
| FormatInvalid.cs:116:18:116:20 | "}" | semmle.label | "}" |
| FormatInvalid.cs:117:40:117:42 | "}" | semmle.label | "}" |
| FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | semmle.label | "class {0} { }" |
| FormatInvalidGood.cs:7:30:7:46 | "class {0} {{ }}" | semmle.label | "class {0} {{ }}" |
edges
#select
| FormatInvalid.cs:27:24:27:28 | "{ 0}" | FormatInvalid.cs:27:23:27:28 | "{ 0}" | FormatInvalid.cs:27:23:27:28 | "{ 0}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:27:9:27:32 | call to method Format | this |
| FormatInvalid.cs:30:24:30:31 | "{0,--1}" | FormatInvalid.cs:30:23:30:31 | "{0,--1}" | FormatInvalid.cs:30:23:30:31 | "{0,--1}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:30:9:30:35 | call to method Format | this |
| FormatInvalid.cs:33:24:33:30 | "{0:{}}" | FormatInvalid.cs:33:23:33:30 | "{0:{}}" | FormatInvalid.cs:33:23:33:30 | "{0:{}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:33:9:33:34 | call to method Format | this |
| FormatInvalid.cs:39:27:39:33 | "{{0}-{1}}" | FormatInvalid.cs:39:23:39:33 | "{{0}-{1}}" | FormatInvalid.cs:39:23:39:33 | "{{0}-{1}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:39:9:39:40 | call to method Format | this |
| FormatInvalid.cs:42:27:42:28 | "{0}}" | FormatInvalid.cs:42:23:42:28 | "{0}}" | FormatInvalid.cs:42:23:42:28 | "{0}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:42:9:42:35 | call to method Format | this |
| FormatInvalid.cs:45:24:45:32 | "{foo{0}}" | FormatInvalid.cs:45:23:45:32 | "{foo{0}}" | FormatInvalid.cs:45:23:45:32 | "{foo{0}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:45:9:45:36 | call to method Format | this |
| FormatInvalid.cs:51:24:51:25 | "}" | FormatInvalid.cs:51:23:51:25 | "}" | FormatInvalid.cs:51:23:51:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:51:9:51:29 | call to method Format | this |
| FormatInvalid.cs:75:24:75:25 | "}" | FormatInvalid.cs:75:23:75:25 | "}" | FormatInvalid.cs:75:23:75:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:75:9:75:29 | call to method Format | this |
| FormatInvalid.cs:76:24:76:25 | "}" | FormatInvalid.cs:76:23:76:25 | "}" | FormatInvalid.cs:76:23:76:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:76:9:76:30 | call to method Format | this |
| FormatInvalid.cs:77:28:77:29 | "}" | FormatInvalid.cs:77:27:77:29 | "}" | FormatInvalid.cs:77:27:77:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:77:9:77:34 | call to method Format | this |
| FormatInvalid.cs:78:24:78:25 | "}" | FormatInvalid.cs:78:23:78:25 | "}" | FormatInvalid.cs:78:23:78:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:78:9:78:32 | call to method Format | this |
| FormatInvalid.cs:79:24:79:25 | "}" | FormatInvalid.cs:79:23:79:25 | "}" | FormatInvalid.cs:79:23:79:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:79:9:79:35 | call to method Format | this |
| FormatInvalid.cs:80:24:80:25 | "}" | FormatInvalid.cs:80:23:80:25 | "}" | FormatInvalid.cs:80:23:80:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:80:9:80:38 | call to method Format | this |
| FormatInvalid.cs:82:26:82:27 | "}" | FormatInvalid.cs:82:25:82:27 | "}" | FormatInvalid.cs:82:25:82:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:82:9:82:31 | call to method AppendFormat | this |
| FormatInvalid.cs:83:26:83:27 | "}" | FormatInvalid.cs:83:25:83:27 | "}" | FormatInvalid.cs:83:25:83:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:83:9:83:32 | call to method AppendFormat | this |
| FormatInvalid.cs:84:30:84:31 | "}" | FormatInvalid.cs:84:29:84:31 | "}" | FormatInvalid.cs:84:29:84:31 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:84:9:84:36 | call to method AppendFormat | this |
| FormatInvalid.cs:85:26:85:27 | "}" | FormatInvalid.cs:85:25:85:27 | "}" | FormatInvalid.cs:85:25:85:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:85:9:85:34 | call to method AppendFormat | this |
| FormatInvalid.cs:86:26:86:27 | "}" | FormatInvalid.cs:86:25:86:27 | "}" | FormatInvalid.cs:86:25:86:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:86:9:86:37 | call to method AppendFormat | this |
| FormatInvalid.cs:87:26:87:27 | "}" | FormatInvalid.cs:87:25:87:27 | "}" | FormatInvalid.cs:87:25:87:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:87:9:87:40 | call to method AppendFormat | this |
| FormatInvalid.cs:89:28:89:29 | "}" | FormatInvalid.cs:89:27:89:29 | "}" | FormatInvalid.cs:89:27:89:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:89:9:89:33 | call to method WriteLine | this |
| FormatInvalid.cs:90:28:90:29 | "}" | FormatInvalid.cs:90:27:90:29 | "}" | FormatInvalid.cs:90:27:90:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:90:9:90:34 | call to method WriteLine | this |
| FormatInvalid.cs:91:28:91:29 | "}" | FormatInvalid.cs:91:27:91:29 | "}" | FormatInvalid.cs:91:27:91:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:91:9:91:36 | call to method WriteLine | this |
| FormatInvalid.cs:92:28:92:29 | "}" | FormatInvalid.cs:92:27:92:29 | "}" | FormatInvalid.cs:92:27:92:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:92:9:92:39 | call to method WriteLine | this |
| FormatInvalid.cs:93:28:93:29 | "}" | FormatInvalid.cs:93:27:93:29 | "}" | FormatInvalid.cs:93:27:93:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:93:9:93:42 | call to method WriteLine | this |
| FormatInvalid.cs:95:23:95:24 | "}" | FormatInvalid.cs:95:22:95:24 | "}" | FormatInvalid.cs:95:22:95:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:95:9:95:28 | call to method WriteLine | this |
| FormatInvalid.cs:96:23:96:24 | "}" | FormatInvalid.cs:96:22:96:24 | "}" | FormatInvalid.cs:96:22:96:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:96:9:96:29 | call to method WriteLine | this |
| FormatInvalid.cs:97:23:97:24 | "}" | FormatInvalid.cs:97:22:97:24 | "}" | FormatInvalid.cs:97:22:97:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:97:9:97:31 | call to method WriteLine | this |
| FormatInvalid.cs:98:23:98:24 | "}" | FormatInvalid.cs:98:22:98:24 | "}" | FormatInvalid.cs:98:22:98:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:98:9:98:34 | call to method WriteLine | this |
| FormatInvalid.cs:99:23:99:24 | "}" | FormatInvalid.cs:99:22:99:24 | "}" | FormatInvalid.cs:99:22:99:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:99:9:99:37 | call to method WriteLine | this |
| FormatInvalid.cs:101:45:101:46 | "}" | FormatInvalid.cs:101:44:101:46 | "}" | FormatInvalid.cs:101:44:101:46 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:101:9:101:51 | call to method WriteLine | this |
| FormatInvalid.cs:102:46:102:47 | "}" | FormatInvalid.cs:102:45:102:47 | "}" | FormatInvalid.cs:102:45:102:47 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:102:9:102:51 | call to method TraceError | this |
| FormatInvalid.cs:103:52:103:53 | "}" | FormatInvalid.cs:103:51:103:53 | "}" | FormatInvalid.cs:103:51:103:53 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:103:9:103:57 | call to method TraceInformation | this |
| FormatInvalid.cs:104:48:104:49 | "}" | FormatInvalid.cs:104:47:104:49 | "}" | FormatInvalid.cs:104:47:104:49 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:104:9:104:53 | call to method TraceWarning | this |
| FormatInvalid.cs:105:30:105:31 | "}" | FormatInvalid.cs:105:29:105:31 | "}" | FormatInvalid.cs:105:29:105:31 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:105:9:105:35 | call to method TraceInformation | this |
| FormatInvalid.cs:107:24:107:25 | "}" | FormatInvalid.cs:107:23:107:25 | "}" | FormatInvalid.cs:107:23:107:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:107:9:107:29 | call to method Write | this |
| FormatInvalid.cs:108:24:108:25 | "}" | FormatInvalid.cs:108:23:108:25 | "}" | FormatInvalid.cs:108:23:108:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:108:9:108:32 | call to method Write | this |
| FormatInvalid.cs:109:24:109:25 | "}" | FormatInvalid.cs:109:23:109:25 | "}" | FormatInvalid.cs:109:23:109:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:109:9:109:35 | call to method Write | this |
| FormatInvalid.cs:110:24:110:25 | "}" | FormatInvalid.cs:110:23:110:25 | "}" | FormatInvalid.cs:110:23:110:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:110:9:110:38 | call to method Write | this |
| FormatInvalid.cs:115:57:115:58 | "}" | FormatInvalid.cs:115:56:115:58 | "}" | FormatInvalid.cs:115:56:115:58 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:115:9:115:63 | call to method Assert | this |
| FormatInvalid.cs:116:19:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:116:9:116:24 | call to method Write | this |
| FormatInvalid.cs:117:41:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:117:9:117:47 | call to method Print | this |
| FormatInvalidBad.cs:7:41:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | Invalid format string used in $@ formatting call. | FormatInvalidBad.cs:7:16:7:45 | call to method Format | this |

View File

@@ -1,6 +1,22 @@
| FormatMissingArgument.cs:11:9:11:31 | call to method Format | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:11:23:11:27 | "{1}" | this |
| FormatMissingArgument.cs:14:9:14:38 | call to method Format | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this |
| FormatMissingArgument.cs:14:9:14:38 | call to method Format | Argument '{3}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this |
| FormatMissingArgument.cs:28:9:28:32 | call to method Format | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:22:16:22:20 | "{1}" | this |
| FormatMissingArgumentBad.cs:7:9:7:49 | call to method WriteLine | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | this |
| FormatMissingArgumentBad.cs:8:9:8:55 | call to method WriteLine | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | this |
nodes
| FormatMissingArgument.cs:8:23:8:27 | "{0}" | semmle.label | "{0}" |
| FormatMissingArgument.cs:11:23:11:27 | "{1}" | semmle.label | "{1}" |
| FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | semmle.label | "{2} {3}" |
| FormatMissingArgument.cs:17:23:17:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" |
| FormatMissingArgument.cs:20:23:20:39 | "{0} {1} {2} {3}" | semmle.label | "{0} {1} {2} {3}" |
| FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | semmle.label | "{1}" : String |
| FormatMissingArgument.cs:25:24:25:29 | format : String | semmle.label | format : String |
| FormatMissingArgument.cs:28:23:28:28 | access to parameter format | semmle.label | access to parameter format |
| FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | semmle.label | "Hello {0} {1}" |
| FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | semmle.label | "Hello {1} {2}" |
| FormatMissingArgumentGood.cs:7:27:7:41 | "Hello {0} {1}" | semmle.label | "Hello {0} {1}" |
edges
| FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:25:24:25:29 | format : String |
| FormatMissingArgument.cs:25:24:25:29 | format : String | FormatMissingArgument.cs:28:23:28:28 | access to parameter format |
#select
| FormatMissingArgument.cs:11:9:11:31 | call to method Format | FormatMissingArgument.cs:11:23:11:27 | "{1}" | FormatMissingArgument.cs:11:23:11:27 | "{1}" | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:11:23:11:27 | "{1}" | this |
| FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this |
| FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | Argument '{3}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this |
| FormatMissingArgument.cs:28:9:28:32 | call to method Format | FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:28:23:28:28 | access to parameter format | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:22:16:22:20 | "{1}" | this |
| FormatMissingArgumentBad.cs:7:9:7:49 | call to method WriteLine | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | this |
| FormatMissingArgumentBad.cs:8:9:8:55 | call to method WriteLine | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | this |

View File

@@ -1,13 +1,31 @@
| FormatUnusedArgument.cs:11:9:11:29 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:11:23:11:25 | "X" | format string | FormatUnusedArgument.cs:11:28:11:28 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:14:9:14:34 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | format string | FormatUnusedArgument.cs:14:33:14:33 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:17:9:17:38 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | format string | FormatUnusedArgument.cs:17:37:17:37 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:20:9:20:38 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | format string | FormatUnusedArgument.cs:20:34:20:34 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:34:23:34 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:37:23:37 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:40:23:40 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:26:9:26:35 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | format string | FormatUnusedArgument.cs:26:34:26:34 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:38:9:38:33 | call to method Format | The $@ ignores $@. | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | format string | FormatUnusedArgument.cs:38:32:38:32 | (...) ... | this supplied value |
| FormatUnusedArgumentBad.cs:7:9:7:71 | call to method WriteLine | The $@ ignores $@. | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | format string | FormatUnusedArgumentBad.cs:7:61:7:70 | (...) ... | this supplied value |
| FormatUnusedArgumentBad.cs:8:9:8:77 | call to method WriteLine | The $@ ignores $@. | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | format string | FormatUnusedArgumentBad.cs:8:63:8:64 | access to parameter ex | this supplied value |
| FormatUnusedArgumentBad.cs:9:9:9:75 | call to method WriteLine | The $@ ignores $@. | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | format string | FormatUnusedArgumentBad.cs:9:61:9:62 | access to parameter ex | this supplied value |
| FormatUnusedArgumentBad.cs:9:9:9:75 | call to method WriteLine | The $@ ignores $@. | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | format string | FormatUnusedArgumentBad.cs:9:65:9:74 | (...) ... | this supplied value |
nodes
| FormatUnusedArgument.cs:8:23:8:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" |
| FormatUnusedArgument.cs:11:23:11:25 | "X" | semmle.label | "X" |
| FormatUnusedArgument.cs:14:23:14:27 | "{0}" | semmle.label | "{0}" |
| FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | semmle.label | "{0} {0}" |
| FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | semmle.label | "{1} {1}" |
| FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | semmle.label | "abcdefg" |
| FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | semmle.label | "{{sdc}}" |
| FormatUnusedArgument.cs:29:23:29:33 | "{{{0:D}}}" | semmle.label | "{{{0:D}}}" |
| FormatUnusedArgument.cs:32:23:32:39 | "{0} {1} {2} {3}" | semmle.label | "{0} {1} {2} {3}" |
| FormatUnusedArgument.cs:35:23:35:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" |
| FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | semmle.label | "{{0}}" |
| FormatUnusedArgument.cs:42:23:42:24 | "" | semmle.label | "" |
| FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | semmle.label | "Error processing file: {0}" |
| FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | semmle.label | "Error processing file: {1} ({1})" |
| FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | semmle.label | "Error processing file: %s (%d)" |
edges
#select
| FormatUnusedArgument.cs:11:9:11:29 | call to method Format | FormatUnusedArgument.cs:11:23:11:25 | "X" | FormatUnusedArgument.cs:11:23:11:25 | "X" | The $@ ignores $@. | FormatUnusedArgument.cs:11:23:11:25 | "X" | format string | FormatUnusedArgument.cs:11:28:11:28 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:14:9:14:34 | call to method Format | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | The $@ ignores $@. | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | format string | FormatUnusedArgument.cs:14:33:14:33 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:17:9:17:38 | call to method Format | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | The $@ ignores $@. | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | format string | FormatUnusedArgument.cs:17:37:17:37 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:20:9:20:38 | call to method Format | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | The $@ ignores $@. | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | format string | FormatUnusedArgument.cs:20:34:20:34 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:34:23:34 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:37:23:37 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:40:23:40 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:26:9:26:35 | call to method Format | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | The $@ ignores $@. | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | format string | FormatUnusedArgument.cs:26:34:26:34 | (...) ... | this supplied value |
| FormatUnusedArgument.cs:38:9:38:33 | call to method Format | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | The $@ ignores $@. | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | format string | FormatUnusedArgument.cs:38:32:38:32 | (...) ... | this supplied value |
| FormatUnusedArgumentBad.cs:7:9:7:71 | call to method WriteLine | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | format string | FormatUnusedArgumentBad.cs:7:61:7:70 | (...) ... | this supplied value |
| FormatUnusedArgumentBad.cs:8:9:8:77 | call to method WriteLine | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | format string | FormatUnusedArgumentBad.cs:8:63:8:64 | access to parameter ex | this supplied value |
| FormatUnusedArgumentBad.cs:9:9:9:75 | call to method WriteLine | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | format string | FormatUnusedArgumentBad.cs:9:61:9:62 | access to parameter ex | this supplied value |
| FormatUnusedArgumentBad.cs:9:9:9:75 | call to method WriteLine | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | format string | FormatUnusedArgumentBad.cs:9:65:9:74 | (...) ... | this supplied value |

View File

@@ -579,6 +579,8 @@ private module ControlFlowGraphImpl {
n instanceof Stmt and
not n instanceof PostOrderNode and
not n instanceof SynchronizedStmt
or
result = n and n instanceof SwitchExpr
}
/**

View File

@@ -1051,6 +1051,18 @@ class MemberRefExpr extends FunctionalExpr, @memberref {
override string toString() { result = "...::..." }
}
/** A conditional expression or a `switch` expression. */
class ChooseExpr extends Expr {
ChooseExpr() { this instanceof ConditionalExpr or this instanceof SwitchExpr }
/** Gets a result expression of this `switch` or conditional expression. */
Expr getAResultExpr() {
result = this.(ConditionalExpr).getTrueExpr() or
result = this.(ConditionalExpr).getFalseExpr() or
result = this.(SwitchExpr).getAResult()
}
}
/**
* A conditional expression of the form `a ? b : c`, where `a` is the condition,
* `b` is the expression that is evaluated if the condition evaluates to `true`,

View File

@@ -248,8 +248,7 @@ private predicate formatStringFragment(Expr fmt) {
e.(VarAccess).getVariable().getAnAssignedValue() = fmt or
e.(AddExpr).getLeftOperand() = fmt or
e.(AddExpr).getRightOperand() = fmt or
e.(ConditionalExpr).getTrueExpr() = fmt or
e.(ConditionalExpr).getFalseExpr() = fmt
e.(ChooseExpr).getAResultExpr() = fmt
)
}
@@ -293,9 +292,7 @@ private predicate formatStringValue(Expr e, string fmtvalue) {
fmtvalue = left + right
)
or
formatStringValue(e.(ConditionalExpr).getTrueExpr(), fmtvalue)
or
formatStringValue(e.(ConditionalExpr).getFalseExpr(), fmtvalue)
formatStringValue(e.(ChooseExpr).getAResultExpr(), fmtvalue)
or
exists(Method getprop, MethodAccess ma, string prop |
e = ma and

View File

@@ -213,7 +213,7 @@ private predicate hasPossibleUnknownValue(SsaVariable v) {
/**
* Gets a sub-expression of `e` whose value can flow to `e` through
* `ConditionalExpr`s. Parentheses are also removed.
* `ConditionalExpr`s.
*/
private Expr possibleValue(Expr e) {
result = possibleValue(e.(ConditionalExpr).getTrueExpr())

View File

@@ -10,8 +10,7 @@ private import RangeAnalysis
/** Gets an expression that might have the value `i`. */
private Expr exprWithIntValue(int i) {
result.(ConstantIntegerExpr).getIntValue() = i or
result.(ConditionalExpr).getTrueExpr() = exprWithIntValue(i) or
result.(ConditionalExpr).getFalseExpr() = exprWithIntValue(i)
result.(ChooseExpr).getAResultExpr() = exprWithIntValue(i)
}
/**

View File

@@ -45,8 +45,7 @@ private import semmle.code.java.frameworks.Assertions
/** Gets an expression that may be `null`. */
Expr nullExpr() {
result instanceof NullLiteral or
result.(ConditionalExpr).getTrueExpr() = nullExpr() or
result.(ConditionalExpr).getFalseExpr() = nullExpr() or
result.(ChooseExpr).getAResultExpr() = nullExpr() or
result.(AssignExpr).getSource() = nullExpr() or
result.(CastExpr).getExpr() = nullExpr()
}
@@ -81,9 +80,7 @@ private predicate unboxed(Expr e) {
or
exists(UnaryExpr un | un.getExpr() = e)
or
exists(ConditionalExpr cond | cond.getType() instanceof PrimitiveType |
cond.getTrueExpr() = e or cond.getFalseExpr() = e
)
exists(ChooseExpr cond | cond.getType() instanceof PrimitiveType | cond.getAResultExpr() = e)
or
exists(ConditionNode cond | cond.getCondition() = e)
or

View File

@@ -552,9 +552,7 @@ private Sign exprSign(Expr e) {
result = s1.urshift(s2)
)
or
result = exprSign(e.(ConditionalExpr).getTrueExpr())
or
result = exprSign(e.(ConditionalExpr).getFalseExpr())
result = exprSign(e.(ChooseExpr).getAResultExpr())
or
result = exprSign(e.(CastExpr).getExpr())
)

View File

@@ -72,9 +72,7 @@ private predicate privateParamArg(Parameter p, Argument arg) {
* necessarily functionally determined by `n2`.
*/
private predicate joinStep0(TypeFlowNode n1, TypeFlowNode n2) {
n2.asExpr().(ConditionalExpr).getTrueExpr() = n1.asExpr()
or
n2.asExpr().(ConditionalExpr).getFalseExpr() = n1.asExpr()
n2.asExpr().(ChooseExpr).getAResultExpr() = n1.asExpr()
or
exists(Field f, Expr e |
f = n2.asField() and
@@ -226,9 +224,8 @@ private predicate upcastCand(TypeFlowNode n, RefType t, RefType t1, RefType t2)
or
exists(Parameter p | privateParamArg(p, n.asExpr()) and t2 = p.getType().getErasure())
or
exists(ConditionalExpr cond |
cond.getTrueExpr() = n.asExpr() or cond.getFalseExpr() = n.asExpr()
|
exists(ChooseExpr cond |
cond.getAResultExpr() = n.asExpr() and
t2 = cond.getType().getErasure()
)
)

View File

@@ -397,9 +397,7 @@ predicate simpleLocalFlowStep(Node node1, Node node2) {
or
node2.asExpr().(CastExpr).getExpr() = node1.asExpr()
or
node2.asExpr().(ConditionalExpr).getTrueExpr() = node1.asExpr()
or
node2.asExpr().(ConditionalExpr).getFalseExpr() = node1.asExpr()
node2.asExpr().(ChooseExpr).getAResultExpr() = node1.asExpr()
or
node2.asExpr().(AssignExpr).getSource() = node1.asExpr()
}

View File

@@ -296,6 +296,7 @@ private predicate taintPreservingQualifierToMethod(Method m) {
(
m.getName() = "concat" or
m.getName() = "endsWith" or
m.getName() = "formatted" or
m.getName() = "getBytes" or
m.getName() = "split" or
m.getName() = "substring" or
@@ -395,7 +396,7 @@ private predicate argToMethodStep(Expr tracked, MethodAccess sink) {
*/
private predicate taintPreservingArgumentToMethod(Method method) {
method.getDeclaringType() instanceof TypeString and
(method.hasName("format") or method.hasName("join"))
(method.hasName("format") or method.hasName("formatted") or method.hasName("join"))
}
/**

View File

@@ -202,9 +202,7 @@ private predicate flowStep(RelevantNode n1, RelevantNode n2) {
or
n2.asExpr().(CastExpr).getExpr() = n1.asExpr()
or
n2.asExpr().(ConditionalExpr).getTrueExpr() = n1.asExpr()
or
n2.asExpr().(ConditionalExpr).getFalseExpr() = n1.asExpr()
n2.asExpr().(ChooseExpr).getAResultExpr() = n1.asExpr()
or
n2.asExpr().(AssignExpr).getSource() = n1.asExpr()
or

View File

@@ -100,9 +100,7 @@ private predicate step(Node n1, Node n2) {
or
n2.asExpr().(CastExpr).getExpr() = n1.asExpr()
or
n2.asExpr().(ConditionalExpr).getTrueExpr() = n1.asExpr()
or
n2.asExpr().(ConditionalExpr).getFalseExpr() = n1.asExpr()
n2.asExpr().(ChooseExpr).getAResultExpr() = n1.asExpr()
or
n2.asExpr().(AssignExpr).getSource() = n1.asExpr()
or

View File

@@ -0,0 +1,25 @@
class TestSwitchExpr {
Object source() { return new Object(); }
void sink(Object o) { }
void test(String s) {
Object x1 = source();
Object x2 = switch (s) {
case "a", "b", ("a" + "b") -> null;
default -> x1;
};
Object x3 = switch (s) {
case "c", "d" -> { yield x2; }
default -> throw new RuntimeException();
};
Object x4 = switch (s) {
case "a", "b":
case "c", "d", ("c" + "d"):
yield x3;
default:
throw new RuntimeException();
};
sink(x4);
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -source 14 -target 14

View File

@@ -0,0 +1,9 @@
| TestSwitchExpr.java:4:15:4:22 | o |
| TestSwitchExpr.java:7:21:7:28 | source(...) |
| TestSwitchExpr.java:8:21:8:30 | switch (...) |
| TestSwitchExpr.java:10:24:10:25 | x1 |
| TestSwitchExpr.java:12:21:12:30 | switch (...) |
| TestSwitchExpr.java:13:38:13:39 | x2 |
| TestSwitchExpr.java:16:21:16:30 | switch (...) |
| TestSwitchExpr.java:19:23:19:24 | x3 |
| TestSwitchExpr.java:23:14:23:15 | x4 |

View File

@@ -0,0 +1,15 @@
import java
import semmle.code.java.dataflow.DataFlow
import DataFlow
class Conf extends Configuration {
Conf() { this = "qqconf" }
override predicate isSource(Node n) { n.asExpr().(MethodAccess).getMethod().hasName("source") }
override predicate isSink(Node n) { any() }
}
from Conf c, Node sink
where c.hasFlow(_, sink)
select sink

View File

@@ -27,11 +27,10 @@ class DangerousScheme extends string {
/** Returns a node that refers to the scheme of `url`. */
DataFlow::SourceNode schemeOf(DataFlow::Node url) {
// url.split(":")[0]
exists(DataFlow::MethodCallNode split |
split.getMethodName() = "split" and
split.getArgument(0).getStringValue() = ":" and
result = split.getAPropertyRead("0") and
url = split.getReceiver()
exists(StringSplitCall split |
split.getSeparator() = ":" and
result = split.getASubstringRead(0) and
url = split.getBaseString()
)
or
// url.getScheme(), url.getProtocol(), getScheme(url), getProtocol(url)

View File

@@ -1,4 +1,4 @@
$("button").click(function () {
var target = this.attr("data-target");
var target = $(this).attr("data-target");
$(target).hide();
});

View File

@@ -1,4 +1,4 @@
$("button").click(function () {
var target = this.attr("data-target");
$.find(target).hide();
var target = $(this).attr("data-target");
$.find(target).hide();
});

View File

@@ -1,18 +1,21 @@
const pg = require('pg');
const pool = new pg.Pool(config);
const app = require("express")(),
pg = require("pg"),
pool = new pg.Pool(config);
function handler(req, res) {
app.get("search", function handler(req, res) {
// BAD: the category might have SQL special characters in it
var query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ req.params.category + "' ORDER BY PRICE";
var query1 =
"SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" +
req.params.category +
"' ORDER BY PRICE";
pool.query(query1, [], function(err, results) {
// process results
});
// GOOD: use parameters
var query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=$1"
+ " ORDER BY PRICE";
var query2 =
"SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=$1" + " ORDER BY PRICE";
pool.query(query2, [req.params.category], function(err, results) {
// process results
// process results
});
}
});

View File

@@ -1 +1,7 @@
console.log("Unauthorized access attempt by " + user, ip);
const app = require("express")();
app.get("unauthorized", function handler(req, res) {
let user = req.query.user;
let ip = req.connection.remoteAddress;
console.log("Unauthorized access attempt by " + user, ip);
});

View File

@@ -1 +1,7 @@
console.log("Unauthorized access attempt by %s", user, ip);
const app = require("express")();
app.get("unauthorized", function handler(req, res) {
let user = req.query.user;
let ip = req.connection.remoteAddress;
console.log("Unauthorized access attempt by %s", user, ip);
});

View File

@@ -1,7 +1,9 @@
const crypto = require('crypto');
var secretText = obj.getSecretText();
const desCipher = crypto.createCipher('des', key);
let desEncrypted = cipher.write(secretText, 'utf8', 'hex'); // BAD: weak encryption
let desEncrypted = desCipher.write(secretText, 'utf8', 'hex'); // BAD: weak encryption
const aesCipher = crypto.createCipher('aes-128', key);
let aesEncrypted = cipher.update(secretText, 'utf8', 'hex'); // GOOD: strong encryption
let aesEncrypted = aesCipher.update(secretText, 'utf8', 'hex'); // GOOD: strong encryption

View File

@@ -1,11 +1,11 @@
var express = require('express')
var cookieParser = require('cookie-parser')
var passport = require('passport')
var app = require("express")(),
cookieParser = require("cookie-parser"),
passport = require("passport");
var app = express()
app.use(cookieParser());
app.use(passport.authorize({ session: true }));
app.use(cookieParser())
app.use(passport.authorize({ session: true }))
app.post('/changeEmail', ..., function (req, res) {
})
app.post("/changeEmail", function(req, res) {
let newEmail = req.cookies["newEmail"];
// ...
});

View File

@@ -1,13 +1,12 @@
var express = require('express')
var cookieParser = require('cookie-parser')
var passport = require('passport')
var csrf = require('csurf')
var app = require("express")(),
cookieParser = require("cookie-parser"),
passport = require("passport"),
csrf = require("csurf");
var app = express()
app.use(cookieParser())
app.use(passport.authorize({ session: true }))
app.use(csrf({ cookie:true }))
app.post('/changeEmail', ..., function (req, res) {
})
app.use(cookieParser());
app.use(passport.authorize({ session: true }));
app.use(csrf({ cookie: true }));
app.post("/changeEmail", function(req, res) {
let newEmail = req.cookies["newEmail"];
// ...
});

View File

@@ -21,11 +21,10 @@ import semmle.javascript.DynamicPropertyAccess
*
* We restrict this to parameter nodes to focus on "deep assignment" functions.
*/
class SplitCall extends MethodCallNode {
class SplitCall extends StringSplitCall {
SplitCall() {
getMethodName() = "split" and
getArgument(0).mayHaveStringValue(".") and
getReceiver().getALocalSource() instanceof ParameterNode
getSeparator() = "." and
getBaseString().getALocalSource() instanceof ParameterNode
}
}

View File

@@ -1,6 +1,7 @@
const jsyaml = require("js-yaml");
const app = require("express")(),
jsyaml = require("js-yaml");
function requestHandler(req, res) {
app.get("load", function(req, res) {
let data = jsyaml.load(req.params.data);
// ...
}
});

View File

@@ -1,6 +1,7 @@
const jsyaml = require("js-yaml");
const app = require("express")(),
jsyaml = require("js-yaml");
function requestHandler(req, res) {
app.get("load", function(req, res) {
let data = jsyaml.safeLoad(req.params.data);
// ...
}
});

View File

@@ -1,3 +1,5 @@
const app = require("express")();
app.get('/some/path', function(req, res) {
// BAD: a request parameter is incorporated without validation into a URL redirect
res.redirect(req.param("target"));

View File

@@ -1,3 +1,5 @@
const app = require("express")();
const VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html";
app.get('/some/path', function(req, res) {

View File

@@ -1,2 +1,7 @@
const libxml = require('libxmljs');
var doc = libxml.parseXml(xmlSrc, { noent: true });
const app = require("express")(),
libxml = require("libxmljs");
app.post("upload", (req, res) => {
let xmlSrc = req.body,
doc = libxml.parseXml(xmlSrc, { noent: true });
});

View File

@@ -1,2 +1,7 @@
const libxml = require('libxmljs');
var doc = libxml.parseXml(xmlSrc);
const app = require("express")(),
libxml = require("libxmljs");
app.post("upload", (req, res) => {
let xmlSrc = req.body,
doc = libxml.parseXml(xmlSrc);
});

View File

@@ -1,5 +1,10 @@
const expat = require('node-expat');
var parser = new expat.Parser();
parser.on('startElement', handleStart);
parser.on('text', handleText);
parser.write(xmlSrc);
const app = require("express")(),
expat = require("node-expat");
app.post("upload", (req, res) => {
let xmlSrc = req.body,
parser = new expat.Parser();
parser.on("startElement", handleStart);
parser.on("text", handleText);
parser.write(xmlSrc);
});

View File

@@ -1,5 +1,10 @@
const sax = require('sax');
var parser = sax.parser(true);
parser.onopentag = handleStart;
parser.ontext = handleText;
parser.write(xmlSrc);
const app = require("express")(),
sax = require("sax");
app.post("upload", (req, res) => {
let xmlSrc = req.body,
parser = sax.parser(true);
parser.onopentag = handleStart;
parser.ontext = handleText;
parser.write(xmlSrc);
});

View File

@@ -1,10 +1,10 @@
const pg = require('pg')
const pg = require("pg");
const client = new pg.Client({
user: 'dbuser',
host: 'database.server.com',
database: 'mydb',
password: 'secretpassword',
port: 3211,
})
client.connect()
user: "bob",
host: "database.server.com",
database: "mydb",
password: "correct-horse-battery-staple",
port: 3211
});
client.connect();

View File

@@ -1,15 +1,15 @@
var express = require('express'),
path = require('path'),
var app = express();
var app = require("express")(),
path = require("path");
app.get('/user-files', function(req, res) {
var file = req.param('file');
if (file.indexOf('..') !== -1) { // BAD
// forbid paths outside the /public directory
res.status(400).send('Bad request');
} else {
var absolute = path.resolve('/public/' + file);
console.log("Sending file: %s", absolute);
res.sendFile(absolute);
}
app.get("/user-files", function(req, res) {
var file = req.param("file");
if (file.indexOf("..") !== -1) {
// BAD
// forbid paths outside the /public directory
res.status(400).send("Bad request");
} else {
var absolute = path.resolve("/public/" + file);
console.log("Sending file: %s", absolute);
res.sendFile(absolute);
}
});

View File

@@ -1,15 +1,15 @@
var express = require('express'),
path = require('path'),
var app = express();
var app = require("express")(),
path = require("path");
app.get('/user-files', function(req, res) {
var file = req.param('file');
if (typeof path !== 'string' || path.indexOf('..') !== -1) { // GOOD
// forbid paths outside the /public directory
res.status(400).send('Bad request');
} else {
var full = path.resolve('/public/' + file);
console.log("Sending file: %s", full);
res.sendFile(full);
}
app.get("/user-files", function(req, res) {
var file = req.param("file");
if (typeof path !== 'string' || file.indexOf("..") !== -1) {
// BAD
// forbid paths outside the /public directory
res.status(400).send("Bad request");
} else {
var absolute = path.resolve("/public/" + file);
console.log("Sending file: %s", absolute);
res.sendFile(absolute);
}
});

View File

@@ -1,5 +1,5 @@
const crypto = require("crypto");
function hashPassword(password) {
var crypto = require("crypto");
var hasher = crypto.createHash('md5');
var hashed = hasher.update(password).digest("hex"); // BAD
return hashed;

View File

@@ -1,5 +1,5 @@
const bcrypt = require("bcrypt");
function hashPassword(password, salt) {
var bcrypt = require('bcrypt');
var hashed = bcrypt.hashSync(password, salt); // GOOD
return hashed;
var hashed = bcrypt.hashSync(password, salt); // GOOD
return hashed;
}

View File

@@ -2,7 +2,7 @@ import http from 'http';
import url from 'url';
var server = http.createServer(function(req, res) {
var target = url.parse(request.url, true).query.target;
var target = url.parse(req.url, true).query.target;
// BAD: `target` is controlled by the attacker
http.get('https://' + target + ".example.com/data/", res => {

View File

@@ -2,7 +2,7 @@ import http from 'http';
import url from 'url';
var server = http.createServer(function(req, res) {
var target = url.parse(request.url, true).query.target;
var target = url.parse(req.url, true).query.target;
var subdomain;
if (target === 'EU') {

View File

@@ -146,3 +146,37 @@ class StringReplaceCall extends DataFlow::MethodCallNode {
)
}
}
/**
* A call to `String.prototype.split`.
*
* We heuristically include any call to a method called `split`, provided it either
* has one or two arguments, or local data flow suggests that the receiver may be a string.
*/
class StringSplitCall extends DataFlow::MethodCallNode {
StringSplitCall() {
this.getMethodName() = "split" and
(getNumArgument() = [1, 2] or getReceiver().mayHaveStringValue(_))
}
/**
* Gets a string that determines where the string is split.
*/
string getSeparator() {
getArgument(0).mayHaveStringValue(result)
or
result =
getArgument(0).getALocalSource().(DataFlow::RegExpCreationNode).getRoot().getAMatchedString()
}
/**
* Gets the DataFlow::Node for the base string that is split.
*/
DataFlow::Node getBaseString() { result = getReceiver() }
/**
* Gets a read of the `i`th element from the split string.
*/
bindingset[i]
DataFlow::Node getASubstringRead(int i) { result = getAPropertyRead(i.toString()) }
}

View File

@@ -7,24 +7,104 @@
import javascript
module ConnectExpressShared {
/**
* String representing the signature of a route handler, that is,
* the list of parameters taken by the route handler.
*
* Concretely this is a comma-separated list of parameter kinds, which can be either
* `request`, `response`, `next`, `error`, or `parameter`, but this is considered an
* implementation detail.
*/
private class RouteHandlerSignature extends string {
RouteHandlerSignature() {
this = "request,response" or
this = "request,response,next" or
this = "request,response,next,parameter" or
this = "error,request,response,next"
}
/** Gets the index of the parameter corresonding to the given `kind`, if any. */
pragma[noinline]
int getParameterIndex(string kind) { this.splitAt(",", result) = kind }
/** Gets the number of parameters taken by this signature. */
pragma[noinline]
int getArity() { result = count(getParameterIndex(_)) }
/** Holds if this signature takes a parameter of the given kind. */
predicate has(string kind) { exists(getParameterIndex(kind)) }
}
private module RouteHandlerSignature {
/** Gets the signature corresonding to `(req, res, next, param) => {...}`. */
RouteHandlerSignature requestResponseNextParameter() {
result = "request,response,next,parameter"
}
/** Gets the signature corresonding to `(req, res, next) => {...}`. */
RouteHandlerSignature requestResponseNext() { result = "request,response,next" }
/** Gets the signature corresonding to `(err, req, res, next) => {...}`. */
RouteHandlerSignature errorRequestResponseNext() { result = "error,request,response,next" }
}
/**
* Holds if `fun` appears to match the given signature based on parameter naming.
*/
private predicate matchesSignature(Function function, RouteHandlerSignature sig) {
function.getNumParameter() = sig.getArity() and
function.getParameter(sig.getParameterIndex("request")).getName() = ["req", "request"] and
function.getParameter(sig.getParameterIndex("response")).getName() = ["res", "response"] and
(
sig.has("next")
implies
function.getParameter(sig.getParameterIndex("next")).getName() = ["next", "cb"]
)
}
/**
* Gets the parameter corresonding to the given `kind`, where `routeHandler` is interpreted as a
* route handler with the signature `sig`.
*
* This does not check if the function is actually a route handler or matches the signature in any way,
* so the caller should restrict the function accordingly.
*/
pragma[inline]
private Parameter getRouteHandlerParameter(
Function routeHandler, RouteHandlerSignature sig, string kind
) {
result = routeHandler.getParameter(sig.getParameterIndex(kind))
}
/**
* Gets the parameter of kind `kind` of a Connect/Express route parameter handler function.
*
* `kind` is one of: "error", "request", "response", "next".
*/
pragma[inline]
Parameter getRouteParameterHandlerParameter(Function routeHandler, string kind) {
result =
getRouteHandlerParameter(routeHandler, RouteHandlerSignature::requestResponseNextParameter(),
kind)
}
/**
* Gets the parameter of kind `kind` of a Connect/Express route handler function.
*
* `kind` is one of: "error", "request", "response", "next".
*/
SimpleParameter getRouteHandlerParameter(Function routeHandler, string kind) {
exists(int index, int offset |
result = routeHandler.getParameter(index + offset) and
(if routeHandler.getNumParameter() = 4 then offset = 0 else offset = -1)
|
kind = "error" and index = 0
or
kind = "request" and index = 1
or
kind = "response" and index = 2
or
kind = "next" and index = 3
)
pragma[inline]
Parameter getRouteHandlerParameter(Function routeHandler, string kind) {
if routeHandler.getNumParameter() = 4
then
// For arity 4 there is ambiguity between (err, req, res, next) and (req, res, next, param)
// This predicate favors the 'err' signature whereas getRouteParameterHandlerParameter favors the other.
result =
getRouteHandlerParameter(routeHandler, RouteHandlerSignature::errorRequestResponseNext(),
kind)
else
result =
getRouteHandlerParameter(routeHandler, RouteHandlerSignature::requestResponseNext(), kind)
}
/**
@@ -34,39 +114,16 @@ module ConnectExpressShared {
*/
class RouteHandlerCandidate extends HTTP::RouteHandlerCandidate {
RouteHandlerCandidate() {
exists(string request, string response, string next, string error |
(request = "request" or request = "req") and
(response = "response" or response = "res") and
next = "next" and
(error = "error" or error = "err")
|
// heuristic: parameter names match the documentation
astNode.getNumParameter() >= 2 and
getRouteHandlerParameter(astNode, "request").getName() = request and
getRouteHandlerParameter(astNode, "response").getName() = response and
(
astNode.getNumParameter() >= 3
implies
getRouteHandlerParameter(astNode, "next").getName() = next
) and
(
astNode.getNumParameter() = 4
implies
getRouteHandlerParameter(astNode, "error").getName() = error
) and
not (
// heuristic: max four parameters (the server will only supply four arguments)
astNode.getNumParameter() > 4
or
// heuristic: not a class method (the server invokes this with a function call)
astNode = any(MethodDefinition def).getBody()
or
// heuristic: does not return anything (the server will not use the return value)
exists(astNode.getAReturnStmt().getExpr())
or
// heuristic: is not invoked (the server invokes this at a call site we cannot reason precisely about)
exists(DataFlow::InvokeNode cs | cs.getACallee() = astNode)
)
matchesSignature(astNode, _) and
not (
// heuristic: not a class method (the server invokes this with a function call)
astNode = any(MethodDefinition def).getBody()
or
// heuristic: does not return anything (the server will not use the return value)
exists(astNode.getAReturnStmt().getExpr())
or
// heuristic: is not invoked (the server invokes this at a call site we cannot reason precisely about)
exists(DataFlow::InvokeNode cs | cs.getACallee() = astNode)
)
}
}

View File

@@ -127,14 +127,14 @@ module Express {
/**
* Gets the HTTP request type this is registered for, if any.
*
* Has no result for `use` and `all` calls.
* Has no result for `use`, `all`, or `param` calls.
*/
HTTP::RequestMethodName getRequestMethod() { result.toLowerCase() = getMethodName() }
/**
* Holds if this registers a route for all request methods.
*/
predicate handlesAllRequestMethods() { getMethodName() = "use" or getMethodName() = "all" }
predicate handlesAllRequestMethods() { getMethodName() = ["use", "all", "param"] }
/**
* Holds if this route setup sets up a route for the same
@@ -146,6 +146,11 @@ module Express {
that.handlesAllRequestMethods() or
this.getRequestMethod() = that.getRequestMethod()
}
/**
* Holds if this route setup is a parameter handler, such as `app.param("foo", ...)`.
*/
predicate isParameterHandler() { getMethodName() = "param" }
}
/**
@@ -314,7 +319,7 @@ module Express {
/**
* Gets the parameter of kind `kind` of this route handler.
*
* `kind` is one of: "error", "request", "response", "next".
* `kind` is one of: "error", "request", "response", "next", or "parameter".
*/
abstract SimpleParameter getRouteHandlerParameter(string kind);
@@ -340,11 +345,14 @@ module Express {
class StandardRouteHandler extends RouteHandler, HTTP::Servers::StandardRouteHandler,
DataFlow::ValueNode {
override Function astNode;
RouteSetup routeSetup;
StandardRouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
StandardRouteHandler() { this = routeSetup.getARouteHandler() }
override SimpleParameter getRouteHandlerParameter(string kind) {
result = getRouteHandlerParameter(astNode, kind)
if routeSetup.isParameterHandler()
then result = getRouteParameterHandlerParameter(astNode, kind)
else result = getRouteHandlerParameter(astNode, kind)
}
}
@@ -453,32 +461,31 @@ module Express {
string kind;
RequestInputAccess() {
exists(DataFlow::Node request | request = DataFlow::valueNode(rh.getARequestExpr()) |
exists(DataFlow::SourceNode request | request = rh.getARequestSource().ref() |
kind = "parameter" and
(
this.(DataFlow::MethodCallNode).calls(request, "param")
this = request.getAMethodCall("param")
or
exists(DataFlow::PropRead base, string propName |
// `req.params.name` or `req.query.name`
base.accesses(request, propName) and
this = base.getAPropertyReference(_)
|
propName = "params" or
propName = "query"
)
this = request.getAPropertyRead(["params", "query"]).getAPropertyRead()
)
or
// `req.originalUrl`
kind = "url" and
this.(DataFlow::PropRef).accesses(request, "originalUrl")
this = request.getAPropertyRead("originalUrl")
or
// `req.cookies`
kind = "cookie" and
this.(DataFlow::PropRef).accesses(request, "cookies")
this = request.getAPropertyRead("cookies")
)
or
kind = "body" and
this.asExpr() = rh.getARequestBodyAccess()
or
// `value` in `router.param('foo', (req, res, next, value) => { ... })`
kind = "parameter" and
exists(RouteSetup setup | rh = setup.getARouteHandler() |
this = DataFlow::parameterNode(rh.getRouteHandlerParameter("parameter"))
)
}
override RouteHandler getRouteHandler() { result = rh }
@@ -848,10 +855,14 @@ module Express {
*/
private class TrackedRouteHandlerCandidateWithSetup extends RouteHandler,
HTTP::Servers::StandardRouteHandler, DataFlow::FunctionNode {
TrackedRouteHandlerCandidateWithSetup() { this = any(RouteSetup s).getARouteHandler() }
RouteSetup routeSetup;
TrackedRouteHandlerCandidateWithSetup() { this = routeSetup.getARouteHandler() }
override SimpleParameter getRouteHandlerParameter(string kind) {
result = getRouteHandlerParameter(astNode, kind)
if routeSetup.isParameterHandler()
then result = getRouteParameterHandlerParameter(astNode, kind)
else result = getRouteHandlerParameter(astNode, kind)
}
}

View File

@@ -219,12 +219,14 @@ module Firebase {
*/
private class RouteHandler extends Express::RouteHandler, HTTP::Servers::StandardRouteHandler,
DataFlow::ValueNode {
override Function astNode;
RouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
override SimpleParameter getRouteHandlerParameter(string kind) {
kind = "request" and result = this.(DataFlow::FunctionNode).getParameter(0).getParameter()
kind = "request" and result = astNode.getParameter(0)
or
kind = "response" and result = this.(DataFlow::FunctionNode).getParameter(1).getParameter()
kind = "response" and result = astNode.getParameter(1)
}
}
}

View File

@@ -204,6 +204,20 @@ module HTTP {
*/
abstract HeaderDefinition getAResponseHeader(string name);
/**
* Gets a request object originating from this route handler.
*
* Use `RequestSource.ref()` to get reference to this request object.
*/
final Servers::RequestSource getARequestSource() { result.getRouteHandler() = this }
/**
* Gets a response object originating from this route handler.
*
* Use `ResponseSource.ref()` to get reference to this response object.
*/
final Servers::ResponseSource getAResponseSource() { result.getRouteHandler() = this }
/**
* Gets an expression that contains a request object handled
* by this handler.
@@ -296,7 +310,8 @@ module HTTP {
*/
abstract RouteHandler getRouteHandler();
predicate flowsTo(DataFlow::Node nd) { ref(DataFlow::TypeTracker::end()).flowsTo(nd) }
/** DEPRECATED. Use `ref().flowsTo()` instead. */
deprecated predicate flowsTo(DataFlow::Node nd) { ref().flowsTo(nd) }
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and
@@ -304,6 +319,9 @@ module HTTP {
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
}
/** Gets a `SourceNode` that refers to this request object. */
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
}
/**
@@ -317,7 +335,8 @@ module HTTP {
*/
abstract RouteHandler getRouteHandler();
predicate flowsTo(DataFlow::Node nd) { ref(DataFlow::TypeTracker::end()).flowsTo(nd) }
/** DEPRECATED. Use `ref().flowsTo()` instead. */
deprecated predicate flowsTo(DataFlow::Node nd) { ref().flowsTo(nd) }
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and
@@ -325,6 +344,9 @@ module HTTP {
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
}
/** Gets a `SourceNode` that refers to this response object. */
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
}
/**
@@ -333,7 +355,7 @@ module HTTP {
class StandardRequestExpr extends RequestExpr {
RequestSource src;
StandardRequestExpr() { src.flowsTo(DataFlow::valueNode(this)) }
StandardRequestExpr() { src.ref().flowsTo(DataFlow::valueNode(this)) }
override RouteHandler getRouteHandler() { result = src.getRouteHandler() }
}
@@ -344,7 +366,7 @@ module HTTP {
class StandardResponseExpr extends ResponseExpr {
ResponseSource src;
StandardResponseExpr() { src.flowsTo(DataFlow::valueNode(this)) }
StandardResponseExpr() { src.ref().flowsTo(DataFlow::valueNode(this)) }
override RouteHandler getRouteHandler() { result = src.getRouteHandler() }
}
@@ -370,6 +392,7 @@ module HTTP {
/**
* Gets a route handler that is defined by this setup.
*/
pragma[nomagic]
abstract DataFlow::SourceNode getARouteHandler();
/**

View File

@@ -306,7 +306,7 @@ module NodeJSLib {
FsFlowTarget() {
exists(DataFlow::CallNode call, string methodName |
call = DataFlow::moduleMember("fs", methodName).getACall()
call = FS::moduleMember(methodName).getACall()
|
methodName = "realpathSync" and
tainted = call.getArgument(0) and
@@ -430,27 +430,32 @@ module NodeJSLib {
}
/**
* A member `member` from module `fs` or its drop-in replacements `graceful-fs`, `fs-extra`, `original-fs`.
* Provides predicates for working with the "fs" module and its variants as a single module.
*/
private DataFlow::SourceNode fsModuleMember(string member) {
result = fsModule(DataFlow::TypeTracker::end()).getAPropertyRead(member)
}
module FS {
/**
* A member `member` from module `fs` or its drop-in replacements `graceful-fs`, `fs-extra`, `original-fs`.
*/
DataFlow::SourceNode moduleMember(string member) {
result = fsModule(DataFlow::TypeTracker::end()).getAPropertyRead(member)
}
private DataFlow::SourceNode fsModule(DataFlow::TypeTracker t) {
exists(string moduleName |
moduleName = "fs" or
moduleName = "graceful-fs" or
moduleName = "fs-extra" or
moduleName = "original-fs"
|
result = DataFlow::moduleImport(moduleName)
private DataFlow::SourceNode fsModule(DataFlow::TypeTracker t) {
exists(string moduleName |
moduleName = "fs" or
moduleName = "graceful-fs" or
moduleName = "fs-extra" or
moduleName = "original-fs"
|
result = DataFlow::moduleImport(moduleName)
or
// extra support for flexible names
result.asExpr().(Require).getArgument(0).mayHaveStringValue(moduleName)
) and
t.start()
or
// extra support for flexible names
result.asExpr().(Require).getArgument(0).mayHaveStringValue(moduleName)
) and
t.start()
or
exists(DataFlow::TypeTracker t2 | result = fsModule(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = fsModule(t2).track(t2, t))
}
}
/**
@@ -459,7 +464,7 @@ module NodeJSLib {
private class NodeJSFileSystemAccess extends FileSystemAccess, DataFlow::CallNode {
string methodName;
NodeJSFileSystemAccess() { this = maybePromisified(fsModuleMember(methodName)).getACall() }
NodeJSFileSystemAccess() { this = maybePromisified(FS::moduleMember(methodName)).getACall() }
/**
* Gets the name of the called method.
@@ -582,8 +587,8 @@ module NodeJSLib {
name = "readdir" or
name = "realpath"
|
this = fsModuleMember(name).getACall().getCallback([1 .. 2]).getParameter(1) or
this = fsModuleMember(name + "Sync").getACall()
this = FS::moduleMember(name).getACall().getCallback([1 .. 2]).getParameter(1) or
this = FS::moduleMember(name + "Sync").getACall()
)
}
}

View File

@@ -9,6 +9,8 @@ import semmle.javascript.security.dataflow.RemoteFlowSources
import UrlConcatenation
module ClientSideUrlRedirect {
private import Xss::DomBasedXss as DomBasedXss
/**
* A data flow source for unvalidated URL redirect vulnerabilities.
*/
@@ -52,7 +54,7 @@ module ClientSideUrlRedirect {
mce = queryAccess.asExpr() and mce.calls(nd.asExpr(), methodName)
|
methodName = "split" and
// exclude `location.href.split('?')[0]`, which can never refer to the query string
// exclude all splits where only the prefix is accessed, which is safe for url-redirects.
not exists(PropAccess pacc | mce = pacc.getBase() | pacc.getPropertyName() = "0")
or
(methodName = "substring" or methodName = "substr" or methodName = "slice") and
@@ -68,6 +70,11 @@ module ClientSideUrlRedirect {
)
}
/**
* A sanitizer that reads the first part a location split by "?", e.g. `location.href.split('?')[0]`.
*/
class QueryPrefixSanitizer extends Sanitizer, DomBasedXss::QueryPrefixSanitizer { }
/**
* A sink which is used to set the window location.
*/

View File

@@ -97,23 +97,17 @@ module TaintedPath {
)
)
or
// A `str.split()` call can either split into path elements (`str.split("/")`) or split by some other string.
exists(StringSplitCall mcn | dst = mcn and mcn.getBaseString() = src |
if mcn.getSeparator() = "/"
then
srclabel.(Label::PosixPath).canContainDotDotSlash() and
dstlabel instanceof Label::SplitPath
else srclabel = dstlabel
)
or
// array method calls of interest
exists(DataFlow::MethodCallNode mcn, string name | dst = mcn and mcn.calls(src, name) |
// A `str.split()` call can either split into path elements (`str.split("/")`) or split by some other string.
name = "split" and
(
if
exists(DataFlow::Node splitBy | splitBy = mcn.getArgument(0) |
splitBy.mayHaveStringValue("/") or
any(DataFlow::RegExpCreationNode reg | reg.getRoot().getAMatchedString() = "/")
.flowsTo(splitBy)
)
then
srclabel.(Label::PosixPath).canContainDotDotSlash() and
dstlabel instanceof Label::SplitPath
else srclabel = dstlabel
)
or
(
name = "pop" or
name = "shift"

View File

@@ -155,11 +155,11 @@ module TaintedPath {
input = getAnArgument() and
output = this
or
this = DataFlow::moduleMember("fs", "realpathSync").getACall() and
this = NodeJSLib::FS::moduleMember("realpathSync").getACall() and
input = getArgument(0) and
output = this
or
this = DataFlow::moduleMember("fs", "realpath").getACall() and
this = NodeJSLib::FS::moduleMember("realpath").getACall() and
input = getArgument(0) and
output = getCallback(1).getParameter(1)
}

View File

@@ -278,6 +278,20 @@ module DomBasedXss {
}
}
/**
* A sanitizer that reads the first part a location split by "?", e.g. `location.href.split('?')[0]`.
*/
class QueryPrefixSanitizer extends Sanitizer {
StringSplitCall splitCall;
QueryPrefixSanitizer() {
this = splitCall.getASubstringRead(0) and
splitCall.getSeparator() = "?" and
splitCall.getBaseString().getALocalSource() =
[DOM::locationRef(), DOM::locationRef().getAPropertyRead("href")]
}
}
/**
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
* XSS vulnerabilities.

View File

@@ -107,7 +107,14 @@ module ZipSlip {
// However, we want to consider even the bare `createWriteStream`
// to be a zipslip vulnerability since it may truncate an
// existing file.
this = DataFlow::moduleImport("fs").getAMemberCall("createWriteStream").getArgument(0)
this = NodeJSLib::FS::moduleMember("createWriteStream").getACall().getArgument(0)
or
// Not covered by `FileSystemWriteSink` because a later call
// to `fs.write` is required for a write to take place.
exists(DataFlow::CallNode call | this = call.getArgument(0) |
call = NodeJSLib::FS::moduleMember(["open", "openSync"]).getACall() and
call.getArgument(1).getStringValue().regexpMatch("(?i)w.{0,2}")
)
}
}

View File

@@ -3,4 +3,7 @@ var app = express();
app.get('/some/path', function(req, res) {
let { foo, bar: baz } = req.query;
let dynamic1 = req.query[foo];
let dynamic2 = req.query[something()];
res.send(dynamic1);
});

View File

@@ -0,0 +1,16 @@
var express = require('express');
var app = express();
app.param('foo', (req, res, next, value) => {
console.log(req.query.xx);
console.log(req.body.xx);
if (value) {
res.send(value);
} else {
next();
}
});
app.get('/hello/:foo', function(req, res) {
res.send("Hello");
});

View File

@@ -7,12 +7,14 @@ test_RouteHandlerExpr_getBody
| src/express2.js:3:25:3:55 | functio ... , res } | src/express2.js:3:25:3:55 | functio ... , res } |
| src/express2.js:4:32:4:76 | functio ... esult } | src/express2.js:4:32:4:76 | functio ... esult } |
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express4.js:4:23:6:1 | functio ... uery;\\n} | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:16:19:18:3 | functio ... ");\\n } |
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:22:30:32:1 | functio ... ar');\\n} |
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:14:24:16:1 | functio ... lo");\\n} | src/params.js:14:24:16:1 | functio ... lo");\\n} |
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
@@ -28,12 +30,14 @@ test_RouteSetup
| src/express2.js:3:1:3:56 | router. ... res }) | src/express2.js:5:11:5:13 | e() | false |
| src/express2.js:3:1:4:77 | router. ... sult }) | src/express2.js:5:11:5:13 | e() | false |
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | src/express3.js:2:11:2:19 | express() | false |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | src/express4.js:2:11:2:19 | express() | false |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | src/express4.js:2:11:2:19 | express() | false |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:2:11:2:19 | express() | false |
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:2:11:2:19 | express() | false |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:2:11:2:19 | express() | false |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:2:11:2:19 | express() | false |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | src/inheritedFromNode.js:2:11:2:19 | express() | false |
| src/params.js:4:1:12:2 | app.par ... }\\n}) | src/params.js:2:11:2:19 | express() | false |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | src/params.js:2:11:2:19 | express() | false |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:2:11:2:19 | express() | false |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:2:11:2:19 | express() | false |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:2:11:2:19 | express() | false |
@@ -55,7 +59,7 @@ test_RouteSetup_getLastRouteHandlerExpr
| src/express2.js:6:1:6:15 | app.use(router) | src/express2.js:6:9:6:14 | router |
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express3.js:12:1:12:21 | app.use ... dler()) | src/express3.js:12:9:12:20 | getHandler() |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:16:19:18:3 | functio ... ");\\n } |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:22:30:32:1 | functio ... ar');\\n} |
@@ -64,6 +68,8 @@ test_RouteSetup_getLastRouteHandlerExpr
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:44:9:44:25 | getArrowHandler() |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:4:1:12:2 | app.par ... }\\n}) | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | src/params.js:14:24:16:1 | functio ... lo");\\n} |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
@@ -182,6 +188,8 @@ test_isRequest
| src/express3.js:5:14:5:16 | req |
| src/express3.js:5:35:5:37 | req |
| src/express4.js:5:27:5:29 | req |
| src/express4.js:6:18:6:20 | req |
| src/express4.js:7:18:7:20 | req |
| src/express.js:5:16:5:18 | req |
| src/express.js:6:26:6:28 | req |
| src/express.js:23:3:23:5 | req |
@@ -197,6 +205,8 @@ test_isRequest
| src/express.js:49:3:49:5 | req |
| src/express.js:50:3:50:5 | req |
| src/inheritedFromNode.js:7:2:7:4 | req |
| src/params.js:5:17:5:19 | req |
| src/params.js:6:17:6:19 | req |
| src/passport.js:28:2:28:4 | req |
| src/responseExprs.js:17:5:17:7 | req |
test_RouteSetup_getRouter
@@ -215,7 +225,7 @@ test_RouteSetup_getRouter
| src/express2.js:6:1:6:15 | app.use(router) | src/express2.js:5:11:5:13 | e() |
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | src/express3.js:2:11:2:19 | express() |
| src/express3.js:12:1:12:21 | app.use ... dler()) | src/express3.js:2:11:2:19 | express() |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | src/express4.js:2:11:2:19 | express() |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | src/express4.js:2:11:2:19 | express() |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:2:11:2:19 | express() |
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:2:11:2:19 | express() |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:2:11:2:19 | express() |
@@ -224,6 +234,8 @@ test_RouteSetup_getRouter
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:2:11:2:19 | express() |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:2:11:2:19 | express() |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | src/inheritedFromNode.js:2:11:2:19 | express() |
| src/params.js:4:1:12:2 | app.par ... }\\n}) | src/params.js:2:11:2:19 | express() |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | src/params.js:2:11:2:19 | express() |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:2:11:2:19 | express() |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
@@ -249,12 +261,14 @@ test_StandardRouteHandler
| src/express2.js:3:25:3:55 | functio ... , res } | src/express2.js:5:11:5:13 | e() | src/express2.js:3:34:3:36 | req | src/express2.js:3:39:3:41 | res |
| src/express2.js:4:32:4:76 | functio ... esult } | src/express2.js:5:11:5:13 | e() | src/express2.js:4:41:4:47 | request | src/express2.js:4:50:4:55 | result |
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:2:11:2:19 | express() | src/express3.js:4:32:4:34 | req | src/express3.js:4:37:4:39 | res |
| src/express4.js:4:23:6:1 | functio ... uery;\\n} | src/express4.js:2:11:2:19 | express() | src/express4.js:4:32:4:34 | req | src/express4.js:4:37:4:39 | res |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:2:11:2:19 | express() | src/express4.js:4:32:4:34 | req | src/express4.js:4:37:4:39 | res |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:2:11:2:19 | express() | src/express.js:4:32:4:34 | req | src/express.js:4:37:4:39 | res |
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:2:11:2:19 | express() | src/express.js:16:28:16:30 | req | src/express.js:16:33:16:35 | res |
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:2:11:2:19 | express() | src/express.js:22:39:22:41 | req | src/express.js:22:44:22:46 | res |
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:2:11:2:19 | express() | src/express.js:46:31:46:33 | req | src/express.js:46:36:46:38 | res |
| src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} | src/inheritedFromNode.js:2:11:2:19 | express() | src/inheritedFromNode.js:4:24:4:26 | req | src/inheritedFromNode.js:4:29:4:31 | res |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:2:11:2:19 | express() | src/params.js:4:19:4:21 | req | src/params.js:4:24:4:26 | res |
| src/params.js:14:24:16:1 | functio ... lo");\\n} | src/params.js:2:11:2:19 | express() | src/params.js:14:33:14:35 | req | src/params.js:14:38:14:40 | res |
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:4:32:4:34 | req | src/responseExprs.js:4:37:4:40 | res1 |
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:7:32:7:34 | req | src/responseExprs.js:7:37:7:40 | res2 |
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:10:39:10:41 | req | src/responseExprs.js:10:44:10:47 | res3 |
@@ -263,8 +277,10 @@ test_StandardRouteHandler
test_RequestInputAccess
| src/express3.js:5:14:5:32 | req.param("header") | parameter | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express3.js:5:35:5:50 | req.param("val") | parameter | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express4.js:5:9:5:11 | foo | parameter | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:5:14:5:21 | bar: baz | parameter | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:5:9:5:11 | foo | parameter | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express4.js:5:14:5:21 | bar: baz | parameter | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express4.js:6:18:6:31 | req.query[foo] | parameter | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express4.js:7:18:7:39 | req.que ... hing()] | parameter | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:5:16:5:34 | req.param("target") | parameter | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:6:26:6:44 | req.param("target") | parameter | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:23:3:23:10 | req.body | body | src/express.js:22:30:32:1 | functio ... ar');\\n} |
@@ -280,6 +296,9 @@ test_RequestInputAccess
| src/express.js:49:3:49:14 | req.hostname | header | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/express.js:50:3:50:32 | req.hea ... erName] | header | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/inheritedFromNode.js:7:2:7:8 | req.url | url | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:4:35:4:39 | value | parameter | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:5:17:5:28 | req.query.xx | parameter | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:6:17:6:24 | req.body | body | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/passport.js:28:2:28:9 | req.body | body | src/passport.js:27:4:29:1 | functio ... ccss`\\n} |
test_SetCookie
| src/express.js:31:3:31:26 | res.coo ... 'bar') | src/express.js:22:30:32:1 | functio ... ar');\\n} |
@@ -335,6 +354,8 @@ test_ResponseExpr
| src/express3.js:5:3:5:51 | res.hea ... "val")) | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express3.js:6:3:6:5 | res | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express3.js:6:3:6:17 | res.send("val") | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express4.js:8:3:8:5 | res | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express4.js:8:3:8:20 | res.send(dynamic1) | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:5:3:5:5 | res | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:6:3:6:5 | res | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:6:3:6:45 | res.hea ... rget")) | src/express.js:4:23:9:1 | functio ... res);\\n} |
@@ -349,6 +370,10 @@ test_ResponseExpr
| src/express.js:31:3:31:26 | res.coo ... 'bar') | src/express.js:22:30:32:1 | functio ... ar');\\n} |
| src/inheritedFromNode.js:5:2:5:4 | res | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/inheritedFromNode.js:6:2:6:4 | res | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:8:9:8:11 | res | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:8:9:8:23 | res.send(value) | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:15:3:15:5 | res | src/params.js:14:24:16:1 | functio ... lo");\\n} |
| src/params.js:15:3:15:19 | res.send("Hello") | src/params.js:14:24:16:1 | functio ... lo");\\n} |
| src/responseExprs.js:5:5:5:8 | res1 | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
| src/responseExprs.js:8:5:8:8 | res2 | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
| src/responseExprs.js:11:5:11:8 | res3 | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
@@ -401,12 +426,14 @@ test_RouterDefinition_getARouteHandler
| src/express2.js:2:14:2:23 | e.Router() | src/express2.js:3:25:3:55 | functio ... , res } |
| src/express2.js:2:14:2:23 | e.Router() | src/express2.js:4:32:4:76 | functio ... esult } |
| src/express3.js:2:11:2:19 | express() | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express4.js:2:11:2:19 | express() | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:2:11:2:19 | express() | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:2:11:2:19 | express() | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:2:11:2:19 | express() | src/express.js:16:19:18:3 | functio ... ");\\n } |
| src/express.js:2:11:2:19 | express() | src/express.js:22:30:32:1 | functio ... ar');\\n} |
| src/express.js:2:11:2:19 | express() | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/inheritedFromNode.js:2:11:2:19 | express() | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:2:11:2:19 | express() | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:2:11:2:19 | express() | src/params.js:14:24:16:1 | functio ... lo");\\n} |
| src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
| src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
| src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
@@ -450,6 +477,7 @@ test_ExpressSession
| src/express-session.js:7:1:9:2 | session ... -3"]\\n}) | secret | src/express-session.js:8:13:8:44 | ["secre ... key-3"] |
test_RequestBodyAccess
| src/express.js:23:3:23:10 | req.body |
| src/params.js:6:17:6:24 | req.body |
| src/passport.js:28:2:28:9 | req.body |
test_RouteSetup_getServer
| src/csurf-example.js:20:1:23:2 | app.get ... ) })\\n}) | src/csurf-example.js:7:11:7:19 | express() |
@@ -460,12 +488,14 @@ test_RouteSetup_getServer
| src/express2.js:3:1:3:56 | router. ... res }) | src/express2.js:5:11:5:13 | e() |
| src/express2.js:3:1:4:77 | router. ... sult }) | src/express2.js:5:11:5:13 | e() |
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | src/express3.js:2:11:2:19 | express() |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | src/express4.js:2:11:2:19 | express() |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | src/express4.js:2:11:2:19 | express() |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:2:11:2:19 | express() |
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:2:11:2:19 | express() |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:2:11:2:19 | express() |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:2:11:2:19 | express() |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | src/inheritedFromNode.js:2:11:2:19 | express() |
| src/params.js:4:1:12:2 | app.par ... }\\n}) | src/params.js:2:11:2:19 | express() |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | src/params.js:2:11:2:19 | express() |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:2:11:2:19 | express() |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
@@ -497,7 +527,7 @@ test_RouteHandlerExpr
| src/express2.js:6:9:6:14 | router | src/express2.js:6:1:6:15 | app.use(router) | false |
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:4:1:7:2 | app.get ... l");\\n}) | true |
| src/express3.js:12:9:12:20 | getHandler() | src/express3.js:12:1:12:21 | app.use ... dler()) | false |
| src/express4.js:4:23:6:1 | functio ... uery;\\n} | src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | true |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | true |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:4:1:9:2 | app.get ... es);\\n}) | true |
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:16:3:18:4 | router. ... );\\n }) | true |
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:22:1:32:2 | app.pos ... r');\\n}) | true |
@@ -506,6 +536,8 @@ test_RouteHandlerExpr
| src/express.js:44:9:44:25 | getArrowHandler() | src/express.js:44:1:44:26 | app.use ... dler()) | false |
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:46:1:51:2 | app.pos ... me];\\n}) | true |
| src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} | src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | true |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:4:1:12:2 | app.par ... }\\n}) | true |
| src/params.js:14:24:16:1 | functio ... lo");\\n} | src/params.js:14:1:16:2 | app.get ... o");\\n}) | true |
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | true |
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | true |
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | true |
@@ -530,7 +562,9 @@ test_RouteSetup_handlesAllRequestMethods
| src/express3.js:12:1:12:21 | app.use ... dler()) |
| src/express.js:39:1:39:21 | app.use ... dler()) |
| src/express.js:44:1:44:26 | app.use ... dler()) |
| src/params.js:4:1:12:2 | app.par ... }\\n}) |
| src/route.js:4:1:5:39 | router. ... xt) {}) |
| src/routesetups.js:3:1:4:14 | express ... ('', h) |
| src/subrouter.js:4:1:4:26 | app.use ... rotect) |
| src/subrouter.js:5:1:5:29 | app.use ... uter()) |
test_RouterDefinition_getASubRouter
@@ -550,6 +584,7 @@ test_appCreation
| src/express4.js:2:11:2:19 | express() |
| src/express.js:2:11:2:19 | express() |
| src/inheritedFromNode.js:2:11:2:19 | express() |
| src/params.js:2:11:2:19 | express() |
| src/responseExprs.js:2:11:2:19 | express() |
| src/routesetups.js:7:11:7:32 | express ... erver() |
| src/subrouter.js:2:11:2:19 | express() |
@@ -562,13 +597,14 @@ test_RouteSetup_getRequestMethod
| src/express2.js:3:1:3:56 | router. ... res }) | GET |
| src/express2.js:3:1:4:77 | router. ... sult }) | POST |
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | GET |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | GET |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | GET |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | GET |
| src/express.js:16:3:18:4 | router. ... );\\n }) | GET |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | POST |
| src/express.js:34:1:34:53 | app.get ... andler) | GET |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | POST |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | POST |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | GET |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | GET |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | GET |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | GET |
@@ -595,7 +631,7 @@ test_RouteExpr
| src/express2.js:6:1:6:15 | app.use(router) | src/express2.js:5:11:5:13 | e() |
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | src/express3.js:2:11:2:19 | express() |
| src/express3.js:12:1:12:21 | app.use ... dler()) | src/express3.js:2:11:2:19 | express() |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | src/express4.js:2:11:2:19 | express() |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | src/express4.js:2:11:2:19 | express() |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:2:11:2:19 | express() |
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:2:11:2:19 | express() |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:2:11:2:19 | express() |
@@ -604,6 +640,8 @@ test_RouteExpr
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:2:11:2:19 | express() |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:2:11:2:19 | express() |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | src/inheritedFromNode.js:2:11:2:19 | express() |
| src/params.js:4:1:12:2 | app.par ... }\\n}) | src/params.js:2:11:2:19 | express() |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | src/params.js:2:11:2:19 | express() |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:2:11:2:19 | express() |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
@@ -639,6 +677,8 @@ test_RouteHandler_getAResponseExpr
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:5:3:5:51 | res.hea ... "val")) |
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:6:3:6:5 | res |
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:6:3:6:17 | res.send("val") |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:8:3:8:5 | res |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:8:3:8:20 | res.send(dynamic1) |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:5:3:5:5 | res |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:6:3:6:5 | res |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:6:3:6:45 | res.hea ... rget")) |
@@ -653,6 +693,10 @@ test_RouteHandler_getAResponseExpr
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:31:3:31:26 | res.coo ... 'bar') |
| src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} | src/inheritedFromNode.js:5:2:5:4 | res |
| src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} | src/inheritedFromNode.js:6:2:6:4 | res |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:8:9:8:11 | res |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:8:9:8:23 | res.send(value) |
| src/params.js:14:24:16:1 | functio ... lo");\\n} | src/params.js:15:3:15:5 | res |
| src/params.js:14:24:16:1 | functio ... lo");\\n} | src/params.js:15:3:15:19 | res.send("Hello") |
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:5:5:5:8 | res1 |
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:8:5:8:8 | res2 |
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:11:5:11:8 | res3 |
@@ -710,6 +754,8 @@ test_isResponse
| src/express3.js:5:3:5:51 | res.hea ... "val")) |
| src/express3.js:6:3:6:5 | res |
| src/express3.js:6:3:6:17 | res.send("val") |
| src/express4.js:8:3:8:5 | res |
| src/express4.js:8:3:8:20 | res.send(dynamic1) |
| src/express.js:5:3:5:5 | res |
| src/express.js:6:3:6:5 | res |
| src/express.js:6:3:6:45 | res.hea ... rget")) |
@@ -724,6 +770,10 @@ test_isResponse
| src/express.js:31:3:31:26 | res.coo ... 'bar') |
| src/inheritedFromNode.js:5:2:5:4 | res |
| src/inheritedFromNode.js:6:2:6:4 | res |
| src/params.js:8:9:8:11 | res |
| src/params.js:8:9:8:23 | res.send(value) |
| src/params.js:15:3:15:5 | res |
| src/params.js:15:3:15:19 | res.send("Hello") |
| src/responseExprs.js:5:5:5:8 | res1 |
| src/responseExprs.js:8:5:8:8 | res2 |
| src/responseExprs.js:11:5:11:8 | res3 |
@@ -772,12 +822,18 @@ test_ResponseBody
| src/csurf-example.js:26:12:26:42 | 'csrf w ... t here' | src/csurf-example.js:25:22:27:1 | functio ... ere')\\n} |
| src/csurf-example.js:33:14:33:34 | 'no csr ... t here' | src/csurf-example.js:32:30:34:3 | functio ... e')\\n } |
| src/express3.js:6:12:6:16 | "val" | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express4.js:8:12:8:19 | dynamic1 | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:17:14:17:23 | "Go away." | src/express.js:16:19:18:3 | functio ... ");\\n } |
| src/params.js:8:18:8:22 | value | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:15:12:15:18 | "Hello" | src/params.js:14:24:16:1 | functio ... lo");\\n} |
test_ResponseSendArgument
| src/csurf-example.js:26:12:26:42 | 'csrf w ... t here' | src/csurf-example.js:25:22:27:1 | functio ... ere')\\n} |
| src/csurf-example.js:33:14:33:34 | 'no csr ... t here' | src/csurf-example.js:32:30:34:3 | functio ... e')\\n } |
| src/express3.js:6:12:6:16 | "val" | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express4.js:8:12:8:19 | dynamic1 | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:17:14:17:23 | "Go away." | src/express.js:16:19:18:3 | functio ... ");\\n } |
| src/params.js:8:18:8:22 | value | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:15:12:15:18 | "Hello" | src/params.js:14:24:16:1 | functio ... lo");\\n} |
test_RouteSetup_getARouteHandler
| src/auth.js:4:1:4:53 | app.use ... d' }})) | src/auth.js:4:9:4:52 | basicAu ... rd' }}) |
| src/csurf-example.js:13:1:13:20 | app.use('/api', api) | src/csurf-example.js:10:11:10:27 | createApiRouter() |
@@ -796,7 +852,7 @@ test_RouteSetup_getARouteHandler
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express3.js:12:1:12:21 | app.use ... dler()) | src/express3.js:10:12:10:32 | functio ... res){} |
| src/express3.js:12:1:12:21 | app.use ... dler()) | src/express3.js:12:9:12:20 | getHandler() |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:16:19:18:3 | functio ... ");\\n } |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:22:30:32:1 | functio ... ar');\\n} |
@@ -808,6 +864,8 @@ test_RouteSetup_getARouteHandler
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:44:9:44:25 | getArrowHandler() |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:4:1:12:2 | app.par ... }\\n}) | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | src/params.js:14:24:16:1 | functio ... lo");\\n} |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
@@ -855,6 +913,7 @@ test_isRouterCreation
| src/express4.js:2:11:2:19 | express() |
| src/express.js:2:11:2:19 | express() |
| src/inheritedFromNode.js:2:11:2:19 | express() |
| src/params.js:2:11:2:19 | express() |
| src/responseExprs.js:2:11:2:19 | express() |
| src/route.js:2:14:2:29 | express.Router() |
| src/routesetups.js:3:1:3:16 | express.Router() |
@@ -878,7 +937,7 @@ test_RouteSetup_getRouteHandlerExpr
| src/express2.js:6:1:6:15 | app.use(router) | 0 | src/express2.js:6:9:6:14 | router |
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | 0 | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express3.js:12:1:12:21 | app.use ... dler()) | 0 | src/express3.js:12:9:12:20 | getHandler() |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | 0 | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | 0 | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | 0 | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:16:3:18:4 | router. ... );\\n }) | 0 | src/express.js:16:19:18:3 | functio ... ");\\n } |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | 0 | src/express.js:22:30:32:1 | functio ... ar');\\n} |
@@ -887,6 +946,8 @@ test_RouteSetup_getRouteHandlerExpr
| src/express.js:44:1:44:26 | app.use ... dler()) | 0 | src/express.js:44:9:44:25 | getArrowHandler() |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | 0 | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | 0 | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:4:1:12:2 | app.par ... }\\n}) | 0 | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | 0 | src/params.js:14:24:16:1 | functio ... lo");\\n} |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | 0 | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | 0 | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | 0 | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
@@ -912,6 +973,7 @@ test_RouterDefinition_RouterDefinition
| src/express4.js:2:11:2:19 | express() |
| src/express.js:2:11:2:19 | express() |
| src/inheritedFromNode.js:2:11:2:19 | express() |
| src/params.js:2:11:2:19 | express() |
| src/responseExprs.js:2:11:2:19 | express() |
| src/route.js:2:14:2:29 | express.Router() |
| src/routesetups.js:3:1:3:16 | express.Router() |
@@ -921,6 +983,7 @@ test_RouterDefinition_RouterDefinition
| src/subrouter.js:8:16:8:31 | express.Router() |
test_RouteHandler_getARequestBodyAccess
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:23:3:23:10 | req.body |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:6:17:6:24 | req.body |
| src/passport.js:27:4:29:1 | functio ... ccss`\\n} | src/passport.js:28:2:28:9 | req.body |
test_RouterDefinition_getMiddlewareStack
| src/auth.js:1:13:1:32 | require('express')() | src/auth.js:4:9:4:52 | basicAu ... rd' }}) |
@@ -940,7 +1003,7 @@ test_RouteHandler
| src/express2.js:4:32:4:76 | functio ... esult } | src/express2.js:4:41:4:47 | request | src/express2.js:4:50:4:55 | result |
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:4:32:4:34 | req | src/express3.js:4:37:4:39 | res |
| src/express3.js:10:12:10:32 | functio ... res){} | src/express3.js:10:22:10:24 | req | src/express3.js:10:27:10:29 | res |
| src/express4.js:4:23:6:1 | functio ... uery;\\n} | src/express4.js:4:32:4:34 | req | src/express4.js:4:37:4:39 | res |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:4:32:4:34 | req | src/express4.js:4:37:4:39 | res |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:4:32:4:34 | req | src/express.js:4:37:4:39 | res |
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:16:28:16:30 | req | src/express.js:16:33:16:35 | res |
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:22:39:22:41 | req | src/express.js:22:44:22:46 | res |
@@ -948,6 +1011,8 @@ test_RouteHandler
| src/express.js:42:12:42:28 | (req, res) => f() | src/express.js:42:13:42:15 | req | src/express.js:42:18:42:20 | res |
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:46:31:46:33 | req | src/express.js:46:36:46:38 | res |
| src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} | src/inheritedFromNode.js:4:24:4:26 | req | src/inheritedFromNode.js:4:29:4:31 | res |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:4:19:4:21 | req | src/params.js:4:24:4:26 | res |
| src/params.js:14:24:16:1 | functio ... lo");\\n} | src/params.js:14:33:14:35 | req | src/params.js:14:38:14:40 | res |
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:4:32:4:34 | req | src/responseExprs.js:4:37:4:40 | res1 |
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:7:32:7:34 | req | src/responseExprs.js:7:37:7:40 | res2 |
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:10:39:10:41 | req | src/responseExprs.js:10:44:10:47 | res3 |
@@ -970,7 +1035,7 @@ test_RouteSetup_getARouteHandlerExpr
| src/express2.js:6:1:6:15 | app.use(router) | src/express2.js:6:9:6:14 | router |
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express3.js:12:1:12:21 | app.use ... dler()) | src/express3.js:12:9:12:20 | getHandler() |
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:4:1:9:2 | app.get ... c1);\\n}) | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:16:19:18:3 | functio ... ");\\n } |
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:22:30:32:1 | functio ... ar');\\n} |
@@ -979,6 +1044,8 @@ test_RouteSetup_getARouteHandlerExpr
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:44:9:44:25 | getArrowHandler() |
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/inheritedFromNode.js:4:1:8:2 | app.pos ... url;\\n}) | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:4:1:12:2 | app.par ... }\\n}) | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:14:1:16:2 | app.get ... o");\\n}) | src/params.js:14:24:16:1 | functio ... lo");\\n} |
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
@@ -1011,7 +1078,9 @@ test_RequestExpr
| src/express2.js:4:60:4:66 | request | src/express2.js:4:32:4:76 | functio ... esult } |
| src/express3.js:5:14:5:16 | req | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express3.js:5:35:5:37 | req | src/express3.js:4:23:7:1 | functio ... al");\\n} |
| src/express4.js:5:27:5:29 | req | src/express4.js:4:23:6:1 | functio ... uery;\\n} |
| src/express4.js:5:27:5:29 | req | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express4.js:6:18:6:20 | req | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express4.js:7:18:7:20 | req | src/express4.js:4:23:9:1 | functio ... ic1);\\n} |
| src/express.js:5:16:5:18 | req | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:6:26:6:28 | req | src/express.js:4:23:9:1 | functio ... res);\\n} |
| src/express.js:23:3:23:5 | req | src/express.js:22:30:32:1 | functio ... ar');\\n} |
@@ -1027,6 +1096,8 @@ test_RequestExpr
| src/express.js:49:3:49:5 | req | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/express.js:50:3:50:5 | req | src/express.js:46:22:51:1 | functio ... ame];\\n} |
| src/inheritedFromNode.js:7:2:7:4 | req | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
| src/params.js:5:17:5:19 | req | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/params.js:6:17:6:19 | req | src/params.js:4:18:12:1 | (req, r ... }\\n} |
| src/passport.js:28:2:28:4 | req | src/passport.js:27:4:29:1 | functio ... ccss`\\n} |
| src/responseExprs.js:17:5:17:7 | req | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
test_RequestExprStandalone
@@ -1044,7 +1115,9 @@ test_RouteHandler_getARequestExpr
| src/express2.js:4:32:4:76 | functio ... esult } | src/express2.js:4:60:4:66 | request |
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:5:14:5:16 | req |
| src/express3.js:4:23:7:1 | functio ... al");\\n} | src/express3.js:5:35:5:37 | req |
| src/express4.js:4:23:6:1 | functio ... uery;\\n} | src/express4.js:5:27:5:29 | req |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:5:27:5:29 | req |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:6:18:6:20 | req |
| src/express4.js:4:23:9:1 | functio ... ic1);\\n} | src/express4.js:7:18:7:20 | req |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:5:16:5:18 | req |
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:6:26:6:28 | req |
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:23:3:23:5 | req |
@@ -1060,5 +1133,7 @@ test_RouteHandler_getARequestExpr
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:49:3:49:5 | req |
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:50:3:50:5 | req |
| src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} | src/inheritedFromNode.js:7:2:7:4 | req |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:5:17:5:19 | req |
| src/params.js:4:18:12:1 | (req, r ... }\\n} | src/params.js:6:17:6:19 | req |
| src/passport.js:27:4:29:1 | functio ... ccss`\\n} | src/passport.js:28:2:28:4 | req |
| src/responseExprs.js:16:30:42:1 | functio ... }\\n} | src/responseExprs.js:17:5:17:7 | req |

View File

@@ -3,3 +3,4 @@
| IncompleteUrlSchemeCheck.js:23:9:23:43 | badProt ... scheme) | This check does not consider vbscript:. |
| IncompleteUrlSchemeCheck.js:30:9:30:43 | badProt ... scheme) | This check does not consider vbscript:. |
| IncompleteUrlSchemeCheck.js:37:9:37:31 | scheme ... script" | This check does not consider data: and vbscript:. |
| IncompleteUrlSchemeCheck.js:51:9:51:31 | scheme ... script" | This check does not consider data: and vbscript:. |

View File

@@ -45,3 +45,10 @@ function test6(url) {
return "about:blank";
return url;
}
function test7(url) {
let scheme = url.split(/:/)[0];
if (scheme === "javascript") // NOT OK
return "about:blank";
return url;
}

View File

@@ -24,6 +24,11 @@ nodes
| ZipSlipBad.js:15:22:15:31 | entry.path |
| ZipSlipBad.js:16:30:16:37 | fileName |
| ZipSlipBad.js:16:30:16:37 | fileName |
| ZipSlipBad.js:22:11:22:31 | fileName |
| ZipSlipBad.js:22:22:22:31 | entry.path |
| ZipSlipBad.js:22:22:22:31 | entry.path |
| ZipSlipBad.js:23:28:23:35 | fileName |
| ZipSlipBad.js:23:28:23:35 | fileName |
| ZipSlipBadUnzipper.js:7:9:7:29 | fileName |
| ZipSlipBadUnzipper.js:7:20:7:29 | entry.path |
| ZipSlipBadUnzipper.js:7:20:7:29 | entry.path |
@@ -46,6 +51,10 @@ edges
| ZipSlipBad.js:15:11:15:31 | fileName | ZipSlipBad.js:16:30:16:37 | fileName |
| ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:15:11:15:31 | fileName |
| ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:15:11:15:31 | fileName |
| ZipSlipBad.js:22:11:22:31 | fileName | ZipSlipBad.js:23:28:23:35 | fileName |
| ZipSlipBad.js:22:11:22:31 | fileName | ZipSlipBad.js:23:28:23:35 | fileName |
| ZipSlipBad.js:22:22:22:31 | entry.path | ZipSlipBad.js:22:11:22:31 | fileName |
| ZipSlipBad.js:22:22:22:31 | entry.path | ZipSlipBad.js:22:11:22:31 | fileName |
| ZipSlipBadUnzipper.js:7:9:7:29 | fileName | ZipSlipBadUnzipper.js:8:37:8:44 | fileName |
| ZipSlipBadUnzipper.js:7:9:7:29 | fileName | ZipSlipBadUnzipper.js:8:37:8:44 | fileName |
| ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:7:9:7:29 | fileName |
@@ -57,4 +66,5 @@ edges
| ZipSlipBad2.js:6:22:6:29 | fileName | ZipSlipBad2.js:5:37:5:46 | entry.path | ZipSlipBad2.js:6:22:6:29 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad2.js:5:37:5:46 | entry.path | item path |
| ZipSlipBad.js:8:37:8:44 | fileName | ZipSlipBad.js:7:22:7:31 | entry.path | ZipSlipBad.js:8:37:8:44 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:7:22:7:31 | entry.path | item path |
| ZipSlipBad.js:16:30:16:37 | fileName | ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:16:30:16:37 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:15:22:15:31 | entry.path | item path |
| ZipSlipBad.js:23:28:23:35 | fileName | ZipSlipBad.js:22:22:22:31 | entry.path | ZipSlipBad.js:23:28:23:35 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:22:22:22:31 | entry.path | item path |
| ZipSlipBadUnzipper.js:8:37:8:44 | fileName | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:8:37:8:44 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | item path |

View File

@@ -15,3 +15,10 @@ fs.createReadStream('archive.zip')
const fileName = entry.path;
entry.pipe(Writer({path: fileName}));
});
fs.createReadStream('archive.zip')
.pipe(unzip.Parse())
.on('entry', entry => {
const fileName = entry.path;
var file = fs.openSync(fileName, "w");
});

View File

@@ -15,4 +15,12 @@ fs.writeFileSync = function(filename, data) {};
* @param {(string|Buffer)} dstpath
* @return {void}
*/
fs.linkSync = function(srcpath, dstpath) {};
fs.linkSync = function(srcpath, dstpath) {};
/**
* @param {(string|Buffer)} path
* @param {(string|number)} flags
* @param {number=} mode
* @return {number}
*/
fs.openSync = function(path, flags, mode) {};

Some files were not shown because too many files have changed in this diff Show More