diff --git a/change-notes/1.24/analysis-cpp.md b/change-notes/1.24/analysis-cpp.md index 54954e0f70a..78d4aee4ed7 100644 --- a/change-notes/1.24/analysis-cpp.md +++ b/change-notes/1.24/analysis-cpp.md @@ -19,6 +19,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications. | Memory is never freed (`cpp/memory-never-freed`) | More true positive results | This query now identifies a wider variety of buffer allocations using the `semmle.code.cpp.models.interfaces.Allocation` library. | | Memory may not be freed (`cpp/memory-may-not-be-freed`) | More true positive results | This query now identifies a wider variety of buffer allocations using the `semmle.code.cpp.models.interfaces.Allocation` library. | | Missing return statement (`cpp/missing-return`) | Fewer false positive results | Functions containing `asm` statements are no longer highlighted by this query. | +| No space for zero terminator (`cpp/no-space-for-terminator`) | More correct results | String arguments to formatting functions are now (usually) expected to be null terminated strings. | | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | | This query is no longer run on LGTM. | | No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. | | Overloaded assignment does not return 'this' (`cpp/assignment-does-not-return-this`) | Fewer false positive results | This query no longer reports incorrect results in template classes. | diff --git a/change-notes/1.24/analysis-csharp.md b/change-notes/1.24/analysis-csharp.md index 5859d97afb6..27b0b8f5b4a 100644 --- a/change-notes/1.24/analysis-csharp.md +++ b/change-notes/1.24/analysis-csharp.md @@ -29,6 +29,7 @@ The following changes in version 1.24 affect C# analysis in all applications. * Tuple expressions, for example `(int,bool)` in `default((int,bool))` are now extracted correctly. * Expression nullability flow state is extracted. * Implicitly typed `stackalloc` expressions are now extracted correctly. +* The difference between `stackalloc` array creations and normal array creations is extracted. ## Changes to libraries @@ -39,5 +40,6 @@ The following changes in version 1.24 affect C# analysis in all applications. * The taint tracking library now tracks flow through (implicit or explicit) conversion operator calls. * [Code contracts](https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts) are now recognized, and are treated like any other assertion methods. * Expression nullability flow state is given by the predicates `Expr.hasNotNullFlowState()` and `Expr.hasMaybeNullFlowState()`. +* `stackalloc` array creations are now represented by the QL class `Stackalloc`. Previously they were represented by the class `ArrayCreation`. ## Changes to autobuilder diff --git a/change-notes/1.24/analysis-python.md b/change-notes/1.24/analysis-python.md new file mode 100644 index 00000000000..a4a643944c7 --- /dev/null +++ b/change-notes/1.24/analysis-python.md @@ -0,0 +1,37 @@ +# Improvements to Python analysis + +The following changes in version 1.24 affect Python analysis in all applications. + +## General improvements + +## New queries + +| **Query** | **Tags** | **Purpose** | +|-----------------------------|-----------|--------------------------------------------------------------------| + +## Changes to existing queries + +| **Query** | **Expected impact** | **Change** | +|----------------------------|------------------------|------------------------------------------------------------------| + +### Web framework support + +The QL-library support for the web frameworks Bottle, CherryPy, Falcon, Pyramid, TurboGears, Tornado, and Twisted have +been fixed so they provide a proper HttpRequestTaintSource, instead of a TaintSource. This will enable results for the following queries: + +- py/path-injection +- py/command-line-injection +- py/reflective-xss +- py/sql-injection +- py/code-injection +- py/unsafe-deserialization +- py/url-redirection + +The QL-library support for the web framework Twisted have been fixed so they provide a proper +HttpResponseTaintSink, instead of a TaintSink. This will enable results for the following +queries: + +- py/reflective-xss +- py/stack-trace-exposure + +## Changes to libraries diff --git a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql index 79a4418125b..7ee6acdcd59 100644 --- a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql +++ b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql @@ -22,16 +22,25 @@ import semmle.code.cpp.models.interfaces.Allocation predicate terminationProblem(AllocationExpr malloc, string msg) { // malloc(strlen(...)) exists(StrlenCall strlen | DataFlow::localExprFlow(strlen, malloc.getSizeExpr())) and - // flows into a null-terminated string function + // flows to a call that implies this is a null-terminated string exists(ArrayFunction af, FunctionCall fc, int arg | DataFlow::localExprFlow(malloc, fc.getArgument(arg)) and fc.getTarget() = af and ( - // null terminated string + // flows into null terminated string argument af.hasArrayWithNullTerminator(arg) or - // likely a null terminated string (such as `strcpy`, `strcat`) + // flows into likely null terminated string argument (such as `strcpy`, `strcat`) af.hasArrayWithUnknownSize(arg) + or + // flows into string argument to a formatting function (such as `printf`) + exists(int n, FormatLiteral fl | + fc.getArgument(arg) = fc.(FormattingFunctionCall).getConversionArgument(n) and + fl = fc.(FormattingFunctionCall).getFormat() and + fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc + not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p` + not fl.hasPrecision(n) // exclude: `%.*s` + ) ) ) and msg = "This allocation does not include space to null-terminate the string." diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 41d7a1401b5..668512cecde 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -335,6 +335,12 @@ private Element adjustedSink(DataFlow::Node sink) { // For compatibility, send flow into a `NotExpr` even if it's part of a // short-circuiting condition and thus might get skipped. result.(NotExpr).getOperand() = sink.asExpr() + or + // Taint postfix and prefix crement operations when their operand is tainted. + result.(CrementOperation).getAnOperand() = sink.asExpr() + or + // Taint `e1 += e2`, `e &= e2` and friends when `e1` or `e2` is tainted. + result.(AssignOperation).getAnOperand() = sink.asExpr() } predicate tainted(Expr source, Element tainted) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll index ed46d81ac06..4667714d418 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -11,13 +11,19 @@ cached private newtype TOperand = TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) + 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) + not Construction::isInCycle(useInstr) and + ( + strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1 + or + tag instanceof UnmodeledUseOperandTag + ) } or TPhiOperand( PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll index 9e5e74012cd..28042886742 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -2,10 +2,10 @@ private import ValueNumberingImports private import cpp newtype TValueNumber = - TVariableAddressValueNumber(IRFunction irFunc, IRVariable var) { - variableAddressValueNumber(_, irFunc, var) + TVariableAddressValueNumber(IRFunction irFunc, Language::AST ast) { + variableAddressValueNumber(_, irFunc, ast) } or - TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) { + TInitializeParameterValueNumber(IRFunction irFunc, Language::AST var) { initializeParameterValueNumber(_, irFunc, var) } or TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or @@ -100,17 +100,23 @@ private predicate numberableInstruction(Instruction instr) { } private predicate variableAddressValueNumber( - VariableAddressInstruction instr, IRFunction irFunc, IRVariable var + VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast ) { instr.getEnclosingIRFunction() = irFunc and - instr.getIRVariable() = var + // The underlying AST element is used as value-numbering key instead of the + // `IRVariable` to work around a problem where a variable or expression with + // multiple types gives rise to multiple `IRVariable`s. + instr.getIRVariable().getAST() = ast } private predicate initializeParameterValueNumber( - InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var + InitializeParameterInstruction instr, IRFunction irFunc, Language::AST var ) { instr.getEnclosingIRFunction() = irFunc and - instr.getIRVariable() = var + // The underlying AST element is used as value-numbering key instead of the + // `IRVariable` to work around a problem where a variable or expression with + // multiple types gives rise to multiple `IRVariable`s. + instr.getIRVariable().getAST() = var } private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) { @@ -236,12 +242,12 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) { exists(IRFunction irFunc | irFunc = instr.getEnclosingIRFunction() and ( - exists(IRVariable var | - variableAddressValueNumber(instr, irFunc, var) and - result = TVariableAddressValueNumber(irFunc, var) + exists(Language::AST ast | + variableAddressValueNumber(instr, irFunc, ast) and + result = TVariableAddressValueNumber(irFunc, ast) ) or - exists(IRVariable var | + exists(Language::AST var | initializeParameterValueNumber(instr, irFunc, var) and result = TInitializeParameterValueNumber(irFunc, var) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll index ed46d81ac06..4667714d418 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -11,13 +11,19 @@ cached private newtype TOperand = TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) + 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) + not Construction::isInCycle(useInstr) and + ( + strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1 + or + tag instanceof UnmodeledUseOperandTag + ) } or TPhiOperand( PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 9e5e74012cd..28042886742 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -2,10 +2,10 @@ private import ValueNumberingImports private import cpp newtype TValueNumber = - TVariableAddressValueNumber(IRFunction irFunc, IRVariable var) { - variableAddressValueNumber(_, irFunc, var) + TVariableAddressValueNumber(IRFunction irFunc, Language::AST ast) { + variableAddressValueNumber(_, irFunc, ast) } or - TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) { + TInitializeParameterValueNumber(IRFunction irFunc, Language::AST var) { initializeParameterValueNumber(_, irFunc, var) } or TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or @@ -100,17 +100,23 @@ private predicate numberableInstruction(Instruction instr) { } private predicate variableAddressValueNumber( - VariableAddressInstruction instr, IRFunction irFunc, IRVariable var + VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast ) { instr.getEnclosingIRFunction() = irFunc and - instr.getIRVariable() = var + // The underlying AST element is used as value-numbering key instead of the + // `IRVariable` to work around a problem where a variable or expression with + // multiple types gives rise to multiple `IRVariable`s. + instr.getIRVariable().getAST() = ast } private predicate initializeParameterValueNumber( - InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var + InitializeParameterInstruction instr, IRFunction irFunc, Language::AST var ) { instr.getEnclosingIRFunction() = irFunc and - instr.getIRVariable() = var + // The underlying AST element is used as value-numbering key instead of the + // `IRVariable` to work around a problem where a variable or expression with + // multiple types gives rise to multiple `IRVariable`s. + instr.getIRVariable().getAST() = var } private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) { @@ -236,12 +242,12 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) { exists(IRFunction irFunc | irFunc = instr.getEnclosingIRFunction() and ( - exists(IRVariable var | - variableAddressValueNumber(instr, irFunc, var) and - result = TVariableAddressValueNumber(irFunc, var) + exists(Language::AST ast | + variableAddressValueNumber(instr, irFunc, ast) and + result = TVariableAddressValueNumber(irFunc, ast) ) or - exists(IRVariable var | + exists(Language::AST var | initializeParameterValueNumber(instr, irFunc, var) and result = TInitializeParameterValueNumber(irFunc, var) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll index ed46d81ac06..4667714d418 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -11,13 +11,19 @@ cached private newtype TOperand = TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) + 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) + not Construction::isInCycle(useInstr) and + ( + strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1 + or + tag instanceof UnmodeledUseOperandTag + ) } or TPhiOperand( PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 9e5e74012cd..28042886742 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -2,10 +2,10 @@ private import ValueNumberingImports private import cpp newtype TValueNumber = - TVariableAddressValueNumber(IRFunction irFunc, IRVariable var) { - variableAddressValueNumber(_, irFunc, var) + TVariableAddressValueNumber(IRFunction irFunc, Language::AST ast) { + variableAddressValueNumber(_, irFunc, ast) } or - TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) { + TInitializeParameterValueNumber(IRFunction irFunc, Language::AST var) { initializeParameterValueNumber(_, irFunc, var) } or TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or @@ -100,17 +100,23 @@ private predicate numberableInstruction(Instruction instr) { } private predicate variableAddressValueNumber( - VariableAddressInstruction instr, IRFunction irFunc, IRVariable var + VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast ) { instr.getEnclosingIRFunction() = irFunc and - instr.getIRVariable() = var + // The underlying AST element is used as value-numbering key instead of the + // `IRVariable` to work around a problem where a variable or expression with + // multiple types gives rise to multiple `IRVariable`s. + instr.getIRVariable().getAST() = ast } private predicate initializeParameterValueNumber( - InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var + InitializeParameterInstruction instr, IRFunction irFunc, Language::AST var ) { instr.getEnclosingIRFunction() = irFunc and - instr.getIRVariable() = var + // The underlying AST element is used as value-numbering key instead of the + // `IRVariable` to work around a problem where a variable or expression with + // multiple types gives rise to multiple `IRVariable`s. + instr.getIRVariable().getAST() = var } private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) { @@ -236,12 +242,12 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) { exists(IRFunction irFunc | irFunc = instr.getEnclosingIRFunction() and ( - exists(IRVariable var | - variableAddressValueNumber(instr, irFunc, var) and - result = TVariableAddressValueNumber(irFunc, var) + exists(Language::AST ast | + variableAddressValueNumber(instr, irFunc, ast) and + result = TVariableAddressValueNumber(irFunc, ast) ) or - exists(IRVariable var | + exists(Language::AST var | initializeParameterValueNumber(instr, irFunc, var) and result = TInitializeParameterValueNumber(irFunc, var) ) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/NoSpaceForZeroTerminator.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/NoSpaceForZeroTerminator.expected index de52927e1e8..1476b2c7d95 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/NoSpaceForZeroTerminator.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/NoSpaceForZeroTerminator.expected @@ -5,6 +5,7 @@ | test.c:49:20:49:25 | call to malloc | This allocation does not include space to null-terminate the string. | | test.cpp:24:35:24:40 | call to malloc | This allocation does not include space to null-terminate the string. | | test.cpp:45:28:45:33 | call to malloc | This allocation does not include space to null-terminate the string. | +| test.cpp:55:28:55:33 | call to malloc | This allocation does not include space to null-terminate the string. | | test.cpp:63:28:63:33 | call to malloc | This allocation does not include space to null-terminate the string. | | test.cpp:71:28:71:33 | call to malloc | This allocation does not include space to null-terminate the string. | | test.cpp:79:28:79:33 | call to malloc | This allocation does not include space to null-terminate the string. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/test.cpp index b0db8dea6ef..996938c6324 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-131/semmle/NoSpaceForZeroTerminator/test.cpp @@ -51,7 +51,7 @@ void decode(char *dest, char *src); void wdecode(wchar_t *dest, wchar_t *src); void bad4(char *str) { - // BAD -- zero-termination proved by wprintf (as parameter) [NOT DETECTED] + // BAD -- zero-termination proved by wprintf (as parameter) char *buffer = (char *)malloc(strlen(str)); decode(buffer, str); wprintf(L"%s", buffer); @@ -107,3 +107,19 @@ void bad9(wchar_t *wstr) { wcscpy(wbuffer, wstr); delete wbuffer; } + +void good3(char *str) { + // GOOD -- zero-termination not required for this printf + char *buffer = (char *)malloc(strlen(str)); + decode(buffer, str); + wprintf(L"%p", buffer); + free(buffer); +} + +void good4(char *str) { + // GOOD -- zero-termination not required for this printf + char *buffer = (char *)malloc(strlen(str)); + decode(buffer, str); + wprintf(L"%.*s", strlen(str), buffer); + free(buffer); +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs index a08019ce338..a4b1a4beb09 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs @@ -90,6 +90,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions public override InitializerExpressionSyntax Initializer => Syntax.Initializer; + protected override void PopulateExpression(TextWriter trapFile) + { + base.PopulateExpression(trapFile); + trapFile.stackalloc_array_creation(this); + } + public static Expression Create(ExpressionNodeInfo info) => new StackAllocArrayCreation(info).TryPopulate(); } @@ -103,6 +109,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1)); trapFile.implicitly_typed_array_creation(this); + trapFile.stackalloc_array_creation(this); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs index e83cd689596..6d0f14a014e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using Microsoft.CodeAnalysis; @@ -9,10 +10,12 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(Location); - trapFile.Write('_'); - trapFile.Write(symbol.Name); - trapFile.Write(";localvar"); + throw new InvalidOperationException(); + } + + public override void WriteQuotedId(TextWriter trapFile) + { + trapFile.Write('*'); } public override void Populate(TextWriter trapFile) { } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index d263a0e2868..4b24833337c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -466,6 +466,11 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("specific_type_parameter_nullability", constraints, baseType, nullability); } + internal static void stackalloc_array_creation(this TextWriter trapFile, Expression array) + { + trapFile.WriteTuple("stackalloc_array_creation", array); + } + internal static void stmt_location(this TextWriter trapFile, Statement stmt, Location location) { trapFile.WriteTuple("stmt_location", stmt, location); diff --git a/csharp/extractor/Semmle.Extraction/Symbol.cs b/csharp/extractor/Semmle.Extraction/Symbol.cs index 23c340b425e..57bb1ed11ad 100644 --- a/csharp/extractor/Semmle.Extraction/Symbol.cs +++ b/csharp/extractor/Semmle.Extraction/Symbol.cs @@ -53,7 +53,7 @@ namespace Semmle.Extraction public abstract void WriteId(System.IO.TextWriter trapFile); - public void WriteQuotedId(TextWriter trapFile) + public virtual void WriteQuotedId(TextWriter trapFile) { trapFile.Write("@\""); WriteId(trapFile); diff --git a/csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql b/csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql index 2f2b29d33a6..7b875faae67 100644 --- a/csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql +++ b/csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql @@ -11,6 +11,7 @@ import semmle.code.csharp.serialization.Serialization import semmle.code.csharp.controlflow.Guards +import semmle.code.csharp.dataflow.DataFlow /** * The result is a write to the field `f`, assigning it the value @@ -29,7 +30,11 @@ GuardedExpr checkedWrite(Field f, Variable v, IfStmt check) { Expr uncheckedWrite(Callable callable, Field f) { result = f.getAnAssignedValue() and result.getEnclosingCallable() = callable and - not callable.calls*(checkedWrite(f, _, _).getEnclosingCallable()) + not callable.calls*(checkedWrite(f, _, _).getEnclosingCallable()) and + // Exclude object creations because they were not deserialized + not exists(Expr src | DataFlow::localExprFlow(src, result) | + src instanceof ObjectCreation or src.hasValue() + ) } from BinarySerializableType t, Field f, IfStmt check, Expr write, Expr unsafeWrite diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll b/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll index 164a77f584b..f0aebc389d0 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll @@ -372,6 +372,13 @@ class ArrayCreation extends Expr, @array_creation_expr { override string toString() { result = "array creation of type " + this.getType().getName() } } +/** + * A `stackalloc` array creation, for example `stackalloc char[] { 'x', 'y' }`. + */ +class Stackalloc extends ArrayCreation { + Stackalloc() { stackalloc_array_creation(this) } +} + /** * An anonymous function. Either a lambda expression (`LambdaExpr`) or an * anonymous method expression (`AnonymousMethodExpr`). diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll index ed46d81ac06..4667714d418 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll @@ -11,13 +11,19 @@ cached private newtype TOperand = TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) + 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) + not Construction::isInCycle(useInstr) and + ( + strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1 + or + tag instanceof UnmodeledUseOperandTag + ) } or TPhiOperand( PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll index ed46d81ac06..4667714d418 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll @@ -11,13 +11,19 @@ cached private newtype TOperand = TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) + 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) + not Construction::isInCycle(useInstr) and + ( + strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1 + or + tag instanceof UnmodeledUseOperandTag + ) } or TPhiOperand( PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index cf21dd4151d..ad622770b3c 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1084,6 +1084,9 @@ implicitly_typed_array_creation( explicitly_sized_array_creation( unique int id: @array_creation_expr ref); +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + mutator_invocation_mode( unique int id: @operator_invocation_expr ref, int mode: int ref /* prefix = 1, postfix = 2*/); diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 00ad0d841f9..23525a6a24e 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -28440,6 +28440,17 @@ +stackalloc_array_creation +50 + + +id +50 + + + + + mutator_invocation_mode 0 diff --git a/csharp/ql/test/library-tests/csharp7.3/ArrayCreations.expected b/csharp/ql/test/library-tests/csharp7.3/ArrayCreations.expected index 7d3101e1522..df5891b0b8e 100644 --- a/csharp/ql/test/library-tests/csharp7.3/ArrayCreations.expected +++ b/csharp/ql/test/library-tests/csharp7.3/ArrayCreations.expected @@ -1,6 +1,20 @@ +arrayCreation | csharp73.cs:9:20:9:49 | array creation of type Char* | 0 | csharp73.cs:9:20:9:49 | 2 | | csharp73.cs:10:20:10:45 | array creation of type Char* | 0 | csharp73.cs:10:36:10:36 | 1 | | csharp73.cs:11:20:11:37 | array creation of type Char[] | 0 | csharp73.cs:11:20:11:37 | 1 | | csharp73.cs:12:20:12:38 | array creation of type Char* | 0 | csharp73.cs:12:36:12:37 | 10 | | csharp73.cs:13:20:13:31 | array creation of type Char[] | 0 | csharp73.cs:13:29:13:30 | 10 | | csharp73.cs:22:23:22:33 | array creation of type Int32[] | 0 | csharp73.cs:22:31:22:32 | 10 | +arrayElement +| csharp73.cs:9:20:9:49 | array creation of type Char* | 0 | csharp73.cs:9:40:9:42 | x | +| csharp73.cs:9:20:9:49 | array creation of type Char* | 1 | csharp73.cs:9:45:9:47 | y | +| csharp73.cs:10:20:10:45 | array creation of type Char* | 0 | csharp73.cs:10:41:10:43 | x | +| csharp73.cs:11:20:11:37 | array creation of type Char[] | 0 | csharp73.cs:11:33:11:35 | x | +| csharp73.cs:14:20:14:43 | array creation of type Int32* | 0 | csharp73.cs:14:35:14:35 | 1 | +| csharp73.cs:14:20:14:43 | array creation of type Int32* | 1 | csharp73.cs:14:38:14:38 | 2 | +| csharp73.cs:14:20:14:43 | array creation of type Int32* | 2 | csharp73.cs:14:41:14:41 | 3 | +stackalloc +| csharp73.cs:9:20:9:49 | array creation of type Char* | +| csharp73.cs:10:20:10:45 | array creation of type Char* | +| csharp73.cs:12:20:12:38 | array creation of type Char* | +| csharp73.cs:14:20:14:43 | array creation of type Int32* | diff --git a/csharp/ql/test/library-tests/csharp7.3/ArrayCreations.ql b/csharp/ql/test/library-tests/csharp7.3/ArrayCreations.ql index 38aceeda8c3..4fc41227fab 100644 --- a/csharp/ql/test/library-tests/csharp7.3/ArrayCreations.ql +++ b/csharp/ql/test/library-tests/csharp7.3/ArrayCreations.ql @@ -1,4 +1,11 @@ import csharp -from ArrayCreation creation, int i -select creation, i, creation.getLengthArgument(i) +query predicate arrayCreation(ArrayCreation creation, int i, Expr length) { + length = creation.getLengthArgument(i) +} + +query predicate arrayElement(ArrayCreation array, int i, Expr element) { + element = array.getInitializer().getElement(i) +} + +query predicate stackalloc(Stackalloc a) { any() } diff --git a/csharp/ql/test/library-tests/csharp7.3/ArrayElements.expected b/csharp/ql/test/library-tests/csharp7.3/ArrayElements.expected deleted file mode 100644 index cd7bcefbf5f..00000000000 --- a/csharp/ql/test/library-tests/csharp7.3/ArrayElements.expected +++ /dev/null @@ -1,7 +0,0 @@ -| csharp73.cs:9:20:9:49 | array creation of type Char* | 0 | csharp73.cs:9:40:9:42 | x | -| csharp73.cs:9:20:9:49 | array creation of type Char* | 1 | csharp73.cs:9:45:9:47 | y | -| csharp73.cs:10:20:10:45 | array creation of type Char* | 0 | csharp73.cs:10:41:10:43 | x | -| csharp73.cs:11:20:11:37 | array creation of type Char[] | 0 | csharp73.cs:11:33:11:35 | x | -| csharp73.cs:14:20:14:43 | array creation of type Int32* | 0 | csharp73.cs:14:35:14:35 | 1 | -| csharp73.cs:14:20:14:43 | array creation of type Int32* | 1 | csharp73.cs:14:38:14:38 | 2 | -| csharp73.cs:14:20:14:43 | array creation of type Int32* | 2 | csharp73.cs:14:41:14:41 | 3 | diff --git a/csharp/ql/test/library-tests/csharp7.3/ArrayElements.ql b/csharp/ql/test/library-tests/csharp7.3/ArrayElements.ql deleted file mode 100644 index edc11606e83..00000000000 --- a/csharp/ql/test/library-tests/csharp7.3/ArrayElements.ql +++ /dev/null @@ -1,4 +0,0 @@ -import csharp - -from ArrayCreation array, int i -select array, i, array.getInitializer().getElement(i) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-020/RuntimeChecksBypass.cs b/csharp/ql/test/query-tests/Security Features/CWE-020/RuntimeChecksBypass.cs index 76d8fda8e8f..ffc89563916 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-020/RuntimeChecksBypass.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-020/RuntimeChecksBypass.cs @@ -10,14 +10,14 @@ public class Test1 { if (v == "valid") { - f = v /* safe write */; + f = v; // GOOD } } [OnDeserializing] public void Deserialize() { - f = "invalid" /* unsafe write */; + f = $"invalid"; // BAD } } @@ -30,19 +30,19 @@ public class Test2 { if (v == "valid") { - f = v /* safe write */; + f = v; // GOOD } } [OnDeserializing] public void Deserialize() { - var v = "invalid"; - f = v /* unsafe write -- false negative */; + var v = $"invalid"; + f = v; // BAD: False negative if (v == "valid") { - f = v; /* safe write */ + f = v; // GOOD } } } @@ -56,25 +56,25 @@ public class Test3 { if (v == "valid") { - f = v /* safe write */; + f = v; // GOOD } } [OnDeserializing] public void Deserialize() { - var v = "invalid"; - f = v /* unsafe write -- false negative */; + var v = $"invalid"; + f = v; // GOOD: False negative Assign(v); } private void Assign(string v) { - f = v /* unsafe write -- false negative */; + f = v; // GOOD: False negative if (v == "valid") { - f = v /* safe write */; + f = v; // GOOD } } } @@ -88,21 +88,21 @@ public class Test4 { if (v == "valid") { - f = v /* safe write */; + f = v; // GOOD } } [OnDeserializing] public void Deserialize() { - var v = "invalid"; + var v = $"invalid"; if (v == "valid") Assign(v); } private void Assign(string v) { - f = v /* safe write */; + f = v; // GOOD } } @@ -115,13 +115,13 @@ public class Test5 : ISerializable { if (age < 0) throw new ArgumentException(nameof(age)); - Age = age /* safe write */; + Age = age; // GOOD } [OnDeserializing] void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { - Age = info.GetInt32("age"); /* unsafe write */; + Age = info.GetInt32("age"); // BAD } } @@ -134,7 +134,7 @@ public class Test6 : ISerializable { if (age < 0) throw new ArgumentException(nameof(age)); - Age = age /* safe write */; + Age = age; // GOOD } [OnDeserializing] @@ -143,7 +143,7 @@ public class Test6 : ISerializable int age = info.GetInt32("age"); if (age < 0) throw new SerializationException("age"); - Age = age; /* safe write */; + Age = age; // GOOD } } @@ -156,7 +156,7 @@ public class Test7 : ISerializable { if (age < 0) throw new ArgumentException(nameof(age)); - Age = age /* safe write */; + Age = age; // GOOD } [OnDeserializing] @@ -165,6 +165,27 @@ public class Test7 : ISerializable int age = info.GetInt32("age"); if (false) throw new SerializationException("age"); - Age = age; /* unsafe write */; + Age = age; // BAD + } +} + +[Serializable] +public class Test8 : ISerializable +{ + string Options; + + public int Age; + + public Test8(string options) + { + if (options == null) + throw new ArgumentNullException(nameof(options)); + Options = options; // GOOD + } + + [OnDeserializing] + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + Options = new string(""); // GOOD: A created object } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-020/RuntimeChecksbypass.expected b/csharp/ql/test/query-tests/Security Features/CWE-020/RuntimeChecksbypass.expected index e9b03d3aed2..637720fbc64 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-020/RuntimeChecksbypass.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-020/RuntimeChecksbypass.expected @@ -1,4 +1,4 @@ -| RuntimeChecksBypass.cs:20:13:20:21 | "invalid" | This write to $@ may be circumventing a $@. | RuntimeChecksBypass.cs:7:19:7:19 | f | f | RuntimeChecksBypass.cs:11:9:14:9 | if (...) ... | check | +| RuntimeChecksBypass.cs:20:13:20:22 | $"..." | This write to $@ may be circumventing a $@. | RuntimeChecksBypass.cs:7:19:7:19 | f | f | RuntimeChecksBypass.cs:11:9:14:9 | if (...) ... | check | | RuntimeChecksBypass.cs:124:15:124:34 | call to method GetInt32 | This write to $@ may be circumventing a $@. | RuntimeChecksBypass.cs:112:16:112:18 | Age | Age | RuntimeChecksBypass.cs:116:9:117:53 | if (...) ... | check | | RuntimeChecksBypass.cs:168:15:168:17 | access to local variable age | This write to $@ may be circumventing a $@. | RuntimeChecksBypass.cs:153:16:153:18 | Age | Age | RuntimeChecksBypass.cs:157:9:158:53 | if (...) ... | check | | RuntimeChecksBypassBad.cs:19:15:19:34 | call to method GetInt32 | This write to $@ may be circumventing a $@. | RuntimeChecksBypassBad.cs:7:16:7:18 | Age | Age | RuntimeChecksBypassBad.cs:11:9:12:53 | if (...) ... | check | diff --git a/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/old.dbscheme b/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/old.dbscheme new file mode 100644 index 00000000000..cf21dd4151d --- /dev/null +++ b/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/old.dbscheme @@ -0,0 +1,1890 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +is_generic(unique int id: @generic ref); + +is_constructed(unique int id: @generic ref); + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + unique int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/semmlecode.csharp.dbscheme b/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..ad622770b3c --- /dev/null +++ b/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/semmlecode.csharp.dbscheme @@ -0,0 +1,1893 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +is_generic(unique int id: @generic ref); + +is_constructed(unique int id: @generic ref); + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + unique int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/upgrade.properties b/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/upgrade.properties new file mode 100644 index 00000000000..cc8337a2d1c --- /dev/null +++ b/csharp/upgrades/cf21dd4151d107ab649a2a218e7f52e355c43906/upgrade.properties @@ -0,0 +1,2 @@ +description: Adds information about `stackalloc` array creations +compatibility: backwards \ No newline at end of file diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index bddc206aa82..98b8b97e153 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -113,7 +113,7 @@ Then we can make the source more specific, for example an access to a public par where fileReader.getDeclaringType().hasQualifiedName("java.io", "FileReader") and call.getCallee() = fileReader and - DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(fc.getArgument(0))) + DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(call.getArgument(0))) select p The following example finds calls to formatting functions where the format string is not hard-coded. diff --git a/python/ql/src/semmle/python/web/bottle/Request.qll b/python/ql/src/semmle/python/web/bottle/Request.qll index 767b3d0d25b..e4997154cbc 100644 --- a/python/ql/src/semmle/python/web/bottle/Request.qll +++ b/python/ql/src/semmle/python/web/bottle/Request.qll @@ -21,7 +21,7 @@ class BottleRequestKind extends TaintKind { } } -private class RequestSource extends TaintSource { +private class RequestSource extends HttpRequestTaintSource { RequestSource() { this.(ControlFlowNode).pointsTo(theBottleRequestObject()) } override predicate isSourceOf(TaintKind kind) { kind instanceof BottleRequestKind } @@ -69,7 +69,7 @@ class UntrustedFile extends TaintKind { // Move UntrustedFile to shared location // /** Parameter to a bottle request handler function */ -class BottleRequestParameter extends TaintSource { +class BottleRequestParameter extends HttpRequestTaintSource { BottleRequestParameter() { exists(BottleRoute route | route.getNamedArgument() = this.(ControlFlowNode).getNode()) } diff --git a/python/ql/src/semmle/python/web/cherrypy/Request.qll b/python/ql/src/semmle/python/web/cherrypy/Request.qll index 2ae897a7f29..2440a2710f6 100644 --- a/python/ql/src/semmle/python/web/cherrypy/Request.qll +++ b/python/ql/src/semmle/python/web/cherrypy/Request.qll @@ -25,7 +25,7 @@ class CherryPyRequest extends TaintKind { } } -class CherryPyExposedFunctionParameter extends TaintSource { +class CherryPyExposedFunctionParameter extends HttpRequestTaintSource { CherryPyExposedFunctionParameter() { exists(Parameter p | p = any(CherryPyExposedFunction f).getAnArg() and @@ -39,7 +39,7 @@ class CherryPyExposedFunctionParameter extends TaintSource { override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } } -class CherryPyRequestSource extends TaintSource { +class CherryPyRequestSource extends HttpRequestTaintSource { CherryPyRequestSource() { this.(ControlFlowNode).pointsTo(Value::named("cherrypy.request")) } override predicate isSourceOf(TaintKind kind) { kind instanceof CherryPyRequest } diff --git a/python/ql/src/semmle/python/web/django/Response.qll b/python/ql/src/semmle/python/web/django/Response.qll index 21995daa024..a810d481a8b 100644 --- a/python/ql/src/semmle/python/web/django/Response.qll +++ b/python/ql/src/semmle/python/web/django/Response.qll @@ -18,8 +18,8 @@ private ClassValue theDjangoHttpResponseClass() { not result = theDjangoHttpRedirectClass() } -/** Instantiation of a django response. */ -class DjangoResponseSource extends TaintSource { +/** internal class used for tracking a django response. */ +private class DjangoResponseSource extends TaintSource { DjangoResponseSource() { exists(ClassValue cls | cls.getASuperType() = theDjangoHttpResponseClass() and diff --git a/python/ql/src/semmle/python/web/falcon/Request.qll b/python/ql/src/semmle/python/web/falcon/Request.qll index 2df10d1afc4..13f3fa4c441 100644 --- a/python/ql/src/semmle/python/web/falcon/Request.qll +++ b/python/ql/src/semmle/python/web/falcon/Request.qll @@ -35,7 +35,7 @@ class FalconRequest extends TaintKind { } } -class FalconRequestParameter extends TaintSource { +class FalconRequestParameter extends HttpRequestTaintSource { FalconRequestParameter() { exists(FalconHandlerFunction f | f.getRequest() = this.(ControlFlowNode).getNode()) } diff --git a/python/ql/src/semmle/python/web/falcon/Response.qll b/python/ql/src/semmle/python/web/falcon/Response.qll index 8eff15dd53c..ab7798cc2cb 100644 --- a/python/ql/src/semmle/python/web/falcon/Response.qll +++ b/python/ql/src/semmle/python/web/falcon/Response.qll @@ -9,7 +9,8 @@ class FalconResponse extends TaintKind { FalconResponse() { this = "falcon.response" } } -class FalconResponseParameter extends TaintSource { +/** Only used internally to track the response parameter */ +private class FalconResponseParameter extends TaintSource { FalconResponseParameter() { exists(FalconHandlerFunction f | f.getResponse() = this.(ControlFlowNode).getNode()) } diff --git a/python/ql/src/semmle/python/web/flask/Request.qll b/python/ql/src/semmle/python/web/flask/Request.qll index e27e54c722f..8dbc3a5ba42 100644 --- a/python/ql/src/semmle/python/web/flask/Request.qll +++ b/python/ql/src/semmle/python/web/flask/Request.qll @@ -47,7 +47,7 @@ class FlaskRequestArgs extends HttpRequestTaintSource { } /** Source of dictionary whose values are externally controlled */ -class FlaskRequestJson extends TaintSource { +class FlaskRequestJson extends HttpRequestTaintSource { FlaskRequestJson() { flask_request_attr(this, "json") } override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalJsonKind } diff --git a/python/ql/src/semmle/python/web/pyramid/Request.qll b/python/ql/src/semmle/python/web/pyramid/Request.qll index 2514e77d5ac..dc5be31e68a 100644 --- a/python/ql/src/semmle/python/web/pyramid/Request.qll +++ b/python/ql/src/semmle/python/web/pyramid/Request.qll @@ -11,7 +11,7 @@ class PyramidRequest extends BaseWebobRequest { } /** Source of pyramid request objects */ -class PyramidViewArgument extends TaintSource { +class PyramidViewArgument extends HttpRequestTaintSource { PyramidViewArgument() { exists(Function view_func | is_pyramid_view_function(view_func) and diff --git a/python/ql/src/semmle/python/web/tornado/Redirect.qll b/python/ql/src/semmle/python/web/tornado/Redirect.qll index cf213a5b044..2d2c39907eb 100644 --- a/python/ql/src/semmle/python/web/tornado/Redirect.qll +++ b/python/ql/src/semmle/python/web/tornado/Redirect.qll @@ -13,14 +13,16 @@ import Tornado /** * Represents an argument to the `tornado.redirect` function. */ -class TornadoRedirect extends HttpRedirectTaintSink { - override string toString() { result = "tornado.redirect" } +class TornadoHttpRequestHandlerRedirect extends HttpRedirectTaintSink { + override string toString() { result = "tornado.HttpRequestHandler.redirect" } - TornadoRedirect() { + TornadoHttpRequestHandlerRedirect() { exists(CallNode call, ControlFlowNode node | node = call.getFunction().(AttrNode).getObject("redirect") and isTornadoRequestHandlerInstance(node) and - this = call.getAnArg() + this = call.getArg(0) ) } + + override predicate sinks(TaintKind kind) { kind instanceof StringKind } } diff --git a/python/ql/src/semmle/python/web/tornado/Request.qll b/python/ql/src/semmle/python/web/tornado/Request.qll index a5a6c752f8e..66c77d4f269 100644 --- a/python/ql/src/semmle/python/web/tornado/Request.qll +++ b/python/ql/src/semmle/python/web/tornado/Request.qll @@ -30,7 +30,7 @@ class TornadoRequest extends TaintKind { } } -class TornadoRequestSource extends TaintSource { +class TornadoRequestSource extends HttpRequestTaintSource { TornadoRequestSource() { isTornadoRequestHandlerInstance(this.(AttrNode).getObject("request")) } override string toString() { result = "Tornado request source" } @@ -38,7 +38,7 @@ class TornadoRequestSource extends TaintSource { override predicate isSourceOf(TaintKind kind) { kind instanceof TornadoRequest } } -class TornadoExternalInputSource extends TaintSource { +class TornadoExternalInputSource extends HttpRequestTaintSource { TornadoExternalInputSource() { exists(string name | name = "get_argument" or @@ -55,7 +55,7 @@ class TornadoExternalInputSource extends TaintSource { override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } } -class TornadoExternalInputListSource extends TaintSource { +class TornadoExternalInputListSource extends HttpRequestTaintSource { TornadoExternalInputListSource() { exists(string name | name = "get_arguments" or diff --git a/python/ql/src/semmle/python/web/tornado/Response.qll b/python/ql/src/semmle/python/web/tornado/Response.qll index e6312c49549..2c2da1a4c70 100644 --- a/python/ql/src/semmle/python/web/tornado/Response.qll +++ b/python/ql/src/semmle/python/web/tornado/Response.qll @@ -24,11 +24,8 @@ class TornadoConnectionWrite extends HttpResponseTaintSink { TornadoConnectionWrite() { exists(CallNode call, ControlFlowNode conn | conn = call.getFunction().(AttrNode).getObject("write") and - this = call.getAnArg() - | + this = call.getAnArg() and exists(TornadoConnection tc | tc.taints(conn)) - or - isTornadoRequestHandlerInstance(conn) ) } @@ -36,27 +33,13 @@ class TornadoConnectionWrite extends HttpResponseTaintSink { } class TornadoHttpRequestHandlerWrite extends HttpResponseTaintSink { - override string toString() { result = "tornado.HttpRequesHandler.write" } + override string toString() { result = "tornado.HttpRequestHandler.write" } TornadoHttpRequestHandlerWrite() { exists(CallNode call, ControlFlowNode node | node = call.getFunction().(AttrNode).getObject("write") and - isTornadoRequestHandlerInstance(node) and - this = call.getAnArg() - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof StringKind } -} - -class TornadoHttpRequestHandlerRedirect extends HttpResponseTaintSink { - override string toString() { result = "tornado.HttpRequesHandler.redirect" } - - TornadoHttpRequestHandlerRedirect() { - exists(CallNode call, ControlFlowNode node | - node = call.getFunction().(AttrNode).getObject("redirect") and - isTornadoRequestHandlerInstance(node) and - this = call.getArg(0) + this = call.getAnArg() and + isTornadoRequestHandlerInstance(node) ) } diff --git a/python/ql/src/semmle/python/web/turbogears/Request.qll b/python/ql/src/semmle/python/web/turbogears/Request.qll index dc7ef63ab56..92d5728b91f 100644 --- a/python/ql/src/semmle/python/web/turbogears/Request.qll +++ b/python/ql/src/semmle/python/web/turbogears/Request.qll @@ -1,5 +1,6 @@ import python import semmle.python.security.strings.Untrusted +import semmle.python.web.Http import TurboGears private class ValidatedMethodParameter extends Parameter { @@ -11,7 +12,7 @@ private class ValidatedMethodParameter extends Parameter { } } -class UnvalidatedControllerMethodParameter extends TaintSource { +class UnvalidatedControllerMethodParameter extends HttpRequestTaintSource { UnvalidatedControllerMethodParameter() { exists(Parameter p | any(TurboGearsControllerMethod m | not m.getName() = "onerror").getAnArg() = p and diff --git a/python/ql/src/semmle/python/web/turbogears/Response.qll b/python/ql/src/semmle/python/web/turbogears/Response.qll index ddd3d6f711f..cab083bf8b7 100644 --- a/python/ql/src/semmle/python/web/turbogears/Response.qll +++ b/python/ql/src/semmle/python/web/turbogears/Response.qll @@ -5,6 +5,8 @@ import semmle.python.web.Http import TurboGears class ControllerMethodReturnValue extends HttpResponseTaintSink { + override string toString() { result = "TurboGears ControllerMethodReturnValue" } + ControllerMethodReturnValue() { exists(TurboGearsControllerMethod m | m.getAReturnValueFlowNode() = this and @@ -16,6 +18,8 @@ class ControllerMethodReturnValue extends HttpResponseTaintSink { } class ControllerMethodTemplatedReturnValue extends HttpResponseTaintSink { + override string toString() { result = "TurboGears ControllerMethodTemplatedReturnValue" } + ControllerMethodTemplatedReturnValue() { exists(TurboGearsControllerMethod m | m.getAReturnValueFlowNode() = this and diff --git a/python/ql/src/semmle/python/web/twisted/Request.qll b/python/ql/src/semmle/python/web/twisted/Request.qll index 67bb8cedbfe..969392d0eef 100644 --- a/python/ql/src/semmle/python/web/twisted/Request.qll +++ b/python/ql/src/semmle/python/web/twisted/Request.qll @@ -26,7 +26,7 @@ class TwistedRequest extends TaintKind { } } -class TwistedRequestSource extends TaintSource { +class TwistedRequestSource extends HttpRequestTaintSource { TwistedRequestSource() { isTwistedRequestInstance(this) } override string toString() { result = "Twisted request source" } diff --git a/python/ql/src/semmle/python/web/twisted/Response.qll b/python/ql/src/semmle/python/web/twisted/Response.qll index 435960c40ab..b7f67ff6b20 100644 --- a/python/ql/src/semmle/python/web/twisted/Response.qll +++ b/python/ql/src/semmle/python/web/twisted/Response.qll @@ -5,9 +5,9 @@ import semmle.python.security.strings.Basic import Twisted import Request -class TwistedResponse extends TaintSink { +class TwistedResponse extends HttpResponseTaintSink { TwistedResponse() { - exists(PythonFunctionValue func, string name, Return ret | + exists(PythonFunctionValue func, string name | isKnownRequestHandlerMethodName(name) and name = func.getName() and func = getTwistedRequestHandlerMethod(name) and diff --git a/python/ql/test/2/library-tests/six/options b/python/ql/test/2/library-tests/six/options index 8a2bd0171db..55e896b67f2 100644 --- a/python/ql/test/2/library-tests/six/options +++ b/python/ql/test/2/library-tests/six/options @@ -1,2 +1,2 @@ -semmle-extractor-options: --lang=2 --max-import-depth=3 +semmle-extractor-options: --lang=2 --max-import-depth=4 optimize: true diff --git a/python/ql/test/2/library-tests/six/pointsto.expected b/python/ql/test/2/library-tests/six/pointsto.expected index 7b475d40eb7..0e0d568caf3 100644 --- a/python/ql/test/2/library-tests/six/pointsto.expected +++ b/python/ql/test/2/library-tests/six/pointsto.expected @@ -1,3 +1,9 @@ -| six | Module six | -| six.moves | Module six.moves | +| six | Package six | +| six.moves | Package six.moves | +| six.moves.http_client | Module httplib | +| six.moves.http_client.HTTPConnection | class HTTPConnection | | six.moves.range | builtin-class xrange | +| six.moves.urllib | Package six.moves.urllib | +| six.moves.urllib.parse | Module six.moves.urllib_parse | +| six.moves.urllib.parse.urlsplit | Function urlsplit | +| six.moves.zip | builtin-class itertools.izip | diff --git a/python/ql/test/2/library-tests/six/pointsto.ql b/python/ql/test/2/library-tests/six/pointsto.ql index 8104a2e6628..d44761b1b12 100644 --- a/python/ql/test/2/library-tests/six/pointsto.ql +++ b/python/ql/test/2/library-tests/six/pointsto.ql @@ -1,15 +1,11 @@ - import python string longname(Expr e) { result = e.(Name).getId() or - exists(Attribute a | - a = e | - result = longname(a.getObject()) + "." + a.getName() - ) + exists(Attribute a | a = e | result = longname(a.getObject()) + "." + a.getName()) } -from Expr e, Object o -where e.refersTo(o) and e.getLocation().getFile().getShortName() = "test.py" -select longname(e), o.toString() \ No newline at end of file +from Expr e, Value v +where e.pointsTo(v) and e.getLocation().getFile().getShortName() = "test.py" +select longname(e), v.toString() diff --git a/python/ql/test/2/library-tests/six/test.expected b/python/ql/test/2/library-tests/six/test.expected deleted file mode 100644 index 50ad5bc7e57..00000000000 --- a/python/ql/test/2/library-tests/six/test.expected +++ /dev/null @@ -1,268 +0,0 @@ -| Module six | BytesIO | class StringIO | -| Module six | Iterator | class Iterator | -| Module six | MAXSIZE | int() | -| Module six | PY2 | bool True | -| Module six | PY3 | bool False | -| Module six | StringIO | class StringIO | -| Module six | __author__ | str b'Benjamin Peterson ' | -| Module six | __name__ | str b'six' | -| Module six | __version__ | str b'1.5.2' | -| Module six | _add_doc | Function _add_doc | -| Module six | _func_closure | str b'func_closure' | -| Module six | _func_code | str b'func_code' | -| Module six | _func_defaults | str b'func_defaults' | -| Module six | _func_globals | str b'func_globals' | -| Module six | _import_module | Function _import_module | -| Module six | _iteritems | str b'iteritems' | -| Module six | _iterkeys | str b'iterkeys' | -| Module six | _iterlists | str b'iterlists' | -| Module six | _itervalues | str b'itervalues' | -| Module six | _meth_func | str b'im_func' | -| Module six | _meth_self | str b'im_self' | -| Module six | add_metaclass | Function add_metaclass | -| Module six | add_move | Function add_move | -| Module six | advance_iterator | Builtin-function next | -| Module six | b | Function b | -| Module six | binary_type | builtin-class str | -| Module six | byte2int | Function byte2int | -| Module six | callable | Builtin-function callable | -| Module six | callable | Function callable | -| Module six | class_types | Tuple | -| Module six | create_bound_method | Function create_bound_method | -| Module six | exec_ | Function exec_ | -| Module six | get_function_closure | Attribute() | -| Module six | get_function_code | Attribute() | -| Module six | get_function_defaults | Attribute() | -| Module six | get_function_globals | Attribute() | -| Module six | get_method_function | Attribute() | -| Module six | get_method_self | Attribute() | -| Module six | get_unbound_function | Function get_unbound_function | -| Module six | indexbytes | Function indexbytes | -| Module six | int2byte | Builtin-function chr | -| Module six | integer_types | Tuple | -| Module six | iterbytes | Function iterbytes | -| Module six | iteritems | Function iteritems | -| Module six | iterkeys | Function iterkeys | -| Module six | iterlists | Function iterlists | -| Module six | itervalues | Function itervalues | -| Module six | moves | Module six.moves | -| Module six | next | Builtin-function next | -| Module six | operator | Module operator | -| Module six | print_ | Function print_ | -| Module six | remove_move | Function remove_move | -| Module six | reraise | Function reraise | -| Module six | string_types | Tuple | -| Module six | sys | Module sys | -| Module six | text_type | builtin-class unicode | -| Module six | types | Module types | -| Module six | u | Function u | -| Module six | unichr | Builtin-function unichr | -| Module six | with_metaclass | Function with_metaclass | -| Module six.__init__ | BytesIO | class StringIO | -| Module six.__init__ | Iterator | class Iterator | -| Module six.__init__ | MAXSIZE | int() | -| Module six.__init__ | PY2 | bool True | -| Module six.__init__ | PY3 | bool False | -| Module six.__init__ | StringIO | class StringIO | -| Module six.__init__ | __author__ | str b'Benjamin Peterson ' | -| Module six.__init__ | __name__ | str b'six' | -| Module six.__init__ | __version__ | str b'1.5.2' | -| Module six.__init__ | _add_doc | Function _add_doc | -| Module six.__init__ | _func_closure | str b'func_closure' | -| Module six.__init__ | _func_code | str b'func_code' | -| Module six.__init__ | _func_defaults | str b'func_defaults' | -| Module six.__init__ | _func_globals | str b'func_globals' | -| Module six.__init__ | _import_module | Function _import_module | -| Module six.__init__ | _iteritems | str b'iteritems' | -| Module six.__init__ | _iterkeys | str b'iterkeys' | -| Module six.__init__ | _iterlists | str b'iterlists' | -| Module six.__init__ | _itervalues | str b'itervalues' | -| Module six.__init__ | _meth_func | str b'im_func' | -| Module six.__init__ | _meth_self | str b'im_self' | -| Module six.__init__ | add_metaclass | Function add_metaclass | -| Module six.__init__ | add_move | Function add_move | -| Module six.__init__ | advance_iterator | Builtin-function next | -| Module six.__init__ | b | Function b | -| Module six.__init__ | binary_type | builtin-class str | -| Module six.__init__ | byte2int | Function byte2int | -| Module six.__init__ | callable | Builtin-function callable | -| Module six.__init__ | callable | Function callable | -| Module six.__init__ | class_types | Tuple | -| Module six.__init__ | create_bound_method | Function create_bound_method | -| Module six.__init__ | exec_ | Function exec_ | -| Module six.__init__ | get_function_closure | Attribute() | -| Module six.__init__ | get_function_code | Attribute() | -| Module six.__init__ | get_function_defaults | Attribute() | -| Module six.__init__ | get_function_globals | Attribute() | -| Module six.__init__ | get_method_function | Attribute() | -| Module six.__init__ | get_method_self | Attribute() | -| Module six.__init__ | get_unbound_function | Function get_unbound_function | -| Module six.__init__ | indexbytes | Function indexbytes | -| Module six.__init__ | int2byte | Builtin-function chr | -| Module six.__init__ | integer_types | Tuple | -| Module six.__init__ | iterbytes | Function iterbytes | -| Module six.__init__ | iteritems | Function iteritems | -| Module six.__init__ | iterkeys | Function iterkeys | -| Module six.__init__ | iterlists | Function iterlists | -| Module six.__init__ | itervalues | Function itervalues | -| Module six.__init__ | moves | Module six.moves | -| Module six.__init__ | next | Builtin-function next | -| Module six.__init__ | operator | Module operator | -| Module six.__init__ | print_ | Function print_ | -| Module six.__init__ | remove_move | Function remove_move | -| Module six.__init__ | reraise | Function reraise | -| Module six.__init__ | string_types | Tuple | -| Module six.__init__ | sys | Module sys | -| Module six.__init__ | text_type | builtin-class unicode | -| Module six.__init__ | types | Module types | -| Module six.__init__ | u | Function u | -| Module six.__init__ | unichr | Builtin-function unichr | -| Module six.__init__ | with_metaclass | Function with_metaclass | -| Module six.moves | BaseHTTPServer | Module BaseHTTPServer | -| Module six.moves | CGIHTTPServer | Module CGIHTTPServer | -| Module six.moves | PY2 | bool True | -| Module six.moves | PY3 | bool False | -| Module six.moves | SimpleHTTPServer | Module SimpleHTTPServer | -| Module six.moves | StringIO | class StringIO | -| Module six.moves | UserDict | class UserDict | -| Module six.moves | UserList | class UserList | -| Module six.moves | UserString | class UserString | -| Module six.moves | __name__ | str b'six.moves' | -| Module six.moves | _dummy_thread | Module dummy_thread | -| Module six.moves | _thread | Module thread | -| Module six.moves | builtins | Module __builtin__ | -| Module six.moves | cPickle | Module cPickle | -| Module six.moves | cStringIO | Builtin-function StringIO | -| Module six.moves | configparser | Module ConfigParser | -| Module six.moves | copyreg | Module copy_reg | -| Module six.moves | filter | builtin-class itertools.ifilter | -| Module six.moves | filterfalse | builtin-class itertools.ifilterfalse | -| Module six.moves | html_entities | Module htmlentitydefs | -| Module six.moves | html_parser | Module HTMLParser | -| Module six.moves | http_client | Module httplib | -| Module six.moves | http_cookiejar | Module cookielib | -| Module six.moves | http_cookies | Module Cookie | -| Module six.moves | input | Builtin-function raw_input | -| Module six.moves | intern | Builtin-function intern | -| Module six.moves | map | builtin-class itertools.imap | -| Module six.moves | queue | Module Queue | -| Module six.moves | range | builtin-class xrange | -| Module six.moves | reduce | Builtin-function reduce | -| Module six.moves | reload_module | Builtin-function reload | -| Module six.moves | reprlib | Module repr | -| Module six.moves | shlex_quote | Function quote | -| Module six.moves | socketserver | Module SocketServer | -| Module six.moves | tkinter | Module Tkinter | -| Module six.moves | tkinter_colorchooser | Module tkColorChooser | -| Module six.moves | tkinter_commondialog | Module tkCommonDialog | -| Module six.moves | tkinter_constants | Module Tkconstants | -| Module six.moves | tkinter_dialog | Module Dialog | -| Module six.moves | tkinter_dnd | Module Tkdnd | -| Module six.moves | tkinter_filedialog | Module FileDialog | -| Module six.moves | tkinter_font | Module tkFont | -| Module six.moves | tkinter_messagebox | Module tkMessageBox | -| Module six.moves | tkinter_scrolledtext | Module ScrolledText | -| Module six.moves | tkinter_simpledialog | Module SimpleDialog | -| Module six.moves | tkinter_tix | Module Tix | -| Module six.moves | tkinter_tkfiledialog | Module tkFileDialog | -| Module six.moves | tkinter_tksimpledialog | Module tkSimpleDialog | -| Module six.moves | tkinter_ttk | Module ttk | -| Module six.moves | urllib | Module six.moves.urllib | -| Module six.moves | urllib_error | Module six.moves.urllib_error | -| Module six.moves | urllib_parse | Module six.moves.urllib_parse | -| Module six.moves | urllib_request | Module six.moves.urllib_request | -| Module six.moves | urllib_response | Module six.moves.urllib_response | -| Module six.moves | urllib_robotparser | Module six.moves.urllib_robotparser | -| Module six.moves | xmlrpc_client | Module xmlrpclib | -| Module six.moves | xmlrpc_server | Module SimpleXMLRPCServer | -| Module six.moves | xrange | builtin-class xrange | -| Module six.moves | zip | builtin-class itertools.izip | -| Module six.moves | zip_longest | builtin-class itertools.izip_longest | -| Module six.moves.__init__ | BaseHTTPServer | Module BaseHTTPServer | -| Module six.moves.__init__ | CGIHTTPServer | Module CGIHTTPServer | -| Module six.moves.__init__ | PY2 | bool True | -| Module six.moves.__init__ | PY3 | bool False | -| Module six.moves.__init__ | SimpleHTTPServer | Module SimpleHTTPServer | -| Module six.moves.__init__ | StringIO | class StringIO | -| Module six.moves.__init__ | UserDict | class UserDict | -| Module six.moves.__init__ | UserList | class UserList | -| Module six.moves.__init__ | UserString | class UserString | -| Module six.moves.__init__ | __name__ | str b'six.moves' | -| Module six.moves.__init__ | _dummy_thread | Module dummy_thread | -| Module six.moves.__init__ | _thread | Module thread | -| Module six.moves.__init__ | builtins | Module __builtin__ | -| Module six.moves.__init__ | cPickle | Module cPickle | -| Module six.moves.__init__ | cStringIO | Builtin-function StringIO | -| Module six.moves.__init__ | configparser | Module ConfigParser | -| Module six.moves.__init__ | copyreg | Module copy_reg | -| Module six.moves.__init__ | filter | builtin-class itertools.ifilter | -| Module six.moves.__init__ | filterfalse | builtin-class itertools.ifilterfalse | -| Module six.moves.__init__ | html_entities | Module htmlentitydefs | -| Module six.moves.__init__ | html_parser | Module HTMLParser | -| Module six.moves.__init__ | http_client | Module httplib | -| Module six.moves.__init__ | http_cookiejar | Module cookielib | -| Module six.moves.__init__ | http_cookies | Module Cookie | -| Module six.moves.__init__ | input | Builtin-function raw_input | -| Module six.moves.__init__ | intern | Builtin-function intern | -| Module six.moves.__init__ | map | builtin-class itertools.imap | -| Module six.moves.__init__ | queue | Module Queue | -| Module six.moves.__init__ | range | builtin-class xrange | -| Module six.moves.__init__ | reduce | Builtin-function reduce | -| Module six.moves.__init__ | reload_module | Builtin-function reload | -| Module six.moves.__init__ | reprlib | Module repr | -| Module six.moves.__init__ | shlex_quote | Function quote | -| Module six.moves.__init__ | socketserver | Module SocketServer | -| Module six.moves.__init__ | tkinter | Module Tkinter | -| Module six.moves.__init__ | tkinter_colorchooser | Module tkColorChooser | -| Module six.moves.__init__ | tkinter_commondialog | Module tkCommonDialog | -| Module six.moves.__init__ | tkinter_constants | Module Tkconstants | -| Module six.moves.__init__ | tkinter_dialog | Module Dialog | -| Module six.moves.__init__ | tkinter_dnd | Module Tkdnd | -| Module six.moves.__init__ | tkinter_filedialog | Module FileDialog | -| Module six.moves.__init__ | tkinter_font | Module tkFont | -| Module six.moves.__init__ | tkinter_messagebox | Module tkMessageBox | -| Module six.moves.__init__ | tkinter_scrolledtext | Module ScrolledText | -| Module six.moves.__init__ | tkinter_simpledialog | Module SimpleDialog | -| Module six.moves.__init__ | tkinter_tix | Module Tix | -| Module six.moves.__init__ | tkinter_tkfiledialog | Module tkFileDialog | -| Module six.moves.__init__ | tkinter_tksimpledialog | Module tkSimpleDialog | -| Module six.moves.__init__ | tkinter_ttk | Module ttk | -| Module six.moves.__init__ | urllib | Module six.moves.urllib | -| Module six.moves.__init__ | urllib_error | Module six.moves.urllib_error | -| Module six.moves.__init__ | urllib_parse | Module six.moves.urllib_parse | -| Module six.moves.__init__ | urllib_request | Module six.moves.urllib_request | -| Module six.moves.__init__ | urllib_response | Module six.moves.urllib_response | -| Module six.moves.__init__ | urllib_robotparser | Module six.moves.urllib_robotparser | -| Module six.moves.__init__ | xmlrpc_client | Module xmlrpclib | -| Module six.moves.__init__ | xmlrpc_server | Module SimpleXMLRPCServer | -| Module six.moves.__init__ | xrange | builtin-class xrange | -| Module six.moves.__init__ | zip | builtin-class itertools.izip | -| Module six.moves.__init__ | zip_longest | builtin-class itertools.izip_longest | -| Module six.moves.urllib | __name__ | str b'six.moves.urllib' | -| Module six.moves.urllib | error | Module six.moves.urllib_error | -| Module six.moves.urllib | parse | Module six.moves.urllib_parse | -| Module six.moves.urllib | request | Module six.moves.urllib_request | -| Module six.moves.urllib | response | Module six.moves.urllib_response | -| Module six.moves.urllib | robotparser | Module six.moves.urllib_robotparser | -| Module six.moves.urllib.__init__ | __name__ | str b'six.moves.urllib' | -| Module six.moves.urllib.__init__ | error | Module six.moves.urllib_error | -| Module six.moves.urllib.__init__ | parse | Module six.moves.urllib_parse | -| Module six.moves.urllib.__init__ | request | Module six.moves.urllib_request | -| Module six.moves.urllib.__init__ | response | Module six.moves.urllib_response | -| Module six.moves.urllib.__init__ | robotparser | Module six.moves.urllib_robotparser | -| Module six.moves.urllib_error | PY2 | bool True | -| Module six.moves.urllib_error | PY3 | bool False | -| Module six.moves.urllib_error | __name__ | str b'six.moves.urllib_error' | -| Module six.moves.urllib_parse | PY2 | bool True | -| Module six.moves.urllib_parse | PY3 | bool False | -| Module six.moves.urllib_parse | __name__ | str b'six.moves.urllib_parse' | -| Module six.moves.urllib_request | PY2 | bool True | -| Module six.moves.urllib_request | PY3 | bool False | -| Module six.moves.urllib_request | __name__ | str b'six.moves.urllib_request' | -| Module six.moves.urllib_response | PY2 | bool True | -| Module six.moves.urllib_response | PY3 | bool False | -| Module six.moves.urllib_response | __name__ | str b'six.moves.urllib_response' | -| Module six.moves.urllib_robotparser | PY2 | bool True | -| Module six.moves.urllib_robotparser | PY3 | bool False | -| Module six.moves.urllib_robotparser | RobotFileParser | class RobotFileParser | -| Module six.moves.urllib_robotparser | __name__ | str b'six.moves.urllib_robotparser' | diff --git a/python/ql/test/2/library-tests/six/test.py b/python/ql/test/2/library-tests/six/test.py index ff8b9f33bb5..cac31dceb8a 100644 --- a/python/ql/test/2/library-tests/six/test.py +++ b/python/ql/test/2/library-tests/six/test.py @@ -1,5 +1,9 @@ import six -#Check that some expected attributes are visible +# Check that some expected attributes are visible -- this is the reason we added stubs in +# the first place! If this works, we're happy! six.moves six.moves.range +six.moves.zip +six.moves.http_client.HTTPConnection +six.moves.urllib.parse.urlsplit diff --git a/python/ql/test/2/library-tests/six/test.ql b/python/ql/test/2/library-tests/six/test.ql deleted file mode 100644 index 5d694b9fec9..00000000000 --- a/python/ql/test/2/library-tests/six/test.ql +++ /dev/null @@ -1,11 +0,0 @@ -import python - -predicate six(ModuleObject m) { - m.getName() = "six" - or - six(m.getPackage()) -} - -from ModuleObject mod, string name, Object obj -where mod.attributeRefersTo(name, obj, _) and six(mod) -select mod.toString(), name, obj.toString() diff --git a/python/ql/test/3/library-tests/six/options b/python/ql/test/3/library-tests/six/options index be048160aeb..8e16f310b52 100644 --- a/python/ql/test/3/library-tests/six/options +++ b/python/ql/test/3/library-tests/six/options @@ -1,2 +1,2 @@ -semmle-extractor-options: --max-import-depth=3 +semmle-extractor-options: --max-import-depth=4 optimize: true diff --git a/python/ql/test/3/library-tests/six/pointsto.expected b/python/ql/test/3/library-tests/six/pointsto.expected index 64cd745b873..6d1a9181e82 100644 --- a/python/ql/test/3/library-tests/six/pointsto.expected +++ b/python/ql/test/3/library-tests/six/pointsto.expected @@ -1,3 +1,9 @@ -| six | Module six | -| six.moves | Module six.moves | +| six | Package six | +| six.moves | Package six.moves | +| six.moves.http_client | Module http.client | +| six.moves.http_client.HTTPConnection | class HTTPConnection | | six.moves.range | builtin-class range | +| six.moves.urllib | Package six.moves.urllib | +| six.moves.urllib.parse | Module six.moves.urllib_parse | +| six.moves.urllib.parse.urlsplit | Function urlsplit | +| six.moves.zip | builtin-class zip | diff --git a/python/ql/test/3/library-tests/six/pointsto.ql b/python/ql/test/3/library-tests/six/pointsto.ql index 486242930b9..d44761b1b12 100644 --- a/python/ql/test/3/library-tests/six/pointsto.ql +++ b/python/ql/test/3/library-tests/six/pointsto.ql @@ -1,16 +1,11 @@ - import python string longname(Expr e) { result = e.(Name).getId() or - exists(Attribute a | - a = e | - result = longname(a.getObject()) + "." + a.getName() - ) + exists(Attribute a | a = e | result = longname(a.getObject()) + "." + a.getName()) } -from Expr e, Object o -where e.refersTo(o) and e.getLocation().getFile().getShortName() = "test.py" -select longname(e), o.toString() - +from Expr e, Value v +where e.pointsTo(v) and e.getLocation().getFile().getShortName() = "test.py" +select longname(e), v.toString() diff --git a/python/ql/test/3/library-tests/six/test.expected b/python/ql/test/3/library-tests/six/test.expected deleted file mode 100644 index 199ab676f4f..00000000000 --- a/python/ql/test/3/library-tests/six/test.expected +++ /dev/null @@ -1,262 +0,0 @@ -| Module six | BytesIO | builtin-class _io.BytesIO | -| Module six | Iterator | builtin-class object | -| Module six | MAXSIZE | int 9223372036854775807 | -| Module six | PY2 | bool False | -| Module six | PY3 | bool True | -| Module six | StringIO | builtin-class _io.StringIO | -| Module six | __author__ | str u'Benjamin Peterson ' | -| Module six | __name__ | str u'six' | -| Module six | __version__ | str u'1.5.2' | -| Module six | _add_doc | Function _add_doc | -| Module six | _func_closure | str u'__closure__' | -| Module six | _func_code | str u'__code__' | -| Module six | _func_defaults | str u'__defaults__' | -| Module six | _func_globals | str u'__globals__' | -| Module six | _import_module | Function _import_module | -| Module six | _iteritems | str u'items' | -| Module six | _iterkeys | str u'keys' | -| Module six | _iterlists | str u'lists' | -| Module six | _itervalues | str u'values' | -| Module six | _meth_func | str u'__func__' | -| Module six | _meth_self | str u'__self__' | -| Module six | add_metaclass | Function add_metaclass | -| Module six | add_move | Function add_move | -| Module six | advance_iterator | Builtin-function next | -| Module six | b | Function b | -| Module six | binary_type | builtin-class bytes | -| Module six | byte2int | Function byte2int | -| Module six | callable | Builtin-function callable | -| Module six | callable | Function callable | -| Module six | class_types | Tuple | -| Module six | create_bound_method | builtin-class method | -| Module six | get_function_closure | Attribute() | -| Module six | get_function_code | Attribute() | -| Module six | get_function_defaults | Attribute() | -| Module six | get_function_globals | Attribute() | -| Module six | get_method_function | Attribute() | -| Module six | get_method_self | Attribute() | -| Module six | get_unbound_function | Function get_unbound_function | -| Module six | indexbytes | Builtin-function getitem | -| Module six | int2byte | Function int2byte | -| Module six | integer_types | Tuple | -| Module six | io | Module io | -| Module six | iterbytes | Builtin-function iter | -| Module six | iteritems | Function iteritems | -| Module six | iterkeys | Function iterkeys | -| Module six | iterlists | Function iterlists | -| Module six | itervalues | Function itervalues | -| Module six | moves | Module six.moves | -| Module six | next | Builtin-function next | -| Module six | operator | Module operator | -| Module six | print_ | Function print_ | -| Module six | remove_move | Function remove_move | -| Module six | reraise | Function reraise | -| Module six | string_types | Tuple | -| Module six | sys | Module sys | -| Module six | text_type | builtin-class str | -| Module six | types | Module types | -| Module six | u | Function u | -| Module six | unichr | Builtin-function chr | -| Module six | with_metaclass | Function with_metaclass | -| Module six.__init__ | BytesIO | builtin-class _io.BytesIO | -| Module six.__init__ | Iterator | builtin-class object | -| Module six.__init__ | MAXSIZE | int 9223372036854775807 | -| Module six.__init__ | PY2 | bool False | -| Module six.__init__ | PY3 | bool True | -| Module six.__init__ | StringIO | builtin-class _io.StringIO | -| Module six.__init__ | __author__ | str u'Benjamin Peterson ' | -| Module six.__init__ | __name__ | str u'six' | -| Module six.__init__ | __version__ | str u'1.5.2' | -| Module six.__init__ | _add_doc | Function _add_doc | -| Module six.__init__ | _func_closure | str u'__closure__' | -| Module six.__init__ | _func_code | str u'__code__' | -| Module six.__init__ | _func_defaults | str u'__defaults__' | -| Module six.__init__ | _func_globals | str u'__globals__' | -| Module six.__init__ | _import_module | Function _import_module | -| Module six.__init__ | _iteritems | str u'items' | -| Module six.__init__ | _iterkeys | str u'keys' | -| Module six.__init__ | _iterlists | str u'lists' | -| Module six.__init__ | _itervalues | str u'values' | -| Module six.__init__ | _meth_func | str u'__func__' | -| Module six.__init__ | _meth_self | str u'__self__' | -| Module six.__init__ | add_metaclass | Function add_metaclass | -| Module six.__init__ | add_move | Function add_move | -| Module six.__init__ | advance_iterator | Builtin-function next | -| Module six.__init__ | b | Function b | -| Module six.__init__ | binary_type | builtin-class bytes | -| Module six.__init__ | byte2int | Function byte2int | -| Module six.__init__ | callable | Builtin-function callable | -| Module six.__init__ | callable | Function callable | -| Module six.__init__ | class_types | Tuple | -| Module six.__init__ | create_bound_method | builtin-class method | -| Module six.__init__ | get_function_closure | Attribute() | -| Module six.__init__ | get_function_code | Attribute() | -| Module six.__init__ | get_function_defaults | Attribute() | -| Module six.__init__ | get_function_globals | Attribute() | -| Module six.__init__ | get_method_function | Attribute() | -| Module six.__init__ | get_method_self | Attribute() | -| Module six.__init__ | get_unbound_function | Function get_unbound_function | -| Module six.__init__ | indexbytes | Builtin-function getitem | -| Module six.__init__ | int2byte | Function int2byte | -| Module six.__init__ | integer_types | Tuple | -| Module six.__init__ | io | Module io | -| Module six.__init__ | iterbytes | Builtin-function iter | -| Module six.__init__ | iteritems | Function iteritems | -| Module six.__init__ | iterkeys | Function iterkeys | -| Module six.__init__ | iterlists | Function iterlists | -| Module six.__init__ | itervalues | Function itervalues | -| Module six.__init__ | moves | Module six.moves | -| Module six.__init__ | next | Builtin-function next | -| Module six.__init__ | operator | Module operator | -| Module six.__init__ | print_ | Function print_ | -| Module six.__init__ | remove_move | Function remove_move | -| Module six.__init__ | reraise | Function reraise | -| Module six.__init__ | string_types | Tuple | -| Module six.__init__ | sys | Module sys | -| Module six.__init__ | text_type | builtin-class str | -| Module six.__init__ | types | Module types | -| Module six.__init__ | u | Function u | -| Module six.__init__ | unichr | Builtin-function chr | -| Module six.__init__ | with_metaclass | Function with_metaclass | -| Module six.moves | BaseHTTPServer | Module http.server | -| Module six.moves | CGIHTTPServer | Module http.server | -| Module six.moves | PY2 | bool False | -| Module six.moves | PY3 | bool True | -| Module six.moves | SimpleHTTPServer | Module http.server | -| Module six.moves | StringIO | builtin-class _io.StringIO | -| Module six.moves | UserString | class UserString | -| Module six.moves | __name__ | str u'six.moves' | -| Module six.moves | _thread | Module _thread | -| Module six.moves | builtins | Module builtins | -| Module six.moves | cPickle | Module pickle | -| Module six.moves | cStringIO | builtin-class _io.StringIO | -| Module six.moves | configparser | Module configparser | -| Module six.moves | copyreg | Module copyreg | -| Module six.moves | dbm_gnu | Module dbm.gnu | -| Module six.moves | email_mime_base | Module email.mime.base | -| Module six.moves | email_mime_multipart | Module email.mime.multipart | -| Module six.moves | email_mime_text | Module email.mime.text | -| Module six.moves | filter | builtin-class filter | -| Module six.moves | filterfalse | builtin-class itertools.filterfalse | -| Module six.moves | html_entities | Module html.entities | -| Module six.moves | html_parser | Module html.parser | -| Module six.moves | http_client | Module http.client | -| Module six.moves | http_cookiejar | Module http.cookiejar | -| Module six.moves | http_cookies | Module http.cookies | -| Module six.moves | input | Builtin-function input | -| Module six.moves | map | builtin-class map | -| Module six.moves | queue | Module queue | -| Module six.moves | range | builtin-class range | -| Module six.moves | reload_module | Function reload | -| Module six.moves | reprlib | Module reprlib | -| Module six.moves | socketserver | Module socketserver | -| Module six.moves | tkinter | Module tkinter | -| Module six.moves | tkinter_colorchooser | Module tkinter.colorchooser | -| Module six.moves | tkinter_commondialog | Module tkinter.commondialog | -| Module six.moves | tkinter_constants | Module tkinter.constants | -| Module six.moves | tkinter_dialog | Module tkinter.dialog | -| Module six.moves | tkinter_dnd | Module tkinter.dnd | -| Module six.moves | tkinter_filedialog | Module tkinter.filedialog | -| Module six.moves | tkinter_font | Module tkinter.font | -| Module six.moves | tkinter_messagebox | Module tkinter.messagebox | -| Module six.moves | tkinter_scrolledtext | Module tkinter.scrolledtext | -| Module six.moves | tkinter_simpledialog | Module tkinter.simpledialog | -| Module six.moves | tkinter_tix | Module tkinter.tix | -| Module six.moves | tkinter_tkfiledialog | Module tkinter.filedialog | -| Module six.moves | tkinter_tksimpledialog | Module tkinter.simpledialog | -| Module six.moves | tkinter_ttk | Module tkinter.ttk | -| Module six.moves | urllib | Module six.moves.urllib | -| Module six.moves | urllib_error | Module six.moves.urllib_error | -| Module six.moves | urllib_parse | Module six.moves.urllib_parse | -| Module six.moves | urllib_request | Module six.moves.urllib_request | -| Module six.moves | urllib_response | Module six.moves.urllib_response | -| Module six.moves | urllib_robotparser | Module six.moves.urllib_robotparser | -| Module six.moves | xmlrpc_client | Module xmlrpc.client | -| Module six.moves | xrange | builtin-class range | -| Module six.moves | zip | builtin-class zip | -| Module six.moves | zip_longest | builtin-class itertools.zip_longest | -| Module six.moves.__init__ | BaseHTTPServer | Module http.server | -| Module six.moves.__init__ | CGIHTTPServer | Module http.server | -| Module six.moves.__init__ | PY2 | bool False | -| Module six.moves.__init__ | PY3 | bool True | -| Module six.moves.__init__ | SimpleHTTPServer | Module http.server | -| Module six.moves.__init__ | StringIO | builtin-class _io.StringIO | -| Module six.moves.__init__ | UserString | class UserString | -| Module six.moves.__init__ | __name__ | str u'six.moves' | -| Module six.moves.__init__ | _thread | Module _thread | -| Module six.moves.__init__ | builtins | Module builtins | -| Module six.moves.__init__ | cPickle | Module pickle | -| Module six.moves.__init__ | cStringIO | builtin-class _io.StringIO | -| Module six.moves.__init__ | configparser | Module configparser | -| Module six.moves.__init__ | copyreg | Module copyreg | -| Module six.moves.__init__ | dbm_gnu | Module dbm.gnu | -| Module six.moves.__init__ | email_mime_base | Module email.mime.base | -| Module six.moves.__init__ | email_mime_multipart | Module email.mime.multipart | -| Module six.moves.__init__ | email_mime_text | Module email.mime.text | -| Module six.moves.__init__ | filter | builtin-class filter | -| Module six.moves.__init__ | filterfalse | builtin-class itertools.filterfalse | -| Module six.moves.__init__ | html_entities | Module html.entities | -| Module six.moves.__init__ | html_parser | Module html.parser | -| Module six.moves.__init__ | http_client | Module http.client | -| Module six.moves.__init__ | http_cookiejar | Module http.cookiejar | -| Module six.moves.__init__ | http_cookies | Module http.cookies | -| Module six.moves.__init__ | input | Builtin-function input | -| Module six.moves.__init__ | map | builtin-class map | -| Module six.moves.__init__ | queue | Module queue | -| Module six.moves.__init__ | range | builtin-class range | -| Module six.moves.__init__ | reload_module | Function reload | -| Module six.moves.__init__ | reprlib | Module reprlib | -| Module six.moves.__init__ | socketserver | Module socketserver | -| Module six.moves.__init__ | tkinter | Module tkinter | -| Module six.moves.__init__ | tkinter_colorchooser | Module tkinter.colorchooser | -| Module six.moves.__init__ | tkinter_commondialog | Module tkinter.commondialog | -| Module six.moves.__init__ | tkinter_constants | Module tkinter.constants | -| Module six.moves.__init__ | tkinter_dialog | Module tkinter.dialog | -| Module six.moves.__init__ | tkinter_dnd | Module tkinter.dnd | -| Module six.moves.__init__ | tkinter_filedialog | Module tkinter.filedialog | -| Module six.moves.__init__ | tkinter_font | Module tkinter.font | -| Module six.moves.__init__ | tkinter_messagebox | Module tkinter.messagebox | -| Module six.moves.__init__ | tkinter_scrolledtext | Module tkinter.scrolledtext | -| Module six.moves.__init__ | tkinter_simpledialog | Module tkinter.simpledialog | -| Module six.moves.__init__ | tkinter_tix | Module tkinter.tix | -| Module six.moves.__init__ | tkinter_tkfiledialog | Module tkinter.filedialog | -| Module six.moves.__init__ | tkinter_tksimpledialog | Module tkinter.simpledialog | -| Module six.moves.__init__ | tkinter_ttk | Module tkinter.ttk | -| Module six.moves.__init__ | urllib | Module six.moves.urllib | -| Module six.moves.__init__ | urllib_error | Module six.moves.urllib_error | -| Module six.moves.__init__ | urllib_parse | Module six.moves.urllib_parse | -| Module six.moves.__init__ | urllib_request | Module six.moves.urllib_request | -| Module six.moves.__init__ | urllib_response | Module six.moves.urllib_response | -| Module six.moves.__init__ | urllib_robotparser | Module six.moves.urllib_robotparser | -| Module six.moves.__init__ | xmlrpc_client | Module xmlrpc.client | -| Module six.moves.__init__ | xrange | builtin-class range | -| Module six.moves.__init__ | zip | builtin-class zip | -| Module six.moves.__init__ | zip_longest | builtin-class itertools.zip_longest | -| Module six.moves.urllib | __name__ | str u'six.moves.urllib' | -| Module six.moves.urllib | error | Module six.moves.urllib_error | -| Module six.moves.urllib | parse | Module six.moves.urllib_parse | -| Module six.moves.urllib | request | Module six.moves.urllib_request | -| Module six.moves.urllib | response | Module six.moves.urllib_response | -| Module six.moves.urllib | robotparser | Module six.moves.urllib_robotparser | -| Module six.moves.urllib.__init__ | __name__ | str u'six.moves.urllib' | -| Module six.moves.urllib.__init__ | error | Module six.moves.urllib_error | -| Module six.moves.urllib.__init__ | parse | Module six.moves.urllib_parse | -| Module six.moves.urllib.__init__ | request | Module six.moves.urllib_request | -| Module six.moves.urllib.__init__ | response | Module six.moves.urllib_response | -| Module six.moves.urllib.__init__ | robotparser | Module six.moves.urllib_robotparser | -| Module six.moves.urllib_error | PY2 | bool False | -| Module six.moves.urllib_error | PY3 | bool True | -| Module six.moves.urllib_error | __name__ | str u'six.moves.urllib_error' | -| Module six.moves.urllib_parse | PY2 | bool False | -| Module six.moves.urllib_parse | PY3 | bool True | -| Module six.moves.urllib_parse | __name__ | str u'six.moves.urllib_parse' | -| Module six.moves.urllib_request | PY2 | bool False | -| Module six.moves.urllib_request | PY3 | bool True | -| Module six.moves.urllib_request | __name__ | str u'six.moves.urllib_request' | -| Module six.moves.urllib_response | PY2 | bool False | -| Module six.moves.urllib_response | PY3 | bool True | -| Module six.moves.urllib_response | __name__ | str u'six.moves.urllib_response' | -| Module six.moves.urllib_robotparser | PY2 | bool False | -| Module six.moves.urllib_robotparser | PY3 | bool True | -| Module six.moves.urllib_robotparser | RobotFileParser | class RobotFileParser | -| Module six.moves.urllib_robotparser | __name__ | str u'six.moves.urllib_robotparser' | diff --git a/python/ql/test/3/library-tests/six/test.py b/python/ql/test/3/library-tests/six/test.py index 6cffe08b96c..cac31dceb8a 100644 --- a/python/ql/test/3/library-tests/six/test.py +++ b/python/ql/test/3/library-tests/six/test.py @@ -1,5 +1,9 @@ import six -#Check that some expected attributes are visible +# Check that some expected attributes are visible -- this is the reason we added stubs in +# the first place! If this works, we're happy! six.moves -six.moves.range \ No newline at end of file +six.moves.range +six.moves.zip +six.moves.http_client.HTTPConnection +six.moves.urllib.parse.urlsplit diff --git a/python/ql/test/3/library-tests/six/test.ql b/python/ql/test/3/library-tests/six/test.ql deleted file mode 100644 index 5d694b9fec9..00000000000 --- a/python/ql/test/3/library-tests/six/test.ql +++ /dev/null @@ -1,11 +0,0 @@ -import python - -predicate six(ModuleObject m) { - m.getName() = "six" - or - six(m.getPackage()) -} - -from ModuleObject mod, string name, Object obj -where mod.attributeRefersTo(name, obj, _) and six(mod) -select mod.toString(), name, obj.toString() diff --git a/python/ql/test/library-tests/web/bottle/HttpResponseSinks.expected b/python/ql/test/library-tests/web/bottle/HttpResponseSinks.expected new file mode 100644 index 00000000000..c8f60f6a596 --- /dev/null +++ b/python/ql/test/library-tests/web/bottle/HttpResponseSinks.expected @@ -0,0 +1,4 @@ +| test.py:9:12:9:26 | bottle handler function result | externally controlled string | +| test.py:13:12:13:24 | bottle handler function result | externally controlled string | +| test.py:19:12:19:33 | bottle handler function result | externally controlled string | +| test.py:36:21:36:51 | Taint sink | externally controlled string | diff --git a/python/ql/test/library-tests/web/bottle/HttpResponseSinks.ql b/python/ql/test/library-tests/web/bottle/HttpResponseSinks.ql new file mode 100644 index 00000000000..e62ec486da6 --- /dev/null +++ b/python/ql/test/library-tests/web/bottle/HttpResponseSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from HttpResponseTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/bottle/HttpSources.expected b/python/ql/test/library-tests/web/bottle/HttpSources.expected new file mode 100644 index 00000000000..41e68da26d9 --- /dev/null +++ b/python/ql/test/library-tests/web/bottle/HttpSources.expected @@ -0,0 +1,8 @@ +| ../../../query-tests/Security/lib/bottle.py:64:11:64:24 | LocalRequest() | bottle.request | +| test.py:3:35:3:41 | ImportMember | bottle.request | +| test.py:8:11:8:14 | name | externally controlled string | +| test.py:12:9:12:12 | name | externally controlled string | +| test.py:18:12:18:18 | request | bottle.request | +| test.py:27:12:27:16 | where | externally controlled string | +| test.py:32:14:32:20 | request | bottle.request | +| test.py:36:34:36:40 | request | bottle.request | diff --git a/python/ql/test/library-tests/web/bottle/HttpSources.ql b/python/ql/test/library-tests/web/bottle/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/bottle/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/bottle/Routing.ql b/python/ql/test/library-tests/web/bottle/Routing.ql index 3a10c78ddcb..988b8398f04 100644 --- a/python/ql/test/library-tests/web/bottle/Routing.ql +++ b/python/ql/test/library-tests/web/bottle/Routing.ql @@ -1,7 +1,5 @@ import python - import semmle.python.web.bottle.General from BottleRoute route - select route.getUrl(), route.getFunction() diff --git a/python/ql/test/library-tests/web/bottle/Sinks.expected b/python/ql/test/library-tests/web/bottle/Sinks.expected deleted file mode 100644 index 64edd29140f..00000000000 --- a/python/ql/test/library-tests/web/bottle/Sinks.expected +++ /dev/null @@ -1,4 +0,0 @@ -| test.py:9 | BinaryExpr | externally controlled string | -| test.py:13 | BinaryExpr | externally controlled string | -| test.py:19 | BinaryExpr | externally controlled string | -| test.py:36 | BinaryExpr | externally controlled string | diff --git a/python/ql/test/library-tests/web/bottle/Sinks.ql b/python/ql/test/library-tests/web/bottle/Sinks.ql deleted file mode 100644 index 34aa1cfc429..00000000000 --- a/python/ql/test/library-tests/web/bottle/Sinks.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/bottle/Sources.expected b/python/ql/test/library-tests/web/bottle/Sources.expected deleted file mode 100644 index 46c419efb95..00000000000 --- a/python/ql/test/library-tests/web/bottle/Sources.expected +++ /dev/null @@ -1,8 +0,0 @@ -| ../../../query-tests/Security/lib/bottle.py:64 | LocalRequest() | bottle.request | -| test.py:3 | ImportMember | bottle.request | -| test.py:8 | name | externally controlled string | -| test.py:12 | name | externally controlled string | -| test.py:18 | request | bottle.request | -| test.py:27 | where | externally controlled string | -| test.py:32 | request | bottle.request | -| test.py:36 | request | bottle.request | diff --git a/python/ql/test/library-tests/web/bottle/Sources.ql b/python/ql/test/library-tests/web/bottle/Sources.ql deleted file mode 100644 index c1b9cc82e19..00000000000 --- a/python/ql/test/library-tests/web/bottle/Sources.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) and not kind.matches("tornado%") -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/bottle/Taint.ql b/python/ql/test/library-tests/web/bottle/Taint.ql index 2c74191e645..09972af5f98 100644 --- a/python/ql/test/library-tests/web/bottle/Taint.ql +++ b/python/ql/test/library-tests/web/bottle/Taint.ql @@ -1,13 +1,7 @@ - import python - - import semmle.python.web.HttpRequest import semmle.python.web.HttpResponse import semmle.python.security.strings.Untrusted - from TaintedNode node - select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind() - diff --git a/python/ql/test/library-tests/web/cherrypy/HttpResponseSinks.expected b/python/ql/test/library-tests/web/cherrypy/HttpResponseSinks.expected new file mode 100644 index 00000000000..0d7a43a2b07 --- /dev/null +++ b/python/ql/test/library-tests/web/cherrypy/HttpResponseSinks.expected @@ -0,0 +1,3 @@ +| red.py:8:16:8:20 | cherrypy handler function result | externally controlled string | +| test.py:11:16:11:29 | cherrypy handler function result | externally controlled string | +| test.py:17:16:17:27 | cherrypy handler function result | externally controlled string | diff --git a/python/ql/test/library-tests/web/cherrypy/HttpResponseSinks.ql b/python/ql/test/library-tests/web/cherrypy/HttpResponseSinks.ql new file mode 100644 index 00000000000..e62ec486da6 --- /dev/null +++ b/python/ql/test/library-tests/web/cherrypy/HttpResponseSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from HttpResponseTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/cherrypy/HttpSources.expected b/python/ql/test/library-tests/web/cherrypy/HttpSources.expected new file mode 100644 index 00000000000..205cc9caaa8 --- /dev/null +++ b/python/ql/test/library-tests/web/cherrypy/HttpSources.expected @@ -0,0 +1,3 @@ +| ../../../query-tests/Security/lib/cherrypy/__init__.py:10:11:10:38 | _ThreadLocalProxy() | cherrypy.request | +| test.py:10:17:10:19 | arg | externally controlled string | +| test.py:16:17:16:19 | arg | externally controlled string | diff --git a/python/ql/test/library-tests/web/cherrypy/HttpSources.ql b/python/ql/test/library-tests/web/cherrypy/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/cherrypy/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/cherrypy/Sinks.expected b/python/ql/test/library-tests/web/cherrypy/Sinks.expected deleted file mode 100644 index e47936b055c..00000000000 --- a/python/ql/test/library-tests/web/cherrypy/Sinks.expected +++ /dev/null @@ -1,3 +0,0 @@ -| red.py:8 | Str | externally controlled string | -| test.py:11 | BinaryExpr | externally controlled string | -| test.py:17 | BinaryExpr | externally controlled string | diff --git a/python/ql/test/library-tests/web/cherrypy/Sinks.ql b/python/ql/test/library-tests/web/cherrypy/Sinks.ql deleted file mode 100644 index 34aa1cfc429..00000000000 --- a/python/ql/test/library-tests/web/cherrypy/Sinks.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/cherrypy/Sources.expected b/python/ql/test/library-tests/web/cherrypy/Sources.expected deleted file mode 100644 index b2a4d2e7c3e..00000000000 --- a/python/ql/test/library-tests/web/cherrypy/Sources.expected +++ /dev/null @@ -1,3 +0,0 @@ -| ../../../query-tests/Security/lib/cherrypy/__init__.py:10 | _ThreadLocalProxy() | cherrypy.request | -| test.py:10 | arg | externally controlled string | -| test.py:16 | arg | externally controlled string | diff --git a/python/ql/test/library-tests/web/cherrypy/Sources.ql b/python/ql/test/library-tests/web/cherrypy/Sources.ql deleted file mode 100644 index c1b9cc82e19..00000000000 --- a/python/ql/test/library-tests/web/cherrypy/Sources.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) and not kind.matches("tornado%") -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/django/HttpResponseSinks.expected b/python/ql/test/library-tests/web/django/HttpResponseSinks.expected new file mode 100644 index 00000000000..28bda6b1d30 --- /dev/null +++ b/python/ql/test/library-tests/web/django/HttpResponseSinks.expected @@ -0,0 +1,7 @@ +| views.py:7:25:7:63 | django.Response(...) | externally controlled string | +| views.py:11:25:11:52 | django.Response(...) | externally controlled string | +| views.py:15:25:15:53 | django.Response(...) | externally controlled string | +| views.py:23:29:23:60 | django.Response(...) | externally controlled string | +| views.py:29:29:29:65 | django.Response(...) | externally controlled string | +| views.py:34:25:34:63 | django.Response(...) | externally controlled string | +| views.py:38:25:38:70 | django.Response(...) | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/HttpResponseSinks.ql b/python/ql/test/library-tests/web/django/HttpResponseSinks.ql new file mode 100644 index 00000000000..e62ec486da6 --- /dev/null +++ b/python/ql/test/library-tests/web/django/HttpResponseSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from HttpResponseTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/django/HttpSources.expected b/python/ql/test/library-tests/web/django/HttpSources.expected new file mode 100644 index 00000000000..1c25023d0b4 --- /dev/null +++ b/python/ql/test/library-tests/web/django/HttpSources.expected @@ -0,0 +1,19 @@ +| test.py:5:19:5:25 | request | django.request.HttpRequest | +| test.py:5:28:5:31 | path | externally controlled string | +| test.py:11:19:11:25 | request | django.request.HttpRequest | +| test.py:11:28:11:31 | path | externally controlled string | +| views.py:6:19:6:25 | request | django.request.HttpRequest | +| views.py:6:28:6:30 | foo | externally controlled string | +| views.py:6:33:6:35 | bar | externally controlled string | +| views.py:10:20:10:26 | request | django.request.HttpRequest | +| views.py:14:21:14:27 | request | django.request.HttpRequest | +| views.py:22:20:22:26 | request | django.request.HttpRequest | +| views.py:28:19:28:25 | request | django.request.HttpRequest | +| views.py:32:19:32:25 | request | django.request.HttpRequest | +| views.py:32:28:32:38 | page_number | externally controlled string | +| views.py:37:24:37:30 | request | django.request.HttpRequest | +| views.py:37:33:37:36 | arg0 | externally controlled string | +| views.py:37:39:37:42 | arg1 | externally controlled string | +| views.py:57:15:57:21 | request | django.request.HttpRequest | +| views.py:57:24:57:31 | username | externally controlled string | +| views.py:66:30:66:36 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/HttpSources.ql b/python/ql/test/library-tests/web/django/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/django/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected deleted file mode 100644 index e3d233c9990..00000000000 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ /dev/null @@ -1,16 +0,0 @@ -| sql.py:13 | Str | externally controlled string | -| sql.py:14 | Str | externally controlled string | -| sql.py:17 | BinaryExpr | externally controlled string | -| sql.py:20 | BinaryExpr | externally controlled string | -| sql.py:21 | BinaryExpr | externally controlled string | -| sql.py:22 | BinaryExpr | externally controlled string | -| sql.py:36 | Str | externally controlled string | -| sql.py:42 | BinaryExpr | externally controlled string | -| sql.py:47 | BinaryExpr | externally controlled string | -| views.py:7 | Attribute() | externally controlled string | -| views.py:11 | Attribute() | externally controlled string | -| views.py:15 | Attribute() | externally controlled string | -| views.py:23 | Attribute() | externally controlled string | -| views.py:29 | Attribute() | externally controlled string | -| views.py:34 | Attribute() | externally controlled string | -| views.py:38 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sinks.ql b/python/ql/test/library-tests/web/django/Sinks.ql deleted file mode 100644 index 5bdf37e4f44..00000000000 --- a/python/ql/test/library-tests/web/django/Sinks.ql +++ /dev/null @@ -1,13 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.web.django.Db -import semmle.python.web.django.Model - -import semmle.python.security.strings.Untrusted - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected deleted file mode 100644 index 35e0d3d8ced..00000000000 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ /dev/null @@ -1,19 +0,0 @@ -| test.py:5 | path | externally controlled string | -| test.py:5 | request | django.request.HttpRequest | -| test.py:11 | path | externally controlled string | -| test.py:11 | request | django.request.HttpRequest | -| views.py:6 | bar | externally controlled string | -| views.py:6 | foo | externally controlled string | -| views.py:6 | request | django.request.HttpRequest | -| views.py:10 | request | django.request.HttpRequest | -| views.py:14 | request | django.request.HttpRequest | -| views.py:22 | request | django.request.HttpRequest | -| views.py:28 | request | django.request.HttpRequest | -| views.py:32 | page_number | externally controlled string | -| views.py:32 | request | django.request.HttpRequest | -| views.py:37 | arg0 | externally controlled string | -| views.py:37 | arg1 | externally controlled string | -| views.py:37 | request | django.request.HttpRequest | -| views.py:57 | request | django.request.HttpRequest | -| views.py:57 | username | externally controlled string | -| views.py:66 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/Sources.ql b/python/ql/test/library-tests/web/django/Sources.ql deleted file mode 100644 index aece91f44e2..00000000000 --- a/python/ql/test/library-tests/web/django/Sources.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/django/SqlInjectionSinks.expected b/python/ql/test/library-tests/web/django/SqlInjectionSinks.expected new file mode 100644 index 00000000000..d9850f2f7c6 --- /dev/null +++ b/python/ql/test/library-tests/web/django/SqlInjectionSinks.expected @@ -0,0 +1,9 @@ +| sql.py:13:24:13:64 | db.connection.execute | externally controlled string | +| sql.py:14:26:14:66 | django.models.QuerySet.raw(sink,...) | externally controlled string | +| sql.py:17:24:17:77 | db.connection.execute | externally controlled string | +| sql.py:20:38:20:95 | django.db.models.expressions.RawSQL(sink,...) | externally controlled string | +| sql.py:21:26:21:83 | django.models.QuerySet.raw(sink,...) | externally controlled string | +| sql.py:22:28:22:85 | django.models.QuerySet.extra(sink,...) | externally controlled string | +| sql.py:36:26:36:68 | django.models.QuerySet.raw(sink,...) | externally controlled string | +| sql.py:42:11:42:52 | django.models.QuerySet.raw(sink,...) | externally controlled string | +| sql.py:47:13:47:54 | django.models.QuerySet.extra(sink,...) | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/SqlInjectionSinks.ql b/python/ql/test/library-tests/web/django/SqlInjectionSinks.ql new file mode 100644 index 00000000000..bd9f4c22fc8 --- /dev/null +++ b/python/ql/test/library-tests/web/django/SqlInjectionSinks.ql @@ -0,0 +1,9 @@ +import python +import semmle.python.security.injection.Sql +import semmle.python.web.django.Db +import semmle.python.web.django.Model +import semmle.python.security.strings.Untrusted + +from SqlInjectionSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/falcon/HttpResponseSinks.expected b/python/ql/test/library-tests/web/falcon/HttpResponseSinks.expected new file mode 100644 index 00000000000..76fe8773866 --- /dev/null +++ b/python/ql/test/library-tests/web/falcon/HttpResponseSinks.expected @@ -0,0 +1 @@ +| FIXME: temporarily disabled since it's not working | diff --git a/python/ql/test/library-tests/web/falcon/HttpResponseSinks.ql b/python/ql/test/library-tests/web/falcon/HttpResponseSinks.ql new file mode 100644 index 00000000000..eec9b1ef3cf --- /dev/null +++ b/python/ql/test/library-tests/web/falcon/HttpResponseSinks.ql @@ -0,0 +1,8 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +// from HttpResponseTaintSink sink, TaintKind kind +// where sink.sinks(kind) +// select sink, kind +select "FIXME: temporarily disabled since it's not working" diff --git a/python/ql/test/library-tests/web/falcon/HttpSources.expected b/python/ql/test/library-tests/web/falcon/HttpSources.expected new file mode 100644 index 00000000000..247015db674 --- /dev/null +++ b/python/ql/test/library-tests/web/falcon/HttpSources.expected @@ -0,0 +1,3 @@ +| test.py:9:22:9:24 | req | falcon.request | +| test.py:19:23:19:25 | req | falcon.request | +| test.py:22:25:22:27 | req | falcon.request | diff --git a/python/ql/test/library-tests/web/falcon/HttpSources.ql b/python/ql/test/library-tests/web/falcon/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/falcon/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/falcon/Routing.ql b/python/ql/test/library-tests/web/falcon/Routing.ql index 0596664ba76..fde6c933b65 100644 --- a/python/ql/test/library-tests/web/falcon/Routing.ql +++ b/python/ql/test/library-tests/web/falcon/Routing.ql @@ -1,8 +1,5 @@ import python - import semmle.python.web.falcon.General from FalconRoute route, string method - select route.getUrl(), method, route.getHandlerFunction(method) - diff --git a/python/ql/test/library-tests/web/falcon/Sinks.ql b/python/ql/test/library-tests/web/falcon/Sinks.ql index 34aa1cfc429..efaafe17f02 100644 --- a/python/ql/test/library-tests/web/falcon/Sinks.ql +++ b/python/ql/test/library-tests/web/falcon/Sinks.ql @@ -1,6 +1,4 @@ - import python - import semmle.python.web.HttpRequest import semmle.python.web.HttpResponse import semmle.python.security.strings.Untrusted diff --git a/python/ql/test/library-tests/web/falcon/Sources.expected b/python/ql/test/library-tests/web/falcon/Sources.expected deleted file mode 100644 index f2ed444a751..00000000000 --- a/python/ql/test/library-tests/web/falcon/Sources.expected +++ /dev/null @@ -1,3 +0,0 @@ -| test.py:9 | req | falcon.request | -| test.py:19 | req | falcon.request | -| test.py:22 | req | falcon.request | \ No newline at end of file diff --git a/python/ql/test/library-tests/web/falcon/Sources.ql b/python/ql/test/library-tests/web/falcon/Sources.ql deleted file mode 100644 index c1b9cc82e19..00000000000 --- a/python/ql/test/library-tests/web/falcon/Sources.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) and not kind.matches("tornado%") -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/falcon/Taint.ql b/python/ql/test/library-tests/web/falcon/Taint.ql index 59dbe108f62..d68b12079b8 100644 --- a/python/ql/test/library-tests/web/falcon/Taint.ql +++ b/python/ql/test/library-tests/web/falcon/Taint.ql @@ -1,12 +1,8 @@ - import python - - import semmle.python.web.HttpRequest import semmle.python.web.HttpResponse import semmle.python.security.strings.Untrusted - from TaintedNode node where node.getLocation().getFile().getShortName() = "test.py" select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind() diff --git a/python/ql/test/library-tests/web/flask/HttpResponseSinks.expected b/python/ql/test/library-tests/web/flask/HttpResponseSinks.expected new file mode 100644 index 00000000000..5581b7fd3ad --- /dev/null +++ b/python/ql/test/library-tests/web/flask/HttpResponseSinks.expected @@ -0,0 +1,8 @@ +| test.py:8:12:8:25 | flask.routed.response | externally controlled string | +| test.py:29:12:29:38 | flask.routed.response | externally controlled string | +| test.py:35:16:35:37 | flask.routed.response | externally controlled string | +| test.py:36:12:36:15 | flask.routed.response | externally controlled string | +| test.py:41:12:41:54 | flask.routed.response | externally controlled string | +| test.py:41:26:41:53 | flask.response.argument | externally controlled string | +| test.py:46:12:46:62 | flask.routed.response | externally controlled string | +| test.py:46:26:46:61 | flask.response.argument | externally controlled string | diff --git a/python/ql/test/library-tests/web/flask/HttpResponseSinks.ql b/python/ql/test/library-tests/web/flask/HttpResponseSinks.ql new file mode 100644 index 00000000000..e62ec486da6 --- /dev/null +++ b/python/ql/test/library-tests/web/flask/HttpResponseSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from HttpResponseTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/flask/HttpSources.expected b/python/ql/test/library-tests/web/flask/HttpSources.expected new file mode 100644 index 00000000000..7899304bb4f --- /dev/null +++ b/python/ql/test/library-tests/web/flask/HttpSources.expected @@ -0,0 +1,5 @@ +| test.py:29:12:29:23 | Attribute | {externally controlled string} | +| test.py:33:9:33:20 | Attribute | {externally controlled string} | +| test.py:35:16:35:27 | Attribute | {externally controlled string} | +| test.py:40:18:40:29 | Attribute | {externally controlled string} | +| test.py:45:18:45:29 | Attribute | {externally controlled string} | diff --git a/python/ql/test/library-tests/web/flask/HttpSources.ql b/python/ql/test/library-tests/web/flask/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/flask/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/flask/Routing.ql b/python/ql/test/library-tests/web/flask/Routing.ql index ebd0ec93abb..92ae6740f0d 100644 --- a/python/ql/test/library-tests/web/flask/Routing.ql +++ b/python/ql/test/library-tests/web/flask/Routing.ql @@ -1,9 +1,6 @@ import python - import semmle.python.web.flask.General from ControlFlowNode regex, Function func - where flask_routing(regex, func) - select regex.getNode().(StrConst).getText(), func.toString() diff --git a/python/ql/test/library-tests/web/flask/Sinks.expected b/python/ql/test/library-tests/web/flask/Sinks.expected deleted file mode 100644 index 741ab7d4d38..00000000000 --- a/python/ql/test/library-tests/web/flask/Sinks.expected +++ /dev/null @@ -1,8 +0,0 @@ -| test.py:8 | Str | externally controlled string | -| test.py:29 | Attribute() | externally controlled string | -| test.py:35 | Subscript | externally controlled string | -| test.py:36 | None | externally controlled string | -| test.py:41 | BinaryExpr | externally controlled string | -| test.py:41 | make_response() | externally controlled string | -| test.py:46 | BinaryExpr | externally controlled string | -| test.py:46 | make_response() | externally controlled string | diff --git a/python/ql/test/library-tests/web/flask/Sinks.ql b/python/ql/test/library-tests/web/flask/Sinks.ql deleted file mode 100644 index 34aa1cfc429..00000000000 --- a/python/ql/test/library-tests/web/flask/Sinks.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/flask/Sources.expected b/python/ql/test/library-tests/web/flask/Sources.expected deleted file mode 100644 index 09b626643a1..00000000000 --- a/python/ql/test/library-tests/web/flask/Sources.expected +++ /dev/null @@ -1,6 +0,0 @@ -| test.py:22 | Attribute() | flask/MyView.as.view | -| test.py:29 | Attribute | {externally controlled string} | -| test.py:33 | Attribute | {externally controlled string} | -| test.py:35 | Attribute | {externally controlled string} | -| test.py:40 | Attribute | {externally controlled string} | -| test.py:45 | Attribute | {externally controlled string} | diff --git a/python/ql/test/library-tests/web/flask/Sources.ql b/python/ql/test/library-tests/web/flask/Sources.ql deleted file mode 100644 index b1b7fe3e08b..00000000000 --- a/python/ql/test/library-tests/web/flask/Sources.ql +++ /dev/null @@ -1,11 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/flask/Taint.ql b/python/ql/test/library-tests/web/flask/Taint.ql index 59dbe108f62..d68b12079b8 100644 --- a/python/ql/test/library-tests/web/flask/Taint.ql +++ b/python/ql/test/library-tests/web/flask/Taint.ql @@ -1,12 +1,8 @@ - import python - - import semmle.python.web.HttpRequest import semmle.python.web.HttpResponse import semmle.python.security.strings.Untrusted - from TaintedNode node where node.getLocation().getFile().getShortName() = "test.py" select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind() diff --git a/python/ql/test/library-tests/web/pyramid/HttpResponseSinks.expected b/python/ql/test/library-tests/web/pyramid/HttpResponseSinks.expected new file mode 100644 index 00000000000..c5791c9c976 --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/HttpResponseSinks.expected @@ -0,0 +1,3 @@ +| test.py:8:12:8:31 | pyramid.routed.response | externally controlled string | +| test.py:17:12:17:41 | pyramid.routed.response | externally controlled string | +| test.py:25:12:25:43 | pyramid.routed.response | externally controlled string | diff --git a/python/ql/test/library-tests/web/pyramid/HttpResponseSinks.ql b/python/ql/test/library-tests/web/pyramid/HttpResponseSinks.ql new file mode 100644 index 00000000000..e62ec486da6 --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/HttpResponseSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from HttpResponseTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/pyramid/HttpSources.expected b/python/ql/test/library-tests/web/pyramid/HttpSources.expected new file mode 100644 index 00000000000..7a07771b188 --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/HttpSources.expected @@ -0,0 +1,3 @@ +| test.py:7:10:7:16 | request | pyramid.request | +| test.py:15:11:15:17 | request | pyramid.request | +| test.py:24:11:24:17 | request | pyramid.request | diff --git a/python/ql/test/library-tests/web/pyramid/HttpSources.ql b/python/ql/test/library-tests/web/pyramid/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/pyramid/Routing.ql b/python/ql/test/library-tests/web/pyramid/Routing.ql index ef21e5510fe..4a442c1115e 100644 --- a/python/ql/test/library-tests/web/pyramid/Routing.ql +++ b/python/ql/test/library-tests/web/pyramid/Routing.ql @@ -1,9 +1,6 @@ import python - import semmle.python.web.pyramid.View from Function func - where is_pyramid_view_function(func) - select func.getLocation().toString(), func.toString() diff --git a/python/ql/test/library-tests/web/pyramid/Sinks.expected b/python/ql/test/library-tests/web/pyramid/Sinks.expected deleted file mode 100644 index 03e32dac04a..00000000000 --- a/python/ql/test/library-tests/web/pyramid/Sinks.expected +++ /dev/null @@ -1,3 +0,0 @@ -| test.py:8 | Response() | externally controlled string | -| test.py:17 | Response() | externally controlled string | -| test.py:25 | Dict | externally controlled string | diff --git a/python/ql/test/library-tests/web/pyramid/Sinks.ql b/python/ql/test/library-tests/web/pyramid/Sinks.ql deleted file mode 100644 index 63722622990..00000000000 --- a/python/ql/test/library-tests/web/pyramid/Sinks.ql +++ /dev/null @@ -1,11 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) and sink.getLocation().getFile().getShortName() = "test.py" -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/pyramid/Sources.expected b/python/ql/test/library-tests/web/pyramid/Sources.expected deleted file mode 100644 index f7fe4bb2c5c..00000000000 --- a/python/ql/test/library-tests/web/pyramid/Sources.expected +++ /dev/null @@ -1,3 +0,0 @@ -| test.py:7 | request | pyramid.request | -| test.py:15 | request | pyramid.request | -| test.py:24 | request | pyramid.request | diff --git a/python/ql/test/library-tests/web/pyramid/Sources.ql b/python/ql/test/library-tests/web/pyramid/Sources.ql deleted file mode 100644 index b1b7fe3e08b..00000000000 --- a/python/ql/test/library-tests/web/pyramid/Sources.ql +++ /dev/null @@ -1,11 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/pyramid/Taint.ql b/python/ql/test/library-tests/web/pyramid/Taint.ql index 2c67c626aaa..d68b12079b8 100644 --- a/python/ql/test/library-tests/web/pyramid/Taint.ql +++ b/python/ql/test/library-tests/web/pyramid/Taint.ql @@ -1,11 +1,8 @@ - import python - import semmle.python.web.HttpRequest import semmle.python.web.HttpResponse import semmle.python.security.strings.Untrusted from TaintedNode node where node.getLocation().getFile().getShortName() = "test.py" - select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind() diff --git a/python/ql/test/library-tests/web/tornado/Classes.ql b/python/ql/test/library-tests/web/tornado/Classes.ql index 08346af0dcf..fda9b6eb00a 100644 --- a/python/ql/test/library-tests/web/tornado/Classes.ql +++ b/python/ql/test/library-tests/web/tornado/Classes.ql @@ -1,9 +1,7 @@ - import python - import semmle.python.TestUtils - import semmle.python.web.tornado.Tornado + from ClassValue cls where cls = aTornadoRequestHandlerClass() select remove_library_prefix(cls.getScope().getLocation()), cls.toString() diff --git a/python/ql/test/library-tests/web/tornado/HttpRedirectSinks.expected b/python/ql/test/library-tests/web/tornado/HttpRedirectSinks.expected new file mode 100644 index 00000000000..c262f5b6bbb --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/HttpRedirectSinks.expected @@ -0,0 +1 @@ +| test.py:20:23:20:25 | tornado.HttpRequestHandler.redirect | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/HttpRedirectSinks.ql b/python/ql/test/library-tests/web/tornado/HttpRedirectSinks.ql new file mode 100644 index 00000000000..157ef2d4430 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/HttpRedirectSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRedirect +import semmle.python.security.strings.Untrusted + +from HttpRedirectTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/tornado/HttpResponseSinks.expected b/python/ql/test/library-tests/web/tornado/HttpResponseSinks.expected new file mode 100644 index 00000000000..0309c54ceb5 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/HttpResponseSinks.expected @@ -0,0 +1,3 @@ +| test.py:6:20:6:43 | tornado.HttpRequestHandler.write | externally controlled string | +| test.py:12:20:12:23 | tornado.HttpRequestHandler.write | externally controlled string | +| test.py:26:20:26:48 | tornado.HttpRequestHandler.write | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/HttpResponseSinks.ql b/python/ql/test/library-tests/web/tornado/HttpResponseSinks.ql new file mode 100644 index 00000000000..e62ec486da6 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/HttpResponseSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from HttpResponseTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/tornado/HttpSources.expected b/python/ql/test/library-tests/web/tornado/HttpSources.expected new file mode 100644 index 00000000000..bcab5502996 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/HttpSources.expected @@ -0,0 +1,4 @@ +| test.py:6:20:6:43 | Attribute() | externally controlled string | +| test.py:10:16:10:40 | Attribute() | [externally controlled string] | +| test.py:17:15:17:26 | Attribute | tornado.request.HttpRequest | +| test.py:26:20:26:48 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/HttpSources.ql b/python/ql/test/library-tests/web/tornado/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/tornado/Sinks.expected b/python/ql/test/library-tests/web/tornado/Sinks.expected deleted file mode 100644 index d493bb82ee3..00000000000 --- a/python/ql/test/library-tests/web/tornado/Sinks.expected +++ /dev/null @@ -1,4 +0,0 @@ -| test.py:6 | Attribute() | externally controlled string | -| test.py:12 | name | externally controlled string | -| test.py:20 | url | externally controlled string | -| test.py:26 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/Sinks.ql b/python/ql/test/library-tests/web/tornado/Sinks.ql deleted file mode 100644 index 7d338fe63c6..00000000000 --- a/python/ql/test/library-tests/web/tornado/Sinks.ql +++ /dev/null @@ -1,11 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted -import semmle.python.TestUtils - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select remove_library_prefix(sink.getLocation()), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/tornado/Sources.expected b/python/ql/test/library-tests/web/tornado/Sources.expected deleted file mode 100644 index 78fb140df3c..00000000000 --- a/python/ql/test/library-tests/web/tornado/Sources.expected +++ /dev/null @@ -1,4 +0,0 @@ -| test.py:6 | Attribute() | externally controlled string | -| test.py:10 | Attribute() | [externally controlled string] | -| test.py:17 | Attribute | tornado.request.HttpRequest | -| test.py:26 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/Sources.ql b/python/ql/test/library-tests/web/tornado/Sources.ql deleted file mode 100644 index 164f45d627b..00000000000 --- a/python/ql/test/library-tests/web/tornado/Sources.ql +++ /dev/null @@ -1,13 +0,0 @@ - -import python - -import semmle.python.TestUtils - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select remove_library_prefix(src.getLocation()), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/tornado/Taint.ql b/python/ql/test/library-tests/web/tornado/Taint.ql index d0b1d327341..d4fc34b643c 100644 --- a/python/ql/test/library-tests/web/tornado/Taint.ql +++ b/python/ql/test/library-tests/web/tornado/Taint.ql @@ -1,8 +1,5 @@ - import python - import semmle.python.TestUtils - import semmle.python.web.HttpRequest import semmle.python.web.HttpResponse import semmle.python.security.strings.Untrusted @@ -11,4 +8,3 @@ from TaintedNode node // Add this restriction to keep Python2 and 3 results the same. where not exists(node.getContext().getCaller()) select remove_library_prefix(node.getLocation()), node.getAstNode().toString(), node.getTaintKind() - diff --git a/python/ql/test/library-tests/web/turbogears/Controller.ql b/python/ql/test/library-tests/web/turbogears/Controller.ql index a21462ffadb..850e56ef453 100644 --- a/python/ql/test/library-tests/web/turbogears/Controller.ql +++ b/python/ql/test/library-tests/web/turbogears/Controller.ql @@ -1,9 +1,5 @@ - - import python - import semmle.python.web.turbogears.TurboGears from TurboGearsControllerMethod m select m - diff --git a/python/ql/test/library-tests/web/turbogears/HttpResponseSinks.expected b/python/ql/test/library-tests/web/turbogears/HttpResponseSinks.expected new file mode 100644 index 00000000000..bb2cc079e15 --- /dev/null +++ b/python/ql/test/library-tests/web/turbogears/HttpResponseSinks.expected @@ -0,0 +1,5 @@ +| test.py:8:16:8:69 | TurboGears ControllerMethodReturnValue | externally controlled string | +| test.py:14:16:14:50 | TurboGears ControllerMethodReturnValue | externally controlled string | +| test.py:19:16:19:50 | TurboGears ControllerMethodReturnValue | externally controlled string | +| test.py:23:16:23:50 | TurboGears ControllerMethodReturnValue | externally controlled string | +| test.py:27:16:27:38 | TurboGears ControllerMethodTemplatedReturnValue | {externally controlled string} | diff --git a/python/ql/test/library-tests/web/turbogears/HttpResponseSinks.ql b/python/ql/test/library-tests/web/turbogears/HttpResponseSinks.ql new file mode 100644 index 00000000000..e62ec486da6 --- /dev/null +++ b/python/ql/test/library-tests/web/turbogears/HttpResponseSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from HttpResponseTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/turbogears/HttpSources.expected b/python/ql/test/library-tests/web/turbogears/HttpSources.expected new file mode 100644 index 00000000000..cae6b169eb6 --- /dev/null +++ b/python/ql/test/library-tests/web/turbogears/HttpSources.expected @@ -0,0 +1,3 @@ +| test.py:18:43:18:43 | b | externally controlled string | +| test.py:22:29:22:29 | a | externally controlled string | +| test.py:22:37:22:37 | b | externally controlled string | diff --git a/python/ql/test/library-tests/web/turbogears/HttpSources.ql b/python/ql/test/library-tests/web/turbogears/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/turbogears/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/turbogears/Sinks.expected b/python/ql/test/library-tests/web/turbogears/Sinks.expected deleted file mode 100644 index b528861c340..00000000000 --- a/python/ql/test/library-tests/web/turbogears/Sinks.expected +++ /dev/null @@ -1,5 +0,0 @@ -| test.py:8 | BinaryExpr | externally controlled string | -| test.py:14 | BinaryExpr | externally controlled string | -| test.py:19 | BinaryExpr | externally controlled string | -| test.py:23 | BinaryExpr | externally controlled string | -| test.py:27 | Dict | {externally controlled string} | diff --git a/python/ql/test/library-tests/web/turbogears/Sinks.ql b/python/ql/test/library-tests/web/turbogears/Sinks.ql deleted file mode 100644 index 34aa1cfc429..00000000000 --- a/python/ql/test/library-tests/web/turbogears/Sinks.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/turbogears/Sources.expected b/python/ql/test/library-tests/web/turbogears/Sources.expected deleted file mode 100644 index fe82da5847e..00000000000 --- a/python/ql/test/library-tests/web/turbogears/Sources.expected +++ /dev/null @@ -1,3 +0,0 @@ -| test.py:18 | b | externally controlled string | -| test.py:22 | a | externally controlled string | -| test.py:22 | b | externally controlled string | diff --git a/python/ql/test/library-tests/web/turbogears/Sources.ql b/python/ql/test/library-tests/web/turbogears/Sources.ql deleted file mode 100644 index aece91f44e2..00000000000 --- a/python/ql/test/library-tests/web/turbogears/Sources.ql +++ /dev/null @@ -1,10 +0,0 @@ - -import python - -import semmle.python.web.HttpRequest -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/turbogears/Taint.ql b/python/ql/test/library-tests/web/turbogears/Taint.ql index 2c74191e645..09972af5f98 100644 --- a/python/ql/test/library-tests/web/turbogears/Taint.ql +++ b/python/ql/test/library-tests/web/turbogears/Taint.ql @@ -1,13 +1,7 @@ - import python - - import semmle.python.web.HttpRequest import semmle.python.web.HttpResponse import semmle.python.security.strings.Untrusted - from TaintedNode node - select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind() - diff --git a/python/ql/test/library-tests/web/twisted/HttpResponseSinks.expected b/python/ql/test/library-tests/web/twisted/HttpResponseSinks.expected new file mode 100644 index 00000000000..ab5b0f5a4a8 --- /dev/null +++ b/python/ql/test/library-tests/web/twisted/HttpResponseSinks.expected @@ -0,0 +1,10 @@ +| test.py:7:16:7:23 | Twisted response | externally controlled string | +| test.py:14:16:14:23 | Twisted response | externally controlled string | +| test.py:21:16:21:23 | Twisted response | externally controlled string | +| test.py:36:16:36:37 | Twisted response | externally controlled string | +| test.py:40:23:40:30 | Twisted request setter | externally controlled string | +| test.py:44:27:44:31 | Twisted request setter | externally controlled string | +| test.py:44:34:44:38 | Twisted request setter | externally controlled string | +| test.py:45:27:45:31 | Twisted request setter | externally controlled string | +| test.py:45:34:45:40 | Twisted request setter | externally controlled string | +| test.py:46:16:46:37 | Twisted response | externally controlled string | diff --git a/python/ql/test/library-tests/web/twisted/HttpResponseSinks.ql b/python/ql/test/library-tests/web/twisted/HttpResponseSinks.ql new file mode 100644 index 00000000000..e62ec486da6 --- /dev/null +++ b/python/ql/test/library-tests/web/twisted/HttpResponseSinks.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from HttpResponseTaintSink sink, TaintKind kind +where sink.sinks(kind) +select sink, kind diff --git a/python/ql/test/library-tests/web/twisted/HttpSources.expected b/python/ql/test/library-tests/web/twisted/HttpSources.expected new file mode 100644 index 00000000000..9f9991e9944 --- /dev/null +++ b/python/ql/test/library-tests/web/twisted/HttpSources.expected @@ -0,0 +1,8 @@ +| test.py:4:22:4:28 | request | twisted.request.http.Request | +| test.py:9:26:9:32 | request | twisted.request.http.Request | +| test.py:16:27:16:33 | request | twisted.request.http.Request | +| test.py:24:24:24:30 | request | twisted.request.http.Request | +| test.py:28:22:28:30 | myrequest | twisted.request.http.Request | +| test.py:31:27:31:37 | postrequest | twisted.request.http.Request | +| test.py:39:22:39:28 | request | twisted.request.http.Request | +| test.py:43:22:43:28 | request | twisted.request.http.Request | diff --git a/python/ql/test/library-tests/web/twisted/HttpSources.ql b/python/ql/test/library-tests/web/twisted/HttpSources.ql new file mode 100644 index 00000000000..6fa1a7d2a6b --- /dev/null +++ b/python/ql/test/library-tests/web/twisted/HttpSources.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +from HttpRequestTaintSource source, TaintKind kind +where source.isSourceOf(kind) +select source.(ControlFlowNode).getNode(), kind diff --git a/python/ql/test/library-tests/web/twisted/Sinks.expected b/python/ql/test/library-tests/web/twisted/Sinks.expected deleted file mode 100644 index f416a03e4b7..00000000000 --- a/python/ql/test/library-tests/web/twisted/Sinks.expected +++ /dev/null @@ -1,8 +0,0 @@ -| test.py:7 | response | externally controlled string | -| test.py:14 | response | externally controlled string | -| test.py:21 | response | externally controlled string | -| test.py:36 | do_stuff_with() | externally controlled string | -| test.py:40 | Str | externally controlled string | -| test.py:44 | Str | externally controlled string | -| test.py:45 | Str | externally controlled string | -| test.py:46 | Str | externally controlled string | diff --git a/python/ql/test/library-tests/web/twisted/Sinks.ql b/python/ql/test/library-tests/web/twisted/Sinks.ql deleted file mode 100644 index 1045e9dda6b..00000000000 --- a/python/ql/test/library-tests/web/twisted/Sinks.ql +++ /dev/null @@ -1,10 +0,0 @@ -import python - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted -import semmle.python.TestUtils - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select remove_library_prefix(sink.getLocation()), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/twisted/Sources.expected b/python/ql/test/library-tests/web/twisted/Sources.expected deleted file mode 100644 index 3015951d32b..00000000000 --- a/python/ql/test/library-tests/web/twisted/Sources.expected +++ /dev/null @@ -1,8 +0,0 @@ -| test.py:4 | request | twisted.request.http.Request | -| test.py:9 | request | twisted.request.http.Request | -| test.py:16 | request | twisted.request.http.Request | -| test.py:24 | request | twisted.request.http.Request | -| test.py:28 | myrequest | twisted.request.http.Request | -| test.py:31 | postrequest | twisted.request.http.Request | -| test.py:39 | request | twisted.request.http.Request | -| test.py:43 | request | twisted.request.http.Request | diff --git a/python/ql/test/library-tests/web/twisted/Sources.ql b/python/ql/test/library-tests/web/twisted/Sources.ql deleted file mode 100644 index bded6087ed2..00000000000 --- a/python/ql/test/library-tests/web/twisted/Sources.ql +++ /dev/null @@ -1,11 +0,0 @@ -import python -import semmle.python.TestUtils - -import semmle.python.web.HttpRequest -import semmle.python.web.HttpResponse -import semmle.python.security.strings.Untrusted - - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select remove_library_prefix(src.getLocation()), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/twisted/Taint.ql b/python/ql/test/library-tests/web/twisted/Taint.ql index f0a95299113..e92616b6b29 100644 --- a/python/ql/test/library-tests/web/twisted/Taint.ql +++ b/python/ql/test/library-tests/web/twisted/Taint.ql @@ -1,11 +1,8 @@ import python import semmle.python.TestUtils - import semmle.python.web.HttpRequest import semmle.python.web.HttpResponse import semmle.python.security.strings.Untrusted from TaintedNode node - select remove_library_prefix(node.getLocation()), node.getAstNode().toString(), node.getTaintKind() -