diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index e883f885f0b..ce317236f93 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -8,13 +8,16 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| -| Query name (`query id`) | tags | Message. | +| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). | ## Changes to existing queries | **Query** | **Expected impact** | **Change** | |----------------------------|------------------------|------------------------------------------------------------------| | Query name (`query id`) | Expected impact | Message. | +| Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) | Deprecated | This query has been deprecated. Use the new combined query Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) instead. | +| Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`) | Deprecated | This query has been deprecated. Use the new combined query Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) instead. | +| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | More correct results | This query now checks for the beginning date of the Reiwa era (1st May 2019). | ## Changes to QL libraries @@ -25,3 +28,10 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. picture of the partial flow paths from a given source. The feature is disabled by default and can be enabled for individual configurations by overriding `int explorationLimit()`. +* The `DataFlow::DefinitionByReferenceNode` class now considers `f(x)` to be a + definition of `x` when `x` is a variable of pointer type. It no longer + considers deep paths such as `f(&x.myField)` to be definitions of `x`. These + changes are in line with the user expectations we've observed. +* There is now a `DataFlow::localExprFlow` predicate and a + `TaintTracking::localExprTaint` predicate to make it easy to use the most + common case of local data flow and taint: from one `Expr` to another. diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index a3cc5906068..697f6e01423 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -18,6 +18,7 @@ | **Query** | **Expected impact** | **Change** | |--------------------------------|------------------------------|---------------------------------------------------------------------------| | Client-side cross-site scripting (`js/xss`) | More results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized. | +| Prototype pollution (`js/prototype-pollution`) | More results | The query now highlights vulnerable uses of jQuery and Angular, and the results are shown on LGTM by default. | ## Changes to QL libraries diff --git a/change-notes/1.23/extractor-javascript.md b/change-notes/1.23/extractor-javascript.md new file mode 100644 index 00000000000..ed9664ce812 --- /dev/null +++ b/change-notes/1.23/extractor-javascript.md @@ -0,0 +1,7 @@ +[[ condition: enterprise-only ]] + +# Improvements to JavaScript analysis + +## Changes to code extraction + +* Asynchronous generator methods are now parsed correctly and no longer cause a spurious syntax error. diff --git a/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.qhelp b/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.qhelp new file mode 100644 index 00000000000..f009401099a --- /dev/null +++ b/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.qhelp @@ -0,0 +1,17 @@ + + + +

+ When eras change, date and time conversions that rely on a hard-coded era start date need to be reviewed. Conversions relying on Japanese dates in the current era can produce an ambiguous date. + The values for the current Japanese era dates should be read from a source that will be updated, such as the Windows registry. +

+
+ + +
  • + The Japanese Calendar's Y2K Moment. +
  • +
    +
    diff --git a/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.ql b/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.ql new file mode 100644 index 00000000000..6abdb6feb8c --- /dev/null +++ b/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.ql @@ -0,0 +1,73 @@ +/** + * @name Hard-coded Japanese era start date + * @description Japanese era changes can lead to code behaving differently. Avoid hard-coding Japanese era start dates. + * @kind problem + * @problem.severity warning + * @id cpp/japanese-era/exact-era-date + * @precision medium + * @tags reliability + * japanese-era + */ + +import cpp +import semmle.code.cpp.commons.DateTime + +predicate assignedYear(Struct s, YearFieldAccess year, int value) { + exists(Operation yearAssignment | + s.getAField().getAnAccess() = year and + yearAssignment.getAnOperand() = year and + yearAssignment.getAnOperand().getValue().toInt() = value + ) +} + +predicate assignedMonth(Struct s, MonthFieldAccess month, int value) { + exists(Operation monthAssignment | + s.getAField().getAnAccess() = month and + monthAssignment.getAnOperand() = month and + monthAssignment.getAnOperand().getValue().toInt() = value + ) +} + +predicate assignedDay(Struct s, DayFieldAccess day, int value) { + exists(Operation dayAssignment | + s.getAField().getAnAccess() = day and + dayAssignment.getAnOperand() = day and + dayAssignment.getAnOperand().getValue().toInt() = value + ) +} + +predicate eraDate(int year, int month, int day) { + year = 1989 and month = 1 and day = 8 + or + year = 2019 and month = 5 and day = 1 +} + + +predicate badStructInitialization(Element target, string message) { + exists( + StructLikeClass s, YearFieldAccess year, MonthFieldAccess month, DayFieldAccess day, + int yearValue, int monthValue, int dayValue + | + eraDate(yearValue, monthValue, dayValue) and + assignedYear(s, year, yearValue) and + assignedMonth(s, month, monthValue) and + assignedDay(s, day, dayValue) and + target = year and + message = "A time struct that is initialized with exact Japanese calendar era start date." + ) +} + +predicate badCall(Element target, string message) { + exists(Call cc, int i | + eraDate(cc.getArgument(i).getValue().toInt(), cc.getArgument(i + 1).getValue().toInt(), + cc.getArgument(i + 2).getValue().toInt()) and + target = cc and + message = "Call that appears to have hard-coded Japanese era start date as parameter." + ) +} + +from Element target, string message +where + badStructInitialization(target, message) or + badCall(target, message) +select target, message diff --git a/cpp/ql/src/Critical/NewDelete.qll b/cpp/ql/src/Critical/NewDelete.qll index 5cd7ef646d1..39b265556b0 100644 --- a/cpp/ql/src/Critical/NewDelete.qll +++ b/cpp/ql/src/Critical/NewDelete.qll @@ -47,7 +47,7 @@ predicate allocExprOrIndirect(Expr alloc, string kind) { or exists(Expr e | allocExprOrIndirect(e, kind) and - DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(rtn.getExpr())) + DataFlow::localExprFlow(e, rtn.getExpr()) ) ) ) diff --git a/cpp/ql/src/Critical/OverflowStatic.ql b/cpp/ql/src/Critical/OverflowStatic.ql index a0917c47024..bd76173b6f4 100644 --- a/cpp/ql/src/Critical/OverflowStatic.ql +++ b/cpp/ql/src/Critical/OverflowStatic.ql @@ -95,7 +95,7 @@ class CallWithBufferSize extends FunctionCall { int statedSizeValue() { exists(Expr statedSizeSrc | - DataFlow::localFlow(DataFlow::exprNode(statedSizeSrc), DataFlow::exprNode(statedSizeExpr())) and + DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr()) and result = statedSizeSrc.getValue().toInt() ) } diff --git a/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql b/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql index 5a8c3ee84bc..0b844bdcbf5 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql @@ -55,7 +55,7 @@ predicate whiteListWrapped(FunctionCall fc) { whitelistPow(fc) or exists(Expr e, ReturnStmt rs | whiteListWrapped(e) and - DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(rs.getExpr())) and + DataFlow::localExprFlow(e, rs.getExpr()) and fc.getTarget() = rs.getEnclosingFunction() ) } diff --git a/cpp/ql/src/Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql b/cpp/ql/src/Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql index 2a6a0f52874..fa468c74218 100644 --- a/cpp/ql/src/Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql +++ b/cpp/ql/src/Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql @@ -1,5 +1,5 @@ /** - * @name Hard-coded Japanese era start date + * @name Hard-coded Japanese era start date in call * @description Japanese era changes can lead to code behaving differently. Avoid hard-coding Japanese era start dates. * @kind problem * @problem.severity warning @@ -7,6 +7,9 @@ * @precision medium * @tags reliability * japanese-era + * @deprecated This query is deprecated, use + * Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) + * instead. */ import cpp diff --git a/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql b/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql index 72069d07e13..fe924954d99 100644 --- a/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql +++ b/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql @@ -1,5 +1,5 @@ /** - * @name Hard-coded Japanese era start date + * @name Hard-coded Japanese era start date in struct * @description Japanese era changes can lead to code behaving differently. Avoid hard-coding Japanese era start dates. * @kind problem * @problem.severity warning @@ -7,6 +7,9 @@ * @precision medium * @tags reliability * japanese-era + * @deprecated This query is deprecated, use + * Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) + * instead. */ import cpp diff --git a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll index dbb4c261519..0f1a37d4813 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll +++ b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll @@ -4,7 +4,6 @@ import cpp import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.controlflow.Guards import semmle.code.cpp.commons.DateTime /** diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql b/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql index e41b9f7113d..ddc74cc6205 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql @@ -23,7 +23,7 @@ predicate isBoolean(Expr e1) { } predicate isStringCopyCastedAsBoolean(FunctionCall func, Expr expr1, string msg) { - DataFlow::localFlow(DataFlow::exprNode(func), DataFlow::exprNode(expr1)) and + DataFlow::localExprFlow(func, expr1) and isBoolean(expr1.getConversion*()) and func.getTarget() instanceof StrcpyFunction and msg = "Return value of " + func.getTarget().getName() + " used as a Boolean." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql b/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql index 99e771d0fbf..74d87182380 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql @@ -10,8 +10,9 @@ * security * external/cwe/cwe-676 * @deprecated This query is deprecated, use - * Security/CWE/CWE-120/OverrunWrite.ql and - * Security/CWE/CWE-120/OverrunWriteFloat.ql instead. + * Potentially overrunning write (`cpp/overrunning-write`) and + * Potentially overrunning write with float to string conversion + * (`cpp/overrunning-write-with-float) instead. */ import cpp import semmle.code.cpp.commons.Buffer diff --git a/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql b/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql index 2cb6d111c9b..e4284bbd804 100644 --- a/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql +++ b/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql @@ -8,8 +8,8 @@ * @problem.severity warning * @tags reliability * @deprecated This query is deprecated, and replaced by - * jsf/4.10 Classes/AV Rule 78.ql, which has far fewer false - * positives on typical code. + * No virtual destructor (`cpp/jsf/av-rule-78`), which has far + * fewer false positives on typical code. */ import cpp diff --git a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql index e45be7640bf..d5ab739f348 100644 --- a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql +++ b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql @@ -36,12 +36,10 @@ class MallocCall extends FunctionCall predicate terminationProblem(MallocCall malloc, string msg) { malloc.getAllocatedSize() instanceof StrlenCall and - not exists(DataFlow::Node def, DataFlow::Node use, FunctionCall fc, MemcpyFunction memcpy, int ix | - DataFlow::localFlow(def, use) and - def.asExpr() = malloc and + not exists(FunctionCall fc, MemcpyFunction memcpy, int ix | + DataFlow::localExprFlow(malloc, fc.getArgument(ix)) and fc.getTarget() = memcpy and - memcpy.hasArrayOutput(ix) and - use.asExpr() = fc.getArgument(ix) + memcpy.hasArrayOutput(ix) ) and msg = "This allocation does not include space to null-terminate the string." } diff --git a/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql b/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql index af343fc991f..604f3915e98 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql @@ -12,7 +12,7 @@ * external/cwe/cwe-197 * external/cwe/cwe-835 * -*/ + */ import cpp import semmle.code.cpp.controlflow.Dominance diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow.qll b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow.qll index bfb93f77bfa..3425e9b9901 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow.qll @@ -11,8 +11,10 @@ * * To use global (interprocedural) data flow, extend the class * `DataFlow::Configuration` as documented on that class. To use local - * (intraprocedural) data flow, invoke `DataFlow::localFlow` or - * `DataFlow::LocalFlowStep` with arguments of type `DataFlow::Node`. + * (intraprocedural) data flow between expressions, call + * `DataFlow::localExprFlow`. For more general cases of local data flow, call + * `DataFlow::localFlow` or `DataFlow::localFlowStep` with arguments of type + * `DataFlow::Node`. */ import cpp diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking.qll b/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking.qll index 92cd085927a..a40579adde1 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking.qll @@ -6,6 +6,13 @@ * the information from the source is preserved at the sink. For example, taint * propagates from `x` to `x + 100`, but it does not propagate from `x` to `x > * 100` since we consider a single bit of information to be too little. + * + * To use global (interprocedural) taint tracking, extend the class + * `TaintTracking::Configuration` as documented on that class. To use local + * (intraprocedural) taint tracking between expressions, call + * `TaintTracking::localExprTaint`. For more general cases of local taint + * tracking, call `TaintTracking::localTaint` or + * `TaintTracking::localTaintStep` with arguments of type `DataFlow::Node`. */ import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.dataflow.DataFlow2 diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking2.qll index f67a0e71100..bde6c363347 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking2.qll @@ -1,11 +1,14 @@ /** - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) taint-tracking analyses. + * Provides a `TaintTracking2` module, which is a copy of the `TaintTracking` + * module. Use this class when data-flow configurations or taint-tracking + * configurations must depend on each other. Two classes extending + * `DataFlow::Configuration` should never depend on each other, but one of them + * should instead depend on a `DataFlow2::Configuration`, a + * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. The + * `TaintTracking::Configuration` class extends `DataFlow::Configuration`, and + * `TaintTracking2::Configuration` extends `DataFlow2::Configuration`. * - * We define _taint propagation_ informally to mean that a substantial part of - * the information from the source is preserved at the sink. For example, taint - * propagates from `x` to `x + 100`, but it does not propagate from `x` to `x > - * 100` since we consider a single bit of information to be too little. + * See `semmle.code.cpp.dataflow.TaintTracking` for the full documentation. */ module TaintTracking2 { import semmle.code.cpp.dataflow.internal.tainttracking2.TaintTrackingImpl diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 9bb6a70c742..97052e80004 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -363,6 +363,7 @@ private module ImplCommon { newtype TReturnPosition = TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) } } + import ImplCommon pragma[noinline] @@ -418,7 +419,6 @@ class CallContextReturn extends CallContext, TReturn { /** A callable tagged with a relevant return kind. */ class ReturnPosition extends TReturnPosition0 { private DataFlowCallable c; - private ReturnKind kind; ReturnPosition() { this = TReturnPosition0(c, kind) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index f906f989b48..c7456c714d9 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -496,6 +496,12 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { */ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } +/** + * Holds if data can flow from `e1` to `e2` in zero or more + * local (intra-procedural) steps. + */ +predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) } + /** * Holds if the initial value of `v`, if it is a source, flows to `var`. */ diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 3130e64d7d6..74e96d8d063 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -84,18 +84,28 @@ cached class FlowVar extends TFlowVar { * * In contrast to a normal "definition", which provides a new value for * something, a partial definition is an expression that may affect a - * value, but does not necessarily replace it entirely. For example, - * `x.y = 1;` is a partial definition of the object `x`. + * value, but does not necessarily replace it entirely. For example: + * ``` + * x.y = 1; // a partial definition of the object `x`. + * x.y.z = 1; // a partial definition of the objects `x` and `x.y`. + * x.setY(1); // a partial definition of the object `x`. + * setY(&x); // a partial definition of the object `x`. + * ``` */ private module PartialDefinitions { private newtype TPartialDefinition = TExplicitFieldStoreQualifier(Expr qualifier, ControlFlowNode node) { - exists(FieldAccess fa | - isInstanceFieldWrite(fa, node) and qualifier = fa.getQualifier() + exists(FieldAccess fa | qualifier = fa.getQualifier() | + isInstanceFieldWrite(fa, node) + or + exists(PartialDefinition pd | + node = pd.getSubBasicBlockStart() and + fa = pd.getDefinedExpr() + ) ) } or TExplicitCallQualifier(Expr qualifier, Call call) { qualifier = call.getQualifier() } or - TReferenceArgument(Expr arg, VariableAccess va) { definitionByReference(va, arg) } + TReferenceArgument(Expr arg, VariableAccess va) { referenceArgument(va, arg) } private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) { not fa.getTarget().isStatic() and @@ -116,8 +126,19 @@ private module PartialDefinitions { predicate partiallyDefinesThis(ThisExpr e) { definedExpr = e } + /** + * Gets the subBasicBlock where this `PartialDefinition` is defined. + */ ControlFlowNode getSubBasicBlockStart() { result = node } + /** + * Gets the expression that is being partially defined. For example in the + * following code: + * ``` + * x.y = 1; + * ``` + * The expression `x` is being partially defined. + */ Expr getDefinedExpr() { result = definedExpr } Location getLocation() { @@ -133,18 +154,48 @@ private module PartialDefinitions { } /** - * A partial definition that's a definition by reference (in the sense of the - * `definitionByReference` predicate). + * A partial definition that's a definition by reference. */ class DefinitionByReference extends PartialDefinition, TReferenceArgument { VariableAccess va; - DefinitionByReference() { definitionByReference(va, definedExpr) } + DefinitionByReference() { + // `this` is not restricted in this charpred. That's because the full + // extent of this class includes the charpred of the superclass, which + // relates `this` to `definedExpr`, and `va` is functionally determined + // by `definedExpr`. + referenceArgument(va, definedExpr) + } VariableAccess getVariableAccess() { result = va } override predicate partiallyDefines(Variable v) { va = v.getAnAccess() } } + + private predicate referenceArgument(VariableAccess va, Expr argument) { + argument = any(Call c).getAnArgument() and + exists(Type argumentType | + argumentType = argument.getFullyConverted().getType().stripTopLevelSpecifiers() + | + argumentType instanceof ReferenceType and + not argumentType.(ReferenceType).getBaseType().isConst() and + va = argument + or + argumentType instanceof PointerType and + not argumentType.(PointerType).getBaseType().isConst() and + ( + // f(variable) + va = argument + or + // f(&variable) + va = argument.(AddressOfExpr).getOperand() + or + // f(&array[0]) + va.getType().getUnspecifiedType() instanceof ArrayType and + va = argument.(AddressOfExpr).getOperand().(ArrayExpr).getArrayBase() + ) + ) + } } import PartialDefinitions private import FlowVar_internal @@ -215,7 +266,7 @@ module FlowVar_internal { not v instanceof Field and // Fields are interprocedural data flow, not local reachable(sbb) and ( - initializer(sbb.getANode(), v, _) + initializer(v, sbb.getANode()) or assignmentLikeOperation(sbb, v, _, _) or @@ -332,7 +383,12 @@ module FlowVar_internal { assignmentLikeOperation(node, v, _, e) and node = sbb or - initializer(node, v, e) and + // We pick the defining `ControlFlowNode` of an `Initializer` to be its + // expression rather than the `Initializer` itself. That's because the + // `Initializer` of a `ConditionDeclExpr` is for historical reasons not + // part of the CFG and therefore ends up in the wrong basic block. + initializer(v, e) and + node = e and node = sbb.getANode() } @@ -690,13 +746,11 @@ module FlowVar_internal { } /** - * Holds if `v` is initialized by `init` to have value `assignedExpr`. + * Holds if `v` is initialized to have value `assignedExpr`. */ - predicate initializer( - Initializer init, LocalVariable v, Expr assignedExpr) + predicate initializer(LocalVariable v, Expr assignedExpr) { - v = init.getDeclaration() and - assignedExpr = init.getExpr() + assignedExpr = v.getInitializer().getExpr() } /** diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll index e379157a603..93910382cee 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -80,6 +80,14 @@ predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) } +/** + * Holds if taint can flow from `e1` to `e2` in zero or more + * local (intra-procedural) steps. + */ +predicate localExprTaint(Expr e1, Expr e2) { + localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2)) +} + /** * Holds if we do not propagate taint from `fromExpr` to `toExpr` * even though `toExpr` is the AST parent of `fromExpr`. diff --git a/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll b/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll index 61cd3b2d056..73d3cb6772e 100644 --- a/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll +++ b/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll @@ -1,7 +1,9 @@ import semmle.code.cpp.Type +/** For upgraded databases without mangled name info. */ pragma[noinline] private string getTopLevelClassName(@usertype c) { + not mangled_name(_, _) and isClass(c) and usertypes(c, result, _) and not namespacembrs(_, c) and // not in a namespace @@ -9,24 +11,76 @@ private string getTopLevelClassName(@usertype c) { not class_instantiation(c, _) // not a template instantiation } -/** Holds if `d` is a unique complete class named `name`. */ +/** + * For upgraded databases without mangled name info. + * Holds if `d` is a unique complete class named `name`. + */ pragma[noinline] private predicate existsCompleteWithName(string name, @usertype d) { + not mangled_name(_, _) and is_complete(d) and name = getTopLevelClassName(d) and onlyOneCompleteClassExistsWithName(name) } +/** For upgraded databases without mangled name info. */ pragma[noinline] private predicate onlyOneCompleteClassExistsWithName(string name) { + not mangled_name(_, _) and strictcount(@usertype c | is_complete(c) and getTopLevelClassName(c) = name) = 1 } +/** + * For upgraded databases without mangled name info. + * Holds if `c` is an incomplete class named `name`. + */ +pragma[noinline] +private predicate existsIncompleteWithName(string name, @usertype c) { + not mangled_name(_, _) and + not is_complete(c) and + name = getTopLevelClassName(c) +} + +/** + * For upgraded databases without mangled name info. + * Holds if `c` is an incomplete class, and there exists a unique complete class `d` + * with the same name. + */ +private predicate oldHasCompleteTwin(@usertype c, @usertype d) { + not mangled_name(_, _) and + exists(string name | + existsIncompleteWithName(name, c) and + existsCompleteWithName(name, d) + ) +} + +pragma[noinline] +private @mangledname getTopLevelClassMangledName(@usertype c) { + isClass(c) and + mangled_name(c, result) and + not namespacembrs(_, c) and // not in a namespace + not member(_, _, c) and // not in some structure + not class_instantiation(c, _) // not a template instantiation +} + +/** Holds if `d` is a unique complete class named `name`. */ +pragma[noinline] +private predicate existsCompleteWithMangledName(@mangledname name, @usertype d) { + is_complete(d) and + name = getTopLevelClassMangledName(d) and + onlyOneCompleteClassExistsWithMangledName(name) +} + +pragma[noinline] +private predicate onlyOneCompleteClassExistsWithMangledName(@mangledname name) { + strictcount(@usertype c | is_complete(c) and getTopLevelClassMangledName(c) = name) = 1 +} + /** Holds if `c` is an incomplete class named `name`. */ pragma[noinline] -private predicate existsIncompleteWithName(string name, @usertype c) { +private predicate existsIncompleteWithMangledName(@mangledname name, @usertype c) { not is_complete(c) and - name = getTopLevelClassName(c) + name = getTopLevelClassMangledName(c) } /** @@ -34,9 +88,9 @@ private predicate existsIncompleteWithName(string name, @usertype c) { * with the same name. */ private predicate hasCompleteTwin(@usertype c, @usertype d) { - exists(string name | - existsIncompleteWithName(name, c) and - existsCompleteWithName(name, d) + exists(@mangledname name | + existsIncompleteWithMangledName(name, c) and + existsCompleteWithMangledName(name, d) ) } @@ -49,7 +103,11 @@ cached private module Cached { cached @usertype resolveClass(@usertype c) { hasCompleteTwin(c, result) or - (not hasCompleteTwin(c, _) and result = c) + oldHasCompleteTwin(c, result) + or + (not hasCompleteTwin(c, _) and + not oldHasCompleteTwin(c, _) and + result = c) } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index e248fa0dae6..740f4812bdc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 9bb6a70c742..97052e80004 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -363,6 +363,7 @@ private module ImplCommon { newtype TReturnPosition = TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) } } + import ImplCommon pragma[noinline] @@ -418,7 +419,6 @@ class CallContextReturn extends CallContext, TReturn { /** A callable tagged with a relevant return kind. */ class ReturnPosition extends TReturnPosition0 { private DataFlowCallable c; - private ReturnKind kind; ReturnPosition() { this = TReturnPosition0(c, kind) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index e9715925432..1db97a49c03 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -178,6 +178,12 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { */ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } +/** + * Holds if data can flow from `e1` to `e2` in zero or more + * local (intra-procedural) steps. + */ +predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) } + /** * A guard that validates some expression. * diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/EdgeKind.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/EdgeKind.qll index e7b21f0f6ec..650c15f189a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/EdgeKind.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/EdgeKind.qll @@ -76,7 +76,6 @@ DefaultEdge defaultEdge() { result = TDefaultEdge() } */ class CaseEdge extends EdgeKind, TCaseEdge { string minValue; - string maxValue; CaseEdge() { this = TCaseEdge(minValue, maxValue) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll index 2c1b43672fc..a7ca4593ac4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll @@ -59,7 +59,6 @@ abstract class IRVariable extends TIRVariable { */ class IRUserVariable extends IRVariable, TIRUserVariable { Language::Variable var; - Language::Type type; IRUserVariable() { this = TIRUserVariable(var, type, func) } @@ -110,9 +109,7 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { Language::AST ast; - TempVariableTag tag; - Language::Type type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index ea0a3f72998..43f9663d2cd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -922,7 +922,6 @@ class ConvertInstruction extends UnaryInstruction { */ class InheritanceConversionInstruction extends UnaryInstruction { Language::Class baseClass; - Language::Class derivedClass; InheritanceConversionInstruction() { 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 fda04820848..1ced8ef3282 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 @@ -196,9 +196,7 @@ class MemoryOperand extends Operand { */ class NonPhiOperand extends Operand { Instruction useInstr; - Instruction defInstr; - OperandTag tag; NonPhiOperand() { @@ -231,7 +229,6 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand { class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - Overlap overlap; NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) } @@ -359,7 +356,6 @@ class ThisArgumentOperand extends ArgumentOperand { */ class PositionalArgumentOperand extends ArgumentOperand { override PositionalArgumentOperandTag tag; - int argIndex; PositionalArgumentOperand() { argIndex = tag.getArgIndex() } @@ -413,11 +409,8 @@ class SideEffectOperand extends TypedOperand { */ class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; - Instruction defInstr; - IRBlock predecessorBlock; - Overlap overlap; PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll index 2c1b43672fc..a7ca4593ac4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll @@ -59,7 +59,6 @@ abstract class IRVariable extends TIRVariable { */ class IRUserVariable extends IRVariable, TIRUserVariable { Language::Variable var; - Language::Type type; IRUserVariable() { this = TIRUserVariable(var, type, func) } @@ -110,9 +109,7 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { Language::AST ast; - TempVariableTag tag; - Language::Type type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index ea0a3f72998..43f9663d2cd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -922,7 +922,6 @@ class ConvertInstruction extends UnaryInstruction { */ class InheritanceConversionInstruction extends UnaryInstruction { Language::Class baseClass; - Language::Class derivedClass; InheritanceConversionInstruction() { 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 fda04820848..1ced8ef3282 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 @@ -196,9 +196,7 @@ class MemoryOperand extends Operand { */ class NonPhiOperand extends Operand { Instruction useInstr; - Instruction defInstr; - OperandTag tag; NonPhiOperand() { @@ -231,7 +229,6 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand { class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - Overlap overlap; NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) } @@ -359,7 +356,6 @@ class ThisArgumentOperand extends ArgumentOperand { */ class PositionalArgumentOperand extends ArgumentOperand { override PositionalArgumentOperandTag tag; - int argIndex; PositionalArgumentOperand() { argIndex = tag.getArgIndex() } @@ -413,11 +409,8 @@ class SideEffectOperand extends TypedOperand { */ class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; - Instruction defInstr; - IRBlock predecessorBlock; - Overlap overlap; PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll index 2c1b43672fc..a7ca4593ac4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll @@ -59,7 +59,6 @@ abstract class IRVariable extends TIRVariable { */ class IRUserVariable extends IRVariable, TIRUserVariable { Language::Variable var; - Language::Type type; IRUserVariable() { this = TIRUserVariable(var, type, func) } @@ -110,9 +109,7 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { Language::AST ast; - TempVariableTag tag; - Language::Type type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index ea0a3f72998..43f9663d2cd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -922,7 +922,6 @@ class ConvertInstruction extends UnaryInstruction { */ class InheritanceConversionInstruction extends UnaryInstruction { Language::Class baseClass; - Language::Class derivedClass; InheritanceConversionInstruction() { 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 fda04820848..1ced8ef3282 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 @@ -196,9 +196,7 @@ class MemoryOperand extends Operand { */ class NonPhiOperand extends Operand { Instruction useInstr; - Instruction defInstr; - OperandTag tag; NonPhiOperand() { @@ -231,7 +229,6 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand { class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - Overlap overlap; NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) } @@ -359,7 +356,6 @@ class ThisArgumentOperand extends ArgumentOperand { */ class PositionalArgumentOperand extends ArgumentOperand { override PositionalArgumentOperandTag tag; - int argIndex; PositionalArgumentOperand() { argIndex = tag.getArgIndex() } @@ -413,11 +409,8 @@ class SideEffectOperand extends TypedOperand { */ class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; - Instruction defInstr; - IRBlock predecessorBlock; - Overlap overlap; PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) } diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme b/cpp/ql/src/semmlecode.cpp.dbscheme index 81a312e6daf..c4c27a2661b 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme +++ b/cpp/ql/src/semmlecode.cpp.dbscheme @@ -705,6 +705,11 @@ usertype_uuid( unique string uuid: string ref ); +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + is_pod_class(unique int id: @usertype ref); is_standard_layout_class(unique int id: @usertype ref); diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme.stats b/cpp/ql/src/semmlecode.cpp.dbscheme.stats index 245b2047b8e..85160eeeac5 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme.stats +++ b/cpp/ql/src/semmlecode.cpp.dbscheme.stats @@ -116,6 +116,10 @@ 4328015 +@mangledname +533074 + + @type_mention 1699398 @@ -200,6 +204,22 @@ 1685056 +@preincrexpr +63965 + + +@predecrexpr +26590 + + +@assignexpr +551713 + + +@varaccess +5376523 + + @literal 4374193 @@ -276,14 +296,6 @@ 5401 -@preincrexpr -63965 - - -@predecrexpr -26590 - - @conditionalexpr 154429 @@ -396,10 +408,6 @@ 1 -@assignexpr -551713 - - @assignaddexpr 68305 @@ -488,10 +496,6 @@ 30 -@varaccess -5376523 - - @thisaccess 1181367 @@ -844,6 +848,14 @@ 1284491 +@stmt_return +1197363 + + +@stmt_block +1398476 + + @stmt_if 524558 @@ -860,14 +872,6 @@ 85508 -@stmt_return -1197363 - - -@stmt_block -1398476 - - @stmt_end_test_while 149900 @@ -936,14 +940,6 @@ 3 -@ppd_plain_include -321760 - - -@ppd_define -350005 - - @ppd_if 171105 @@ -968,6 +964,14 @@ 329749 +@ppd_plain_include +321760 + + +@ppd_define +350005 + + @ppd_undef 21155 @@ -1492,7 +1496,7 @@ seconds -12182 +12669 @@ -1536,14 +1540,19 @@ 12 +2 +3 +24 + + 3 4 -3149 +3027 4 5 -7416 +7513 @@ -1589,8 +1598,8 @@ 12 -1002 -1003 +1042 +1043 12 @@ -1647,13 +1656,13 @@ 12 -547 -548 +563 +564 12 -577 -578 +620 +621 12 @@ -1670,28 +1679,23 @@ 1 2 -7684 +8036 2 3 -2662 +2711 3 4 -814 +996 4 -14 +597 924 - -14 -616 -97 - @@ -1706,7 +1710,7 @@ 1 2 -12182 +12669 @@ -1722,17 +1726,17 @@ 1 2 -10517 +10796 2 3 -1653 +1835 3 4 -12 +36 @@ -2111,11 +2115,11 @@ cpu_seconds -8437 +8450 elapsed_seconds -170 +182 @@ -2161,17 +2165,17 @@ 1 2 -7112 +7064 2 3 -911 +984 3 9 -413 +401 @@ -2192,7 +2196,7 @@ 2 3 -486 +498 @@ -2208,7 +2212,7 @@ 1 2 -24 +36 2 @@ -2216,38 +2220,48 @@ 24 -3 -4 +4 +5 12 -9 -10 +10 +11 12 -11 -12 +12 +13 12 -21 -22 -24 - - -45 -46 +18 +19 12 -129 -130 +23 +24 12 -133 -134 +57 +58 +12 + + +127 +128 +12 + + +131 +132 +12 + + +237 +238 12 @@ -2255,11 +2269,6 @@ 246 12 - -248 -249 -12 - @@ -2274,7 +2283,7 @@ 1 2 -24 +36 2 @@ -2282,48 +2291,53 @@ 24 -3 -4 +4 +5 12 -9 -10 +10 +11 12 -11 -12 +12 +13 12 -21 -22 -24 - - -45 -46 +17 +18 12 -107 -108 +23 +24 12 -119 -120 +54 +55 12 -177 -178 +105 +106 12 -215 -216 +114 +115 +12 + + +168 +169 +12 + + +222 +223 12 @@ -23516,6 +23530,79 @@ +mangled_name +4326447 + + +id +4326447 + + +mangled_name +533074 + + + + +id +mangled_name + + +12 + + +1 +2 +4326447 + + + + + + +mangled_name +id + + +12 + + +1 +2 +326831 + + +2 +3 +67771 + + +3 +4 +35794 + + +4 +8 +44998 + + +8 +36 +40183 + + +36 +8470 +17495 + + + + + + + + is_pod_class 1041528 @@ -32123,11 +32210,11 @@ kind -1167 +393 location -3937292 +6150603 @@ -32171,69 +32258,69 @@ 12 -4 -18 -97 +5 +28 +30 -22 -48 -85 +71 +82 +30 -48 -91 -97 +94 +255 +30 -123 -295 -97 +271 +627 +30 -341 -541 -97 +858 +1879 +30 -541 -883 -97 +2191 +3716 +30 -1163 -2188 -97 +4305 +6068 +30 -2428 -3029 -97 +7004 +11661 +30 -3265 -4616 -97 +12107 +20202 +30 -4933 -6580 -97 +21965 +29561 +30 -6933 -20444 -97 +32830 +41032 +30 -30541 -198015 -97 +44670 +145995 +30 -399017 -399018 -12 +447805 +725766 +24 @@ -32248,63 +32335,68 @@ 1 -7 -97 +24 +30 -7 -14 -97 +27 +72 +30 -15 -28 -97 +77 +157 +30 -29 -47 -97 +171 +402 +30 -74 -171 -97 +422 +1083 +30 -175 -325 -97 +1179 +1862 +30 -371 -515 -97 +2201 +4268 +30 -623 -1087 -97 +4679 +6584 +30 -1127 -1577 -97 +6624 +11083 +30 -1827 -2138 -97 +11359 +12983 +30 -2219 -8862 -97 +17158 +28621 +30 -9363 -117436 -97 +29980 +88945 +30 + + +128315 +425042 +24 @@ -32320,37 +32412,22 @@ 1 2 -1896838 +4450587 2 3 -762528 +874643 3 -4 -367780 +6 +496205 -4 -5 -283559 - - -5 -9 -309310 - - -9 -73 -295656 - - -73 -110845 -21617 +6 +22445 +329167 @@ -32366,17 +32443,22 @@ 1 2 -2811371 +4599301 2 3 -875346 +812812 3 -30 -250573 +5 +498909 + + +5 +33 +239579 diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp new file mode 100644 index 00000000000..1ba5dada567 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp @@ -0,0 +1,53 @@ +// semmle-extractor-options: --edg --clang + +int source(); +void sink(int); void sink(const int *); void sink(int **); + +struct twoIntFields { + int m1, m2; + int getFirst() { return m1; } +}; + +void following_pointers( + int sourceArray1[], + int cleanArray1[], + twoIntFields sourceStruct1, + twoIntFields *sourceStruct1_ptr, + int (*sourceFunctionPointer)()) +{ + sink(sourceArray1); // flow + + sink(sourceArray1[0]); // no flow + sink(*sourceArray1); // no flow + sink(&sourceArray1); // no flow (since sourceArray1 is really a pointer) + + sink(sourceStruct1.m1); // no flow + sink(sourceStruct1_ptr->m1); // no flow + sink(sourceStruct1_ptr->getFirst()); // no flow + + sourceStruct1_ptr->m1 = source(); + sink(sourceStruct1_ptr->m1); // flow + sink(sourceStruct1_ptr->getFirst()); // flow [NOT DETECTED with IR] + sink(sourceStruct1_ptr->m2); // no flow + sink(sourceStruct1.m1); // no flow + + twoIntFields s = { source(), source() }; + + + sink(s.m2); // flow + + twoIntFields sArray[1] = { { source(), source() } }; + // TODO: fix this like above + sink(sArray[0].m2); // flow (AST dataflow misses this due to limitations of the analysis) + + twoIntFields sSwapped = { .m2 = source(), .m1 = 0 }; + + sink(sSwapped.m2); // flow + + sink(sourceFunctionPointer()); // no flow + + int stackArray[2] = { source(), source() }; + stackArray[0] = source(); + sink(stackArray); // no flow +} + diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.expected index a14cc1d0929..31217a9c75c 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.expected @@ -37,25 +37,25 @@ | test.cpp:24:10:24:11 | t2 | test.cpp:23:23:23:24 | t1 | | test.cpp:24:10:24:11 | t2 | test.cpp:24:5:24:11 | ... = ... | | test.cpp:24:10:24:11 | t2 | test.cpp:26:8:26:9 | t1 | -| test.cpp:430:48:430:54 | source1 | test.cpp:432:17:432:23 | source1 | -| test.cpp:431:12:431:13 | 0 | test.cpp:432:11:432:13 | tmp | -| test.cpp:431:12:431:13 | 0 | test.cpp:432:33:432:35 | tmp | -| test.cpp:431:12:431:13 | 0 | test.cpp:433:8:433:10 | tmp | -| test.cpp:432:10:432:13 | & ... | test.cpp:432:3:432:8 | call to memcpy | -| test.cpp:432:10:432:13 | ref arg & ... | test.cpp:432:3:432:8 | call to memcpy | -| test.cpp:432:10:432:13 | ref arg & ... | test.cpp:432:33:432:35 | tmp | -| test.cpp:432:10:432:13 | ref arg & ... | test.cpp:433:8:433:10 | tmp | -| test.cpp:432:17:432:23 | source1 | test.cpp:432:10:432:13 | ref arg & ... | -| test.cpp:436:53:436:59 | source1 | test.cpp:439:17:439:23 | source1 | -| test.cpp:436:66:436:66 | b | test.cpp:441:7:441:7 | b | -| test.cpp:437:12:437:13 | 0 | test.cpp:438:19:438:21 | tmp | -| test.cpp:437:12:437:13 | 0 | test.cpp:439:11:439:13 | tmp | -| test.cpp:437:12:437:13 | 0 | test.cpp:439:33:439:35 | tmp | -| test.cpp:437:12:437:13 | 0 | test.cpp:440:8:440:10 | tmp | -| test.cpp:437:12:437:13 | 0 | test.cpp:442:10:442:12 | tmp | -| test.cpp:439:10:439:13 | & ... | test.cpp:439:3:439:8 | call to memcpy | -| test.cpp:439:10:439:13 | ref arg & ... | test.cpp:439:3:439:8 | call to memcpy | -| test.cpp:439:10:439:13 | ref arg & ... | test.cpp:439:33:439:35 | tmp | -| test.cpp:439:10:439:13 | ref arg & ... | test.cpp:440:8:440:10 | tmp | -| test.cpp:439:10:439:13 | ref arg & ... | test.cpp:442:10:442:12 | tmp | -| test.cpp:439:17:439:23 | source1 | test.cpp:439:10:439:13 | ref arg & ... | +| test.cpp:382:48:382:54 | source1 | test.cpp:384:17:384:23 | source1 | +| test.cpp:383:12:383:13 | 0 | test.cpp:384:11:384:13 | tmp | +| test.cpp:383:12:383:13 | 0 | test.cpp:384:33:384:35 | tmp | +| test.cpp:383:12:383:13 | 0 | test.cpp:385:8:385:10 | tmp | +| test.cpp:384:10:384:13 | & ... | test.cpp:384:3:384:8 | call to memcpy | +| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:384:3:384:8 | call to memcpy | +| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:384:33:384:35 | tmp | +| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:385:8:385:10 | tmp | +| test.cpp:384:17:384:23 | source1 | test.cpp:384:10:384:13 | ref arg & ... | +| test.cpp:388:53:388:59 | source1 | test.cpp:391:17:391:23 | source1 | +| test.cpp:388:66:388:66 | b | test.cpp:393:7:393:7 | b | +| test.cpp:389:12:389:13 | 0 | test.cpp:390:19:390:21 | tmp | +| test.cpp:389:12:389:13 | 0 | test.cpp:391:11:391:13 | tmp | +| test.cpp:389:12:389:13 | 0 | test.cpp:391:33:391:35 | tmp | +| test.cpp:389:12:389:13 | 0 | test.cpp:392:8:392:10 | tmp | +| test.cpp:389:12:389:13 | 0 | test.cpp:394:10:394:12 | tmp | +| test.cpp:391:10:391:13 | & ... | test.cpp:391:3:391:8 | call to memcpy | +| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:391:3:391:8 | call to memcpy | +| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:391:33:391:35 | tmp | +| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:392:8:392:10 | tmp | +| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:394:10:394:12 | tmp | +| test.cpp:391:17:391:23 | source1 | test.cpp:391:10:391:13 | ref arg & ... | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index 9b8eb8ca577..6c445fb76c1 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -111,54 +111,6 @@ void local_references(int &source1, int clean1) { } } -struct twoIntFields { - int m1, m2; - int getFirst() { return m1; } -}; - -void following_pointers( - int sourceArray1[], - int cleanArray1[], - twoIntFields sourceStruct1, - twoIntFields *sourceStruct1_ptr, - int (*sourceFunctionPointer)()) -{ - sink(sourceArray1); // flow - - sink(sourceArray1[0]); // no flow - sink(*sourceArray1); // no flow - sink(&sourceArray1); // no flow (since sourceArray1 is really a pointer) - - sink(sourceStruct1.m1); // no flow - sink(sourceStruct1_ptr->m1); // no flow - sink(sourceStruct1_ptr->getFirst()); // no flow - - sourceStruct1_ptr->m1 = source(); - sink(sourceStruct1_ptr->m1); // flow - sink(sourceStruct1_ptr->getFirst()); // flow [NOT DETECTED with IR] - sink(sourceStruct1_ptr->m2); // no flow - sink(sourceStruct1.m1); // no flow - - twoIntFields s = { source(), source() }; - - - sink(s.m2); // flow - - twoIntFields sArray[1] = { { source(), source() } }; - // TODO: fix this like above - sink(sArray[0].m2); // flow (AST dataflow misses this due to limitations of the analysis) - - twoIntFields sSwapped = { .m2 = source(), .m1 = 0 }; - - sink(sSwapped.m2); // flow - - sink(sourceFunctionPointer()); // no flow - - int stackArray[2] = { source(), source() }; - stackArray[0] = source(); - sink(stackArray); // no flow -} - int alwaysAssignSource(int *out) { *out = source(); return 0; diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected index bca0bfbca69..60410aa3c0a 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected @@ -1,4 +1,9 @@ | acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source | +| clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 | +| clang.cpp:29:27:29:28 | m1 | clang.cpp:28:27:28:32 | call to source | +| clang.cpp:30:27:30:34 | call to getFirst | clang.cpp:28:27:28:32 | call to source | +| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source | +| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source | | lambdas.cpp:14:3:14:6 | t | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:21:3:21:6 | t | lambdas.cpp:8:10:8:15 | call to source | @@ -19,42 +24,37 @@ | test.cpp:86:8:86:9 | i1 | test.cpp:83:7:83:8 | u2 | | test.cpp:90:8:90:14 | source1 | test.cpp:89:28:89:34 | source1 | | test.cpp:103:10:103:12 | ref | test.cpp:100:13:100:18 | call to source | -| test.cpp:126:8:126:19 | sourceArray1 | test.cpp:120:9:120:20 | sourceArray1 | -| test.cpp:137:27:137:28 | m1 | test.cpp:136:27:136:32 | call to source | -| test.cpp:138:27:138:34 | call to getFirst | test.cpp:136:27:136:32 | call to source | -| test.cpp:145:10:145:11 | m2 | test.cpp:142:32:142:37 | call to source | -| test.cpp:153:17:153:18 | m2 | test.cpp:151:35:151:40 | call to source | -| test.cpp:188:8:188:8 | y | test.cpp:186:27:186:32 | call to source | -| test.cpp:192:8:192:8 | s | test.cpp:199:33:199:38 | call to source | -| test.cpp:200:8:200:8 | y | test.cpp:199:33:199:38 | call to source | -| test.cpp:205:8:205:8 | x | test.cpp:212:34:212:39 | call to source | -| test.cpp:213:8:213:8 | y | test.cpp:212:34:212:39 | call to source | -| test.cpp:226:8:226:8 | y | test.cpp:219:11:219:16 | call to source | -| test.cpp:308:12:308:12 | x | test.cpp:293:14:293:19 | call to source | -| test.cpp:314:12:314:12 | x | test.cpp:313:22:313:27 | call to source | -| test.cpp:337:14:337:14 | x | test.cpp:353:17:353:22 | call to source | -| test.cpp:366:7:366:7 | x | test.cpp:362:4:362:9 | call to source | -| test.cpp:397:10:397:18 | globalVar | test.cpp:395:17:395:22 | call to source | -| test.cpp:413:10:413:14 | field | test.cpp:407:13:407:18 | call to source | -| test.cpp:417:10:417:14 | field | test.cpp:421:13:421:18 | call to source | -| test.cpp:423:10:423:14 | field | test.cpp:421:13:421:18 | call to source | -| test.cpp:433:8:433:10 | tmp | test.cpp:430:48:430:54 | source1 | -| test.cpp:440:8:440:10 | tmp | test.cpp:436:53:436:59 | source1 | -| test.cpp:442:10:442:12 | tmp | test.cpp:436:53:436:59 | source1 | -| test.cpp:449:8:449:10 | tmp | test.cpp:447:7:447:9 | tmp | -| test.cpp:456:8:456:10 | tmp | test.cpp:453:7:453:9 | tmp | -| test.cpp:466:8:466:12 | local | test.cpp:464:7:464:11 | local | -| test.cpp:466:8:466:12 | local | test.cpp:465:16:465:20 | ref arg local | -| test.cpp:472:8:472:12 | local | test.cpp:470:7:470:11 | local | -| test.cpp:472:8:472:12 | local | test.cpp:471:20:471:25 | ref arg & ... | -| test.cpp:478:8:478:12 | local | test.cpp:476:7:476:11 | local | -| test.cpp:478:8:478:12 | local | test.cpp:477:20:477:24 | ref arg local | -| test.cpp:485:8:485:12 | local | test.cpp:483:7:483:11 | local | -| test.cpp:485:8:485:12 | local | test.cpp:484:18:484:23 | ref arg & ... | -| test.cpp:491:8:491:12 | local | test.cpp:489:7:489:11 | local | -| test.cpp:491:8:491:12 | local | test.cpp:490:18:490:22 | ref arg local | -| test.cpp:498:9:498:22 | (statement expression) | test.cpp:497:26:497:32 | source1 | -| test.cpp:509:8:509:12 | local | test.cpp:497:26:497:32 | source1 | +| test.cpp:140:8:140:8 | y | test.cpp:138:27:138:32 | call to source | +| test.cpp:144:8:144:8 | s | test.cpp:151:33:151:38 | call to source | +| test.cpp:152:8:152:8 | y | test.cpp:151:33:151:38 | call to source | +| test.cpp:157:8:157:8 | x | test.cpp:164:34:164:39 | call to source | +| test.cpp:165:8:165:8 | y | test.cpp:164:34:164:39 | call to source | +| test.cpp:178:8:178:8 | y | test.cpp:171:11:171:16 | call to source | +| test.cpp:260:12:260:12 | x | test.cpp:245:14:245:19 | call to source | +| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source | +| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source | +| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source | +| test.cpp:349:10:349:18 | globalVar | test.cpp:347:17:347:22 | call to source | +| test.cpp:365:10:365:14 | field | test.cpp:359:13:359:18 | call to source | +| test.cpp:369:10:369:14 | field | test.cpp:373:13:373:18 | call to source | +| test.cpp:375:10:375:14 | field | test.cpp:373:13:373:18 | call to source | +| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 | +| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 | +| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 | +| test.cpp:401:8:401:10 | tmp | test.cpp:399:7:399:9 | tmp | +| test.cpp:408:8:408:10 | tmp | test.cpp:405:7:405:9 | tmp | +| test.cpp:418:8:418:12 | local | test.cpp:416:7:416:11 | local | +| test.cpp:418:8:418:12 | local | test.cpp:417:16:417:20 | ref arg local | +| test.cpp:424:8:424:12 | local | test.cpp:422:7:422:11 | local | +| test.cpp:424:8:424:12 | local | test.cpp:423:20:423:25 | ref arg & ... | +| test.cpp:430:8:430:12 | local | test.cpp:428:7:428:11 | local | +| test.cpp:430:8:430:12 | local | test.cpp:429:20:429:24 | ref arg local | +| test.cpp:437:8:437:12 | local | test.cpp:435:7:435:11 | local | +| test.cpp:437:8:437:12 | local | test.cpp:436:18:436:23 | ref arg & ... | +| test.cpp:443:8:443:12 | local | test.cpp:441:7:441:11 | local | +| test.cpp:443:8:443:12 | local | test.cpp:442:18:442:22 | ref arg local | +| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 | +| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 | | true_upon_entry.cpp:21:8:21:8 | x | true_upon_entry.cpp:17:11:17:16 | call to source | | true_upon_entry.cpp:29:8:29:8 | x | true_upon_entry.cpp:27:9:27:14 | call to source | | true_upon_entry.cpp:39:8:39:8 | x | true_upon_entry.cpp:33:11:33:16 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 1228f8f5816..b89b98f42d5 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -1,3 +1,6 @@ +| clang.cpp:28:27:28:32 | clang.cpp:29:27:29:28 | AST only | +| clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only | +| clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only | @@ -7,28 +10,25 @@ | test.cpp:89:28:89:34 | test.cpp:92:8:92:14 | IR only | | test.cpp:100:13:100:18 | test.cpp:103:10:103:12 | AST only | | test.cpp:109:9:109:14 | test.cpp:110:10:110:12 | IR only | -| test.cpp:136:27:136:32 | test.cpp:137:27:137:28 | AST only | -| test.cpp:136:27:136:32 | test.cpp:138:27:138:34 | AST only | -| test.cpp:147:42:147:47 | test.cpp:149:18:149:19 | IR only | -| test.cpp:395:17:395:22 | test.cpp:397:10:397:18 | AST only | -| test.cpp:407:13:407:18 | test.cpp:413:10:413:14 | AST only | -| test.cpp:421:13:421:18 | test.cpp:417:10:417:14 | AST only | -| test.cpp:421:13:421:18 | test.cpp:423:10:423:14 | AST only | -| test.cpp:430:48:430:54 | test.cpp:433:8:433:10 | AST only | -| test.cpp:436:53:436:59 | test.cpp:440:8:440:10 | AST only | -| test.cpp:436:53:436:59 | test.cpp:442:10:442:12 | AST only | -| test.cpp:447:7:447:9 | test.cpp:449:8:449:10 | AST only | -| test.cpp:453:7:453:9 | test.cpp:456:8:456:10 | AST only | -| test.cpp:464:7:464:11 | test.cpp:466:8:466:12 | AST only | -| test.cpp:465:16:465:20 | test.cpp:466:8:466:12 | AST only | -| test.cpp:470:7:470:11 | test.cpp:472:8:472:12 | AST only | -| test.cpp:471:20:471:25 | test.cpp:472:8:472:12 | AST only | -| test.cpp:476:7:476:11 | test.cpp:478:8:478:12 | AST only | -| test.cpp:477:20:477:24 | test.cpp:478:8:478:12 | AST only | -| test.cpp:483:7:483:11 | test.cpp:485:8:485:12 | AST only | -| test.cpp:484:18:484:23 | test.cpp:485:8:485:12 | AST only | -| test.cpp:489:7:489:11 | test.cpp:491:8:491:12 | AST only | -| test.cpp:490:18:490:22 | test.cpp:491:8:491:12 | AST only | +| test.cpp:347:17:347:22 | test.cpp:349:10:349:18 | AST only | +| test.cpp:359:13:359:18 | test.cpp:365:10:365:14 | AST only | +| test.cpp:373:13:373:18 | test.cpp:369:10:369:14 | AST only | +| test.cpp:373:13:373:18 | test.cpp:375:10:375:14 | AST only | +| test.cpp:382:48:382:54 | test.cpp:385:8:385:10 | AST only | +| test.cpp:388:53:388:59 | test.cpp:392:8:392:10 | AST only | +| test.cpp:388:53:388:59 | test.cpp:394:10:394:12 | AST only | +| test.cpp:399:7:399:9 | test.cpp:401:8:401:10 | AST only | +| test.cpp:405:7:405:9 | test.cpp:408:8:408:10 | AST only | +| test.cpp:416:7:416:11 | test.cpp:418:8:418:12 | AST only | +| test.cpp:417:16:417:20 | test.cpp:418:8:418:12 | AST only | +| test.cpp:422:7:422:11 | test.cpp:424:8:424:12 | AST only | +| test.cpp:423:20:423:25 | test.cpp:424:8:424:12 | AST only | +| test.cpp:428:7:428:11 | test.cpp:430:8:430:12 | AST only | +| test.cpp:429:20:429:24 | test.cpp:430:8:430:12 | AST only | +| test.cpp:435:7:435:11 | test.cpp:437:8:437:12 | AST only | +| test.cpp:436:18:436:23 | test.cpp:437:8:437:12 | AST only | +| test.cpp:441:7:441:11 | test.cpp:443:8:443:12 | AST only | +| test.cpp:442:18:442:22 | test.cpp:443:8:443:12 | AST only | | true_upon_entry.cpp:9:11:9:16 | true_upon_entry.cpp:13:8:13:8 | IR only | | true_upon_entry.cpp:62:11:62:16 | true_upon_entry.cpp:66:8:66:8 | IR only | | true_upon_entry.cpp:98:11:98:16 | true_upon_entry.cpp:105:8:105:8 | IR only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index ad242a435a0..83ba546480f 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -1,5 +1,10 @@ | acrossLinkTargets.cpp:12:8:12:8 | Convert: (int)... | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source | | acrossLinkTargets.cpp:12:8:12:8 | Load: x | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source | +| clang.cpp:18:8:18:19 | Convert: (const int *)... | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 | +| clang.cpp:18:8:18:19 | Load: sourceArray1 | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 | +| clang.cpp:37:10:37:11 | Load: m2 | clang.cpp:34:32:34:37 | Call: call to source | +| clang.cpp:41:18:41:19 | Load: m2 | clang.cpp:39:42:39:47 | Call: call to source | +| clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source | | test.cpp:7:8:7:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | | test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | | test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source | @@ -15,23 +20,18 @@ | test.cpp:90:8:90:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 | | test.cpp:92:8:92:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 | | test.cpp:110:10:110:12 | Load: (reference dereference) | test.cpp:109:9:109:14 | Call: call to source | -| test.cpp:126:8:126:19 | Convert: (const int *)... | test.cpp:120:9:120:20 | InitializeParameter: sourceArray1 | -| test.cpp:126:8:126:19 | Load: sourceArray1 | test.cpp:120:9:120:20 | InitializeParameter: sourceArray1 | -| test.cpp:145:10:145:11 | Load: m2 | test.cpp:142:32:142:37 | Call: call to source | -| test.cpp:149:18:149:19 | Load: m2 | test.cpp:147:42:147:47 | Call: call to source | -| test.cpp:153:17:153:18 | Load: m2 | test.cpp:151:35:151:40 | Call: call to source | -| test.cpp:188:8:188:8 | Load: y | test.cpp:186:27:186:32 | Call: call to source | -| test.cpp:192:8:192:8 | Load: s | test.cpp:199:33:199:38 | Call: call to source | -| test.cpp:200:8:200:8 | Load: y | test.cpp:199:33:199:38 | Call: call to source | -| test.cpp:205:8:205:8 | Load: x | test.cpp:212:34:212:39 | Call: call to source | -| test.cpp:213:8:213:8 | Load: y | test.cpp:212:34:212:39 | Call: call to source | -| test.cpp:226:8:226:8 | Load: y | test.cpp:219:11:219:16 | Call: call to source | -| test.cpp:308:12:308:12 | Load: x | test.cpp:293:14:293:19 | Call: call to source | -| test.cpp:314:12:314:12 | Load: x | test.cpp:313:22:313:27 | Call: call to source | -| test.cpp:337:14:337:14 | Load: x | test.cpp:353:17:353:22 | Call: call to source | -| test.cpp:366:7:366:7 | Load: x | test.cpp:362:4:362:9 | Call: call to source | -| test.cpp:498:9:498:22 | CopyValue: (statement expression) | test.cpp:497:26:497:32 | InitializeParameter: source1 | -| test.cpp:509:8:509:12 | Load: local | test.cpp:497:26:497:32 | InitializeParameter: source1 | +| test.cpp:140:8:140:8 | Load: y | test.cpp:138:27:138:32 | Call: call to source | +| test.cpp:144:8:144:8 | Load: s | test.cpp:151:33:151:38 | Call: call to source | +| test.cpp:152:8:152:8 | Load: y | test.cpp:151:33:151:38 | Call: call to source | +| test.cpp:157:8:157:8 | Load: x | test.cpp:164:34:164:39 | Call: call to source | +| test.cpp:165:8:165:8 | Load: y | test.cpp:164:34:164:39 | Call: call to source | +| test.cpp:178:8:178:8 | Load: y | test.cpp:171:11:171:16 | Call: call to source | +| test.cpp:260:12:260:12 | Load: x | test.cpp:245:14:245:19 | Call: call to source | +| test.cpp:266:12:266:12 | Load: x | test.cpp:265:22:265:27 | Call: call to source | +| test.cpp:289:14:289:14 | Load: x | test.cpp:305:17:305:22 | Call: call to source | +| test.cpp:318:7:318:7 | Load: x | test.cpp:314:4:314:9 | Call: call to source | +| test.cpp:450:9:450:22 | CopyValue: (statement expression) | test.cpp:449:26:449:32 | InitializeParameter: source1 | +| test.cpp:461:8:461:12 | Load: local | test.cpp:449:26:449:32 | InitializeParameter: source1 | | true_upon_entry.cpp:13:8:13:8 | Load: x | true_upon_entry.cpp:9:11:9:16 | Call: call to source | | true_upon_entry.cpp:21:8:21:8 | Load: x | true_upon_entry.cpp:17:11:17:16 | Call: call to source | | true_upon_entry.cpp:29:8:29:8 | Load: x | true_upon_entry.cpp:27:9:27:14 | Call: call to source | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/uninitialized.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/uninitialized.expected index 6cfc73519dd..9cffdb99e60 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/uninitialized.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/uninitialized.expected @@ -1,20 +1,20 @@ | test.cpp:75:7:75:8 | u1 | test.cpp:76:8:76:9 | u1 | | test.cpp:83:7:83:8 | u2 | test.cpp:84:13:84:14 | u2 | | test.cpp:83:7:83:8 | u2 | test.cpp:85:8:85:9 | u2 | -| test.cpp:447:7:447:9 | tmp | test.cpp:448:11:448:13 | tmp | -| test.cpp:447:7:447:9 | tmp | test.cpp:449:8:449:10 | tmp | -| test.cpp:453:7:453:9 | tmp | test.cpp:454:19:454:21 | tmp | -| test.cpp:453:7:453:9 | tmp | test.cpp:455:11:455:13 | tmp | -| test.cpp:453:7:453:9 | tmp | test.cpp:456:8:456:10 | tmp | -| test.cpp:464:7:464:11 | local | test.cpp:465:16:465:20 | local | -| test.cpp:464:7:464:11 | local | test.cpp:466:8:466:12 | local | -| test.cpp:470:7:470:11 | local | test.cpp:471:21:471:25 | local | -| test.cpp:470:7:470:11 | local | test.cpp:472:8:472:12 | local | -| test.cpp:476:7:476:11 | local | test.cpp:477:20:477:24 | local | -| test.cpp:476:7:476:11 | local | test.cpp:478:8:478:12 | local | -| test.cpp:476:7:476:11 | local | test.cpp:479:9:479:13 | local | -| test.cpp:483:7:483:11 | local | test.cpp:484:19:484:23 | local | -| test.cpp:483:7:483:11 | local | test.cpp:485:8:485:12 | local | -| test.cpp:489:7:489:11 | local | test.cpp:490:18:490:22 | local | -| test.cpp:489:7:489:11 | local | test.cpp:491:8:491:12 | local | -| test.cpp:489:7:489:11 | local | test.cpp:492:9:492:13 | local | +| test.cpp:399:7:399:9 | tmp | test.cpp:400:11:400:13 | tmp | +| test.cpp:399:7:399:9 | tmp | test.cpp:401:8:401:10 | tmp | +| test.cpp:405:7:405:9 | tmp | test.cpp:406:19:406:21 | tmp | +| test.cpp:405:7:405:9 | tmp | test.cpp:407:11:407:13 | tmp | +| test.cpp:405:7:405:9 | tmp | test.cpp:408:8:408:10 | tmp | +| test.cpp:416:7:416:11 | local | test.cpp:417:16:417:20 | local | +| test.cpp:416:7:416:11 | local | test.cpp:418:8:418:12 | local | +| test.cpp:422:7:422:11 | local | test.cpp:423:21:423:25 | local | +| test.cpp:422:7:422:11 | local | test.cpp:424:8:424:12 | local | +| test.cpp:428:7:428:11 | local | test.cpp:429:20:429:24 | local | +| test.cpp:428:7:428:11 | local | test.cpp:430:8:430:12 | local | +| test.cpp:428:7:428:11 | local | test.cpp:431:9:431:13 | local | +| test.cpp:435:7:435:11 | local | test.cpp:436:19:436:23 | local | +| test.cpp:435:7:435:11 | local | test.cpp:437:8:437:12 | local | +| test.cpp:441:7:441:11 | local | test.cpp:442:18:442:22 | local | +| test.cpp:441:7:441:11 | local | test.cpp:443:8:443:12 | local | +| test.cpp:441:7:441:11 | local | test.cpp:444:9:444:13 | local | diff --git a/cpp/ql/test/library-tests/dataflow/fields/A.cpp b/cpp/ql/test/library-tests/dataflow/fields/A.cpp index 7668db1fbbc..fd49e1e85ee 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/A.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/A.cpp @@ -129,7 +129,7 @@ public: { B *b = new B(); f7(b); - sink(b->c); // flow [NOT DETECTED] + sink(b->c); // flow } class D @@ -151,7 +151,7 @@ public: D *d = new D(b, r()); sink(d->b); // flow x2 sink(d->b->c); // flow - sink(b->c); // flow [NOT DETECTED] + sink(b->c); // flow } void f10() diff --git a/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp b/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp index cdcade3f39d..8a5dcc0e509 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp @@ -61,3 +61,34 @@ void assignBeforeCopy() { S copy2 = s2; sink(copy2.m1); // flow } + +struct Wrapper { + S s; +}; + +void copyIntermediate() { + Wrapper w = { { 0, 0 } }; + S s = w.s; + s.m1 = user_input(); + sink(w.s.m1); // no flow +} + +void pointerIntermediate() { + Wrapper w = { { 0, 0 } }; + S *s = &w.s; + s->m1 = user_input(); + sink(w.s.m1); // flow [FALSE NEGATIVE] +} + +void referenceIntermediate() { + Wrapper w = { { 0, 0 } }; + S &s = w.s; + s.m1 = user_input(); + sink(w.s.m1); // flow [FALSE NEGATIVE] +} + +void nestedAssign() { + Wrapper w = { { 0, 0 } }; + w.s.m1 = user_input(); + sink(w.s.m1); // flow +} diff --git a/cpp/ql/test/library-tests/dataflow/fields/complex.cpp b/cpp/ql/test/library-tests/dataflow/fields/complex.cpp index 5a6c67fa8df..31ed50283be 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/complex.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/complex.cpp @@ -33,8 +33,16 @@ void sink(int x) void bar(Bar &b) { - sink(b.f.a()); // flow (through `b1.f.setA` and `b3.f.setA`) [NOT DETECTED] - sink(b.f.b()); // flow (through `b2.f.setB` and `b3.f.setB`) [NOT DETECTED] + // The library correctly finds that the four `user_input` sources can make it + // to the `sink` calls, but it also finds some source/sink combinations that + // are impossible. Those false positives here are a consequence of how the + // shared data flow library overapproximates field flow. The library only + // tracks the head (`f`) and the length (2) of the field access path, and + // then it tracks that both `a_` and `b_` have followed `f` in _some_ access + // path somewhere in the search. That makes the library conclude that there + // could be flow to `b.f.a_` even when the flow was actually to `b.f.b_`. + sink(b.f.a()); // flow [FALSE POSITIVE through `b2.f.setB` and `b3.f.setB`] + sink(b.f.b()); // flow [FALSE POSITIVE through `b1.f.setA` and `b3.f.setA`] } void foo() diff --git a/cpp/ql/test/library-tests/dataflow/fields/flow.expected b/cpp/ql/test/library-tests/dataflow/fields/flow.expected index 38aa90f8731..fadc2f15bb5 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/flow.expected @@ -24,7 +24,12 @@ edges | A.cpp:103:14:103:14 | c [a] | A.cpp:120:12:120:13 | c1 [a] | | A.cpp:107:12:107:13 | c1 [a] | A.cpp:107:16:107:16 | a | | A.cpp:120:12:120:13 | c1 [a] | A.cpp:120:16:120:16 | a | +| A.cpp:126:5:126:5 | b [post update] [c] | A.cpp:131:8:131:8 | ref arg b [c] | +| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | b [post update] [c] | +| A.cpp:131:8:131:8 | ref arg b [c] | A.cpp:132:10:132:10 | b [c] | +| A.cpp:132:10:132:10 | b [c] | A.cpp:132:13:132:13 | c | | A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:143:7:143:31 | ... = ... [c] | +| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:151:18:151:18 | ref arg b [c] | | A.cpp:142:7:142:20 | ... = ... | A.cpp:142:7:142:7 | b [post update] [c] | | A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | ... = ... | | A.cpp:143:7:143:10 | this [post update] [b, c] | A.cpp:151:12:151:24 | call to D [b, c] | @@ -36,9 +41,11 @@ edges | A.cpp:151:12:151:24 | call to D [b, c] | A.cpp:153:10:153:10 | d [b, c] | | A.cpp:151:12:151:24 | call to D [b] | A.cpp:152:10:152:10 | d [b] | | A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | call to D [b] | +| A.cpp:151:18:151:18 | ref arg b [c] | A.cpp:154:10:154:10 | b [c] | | A.cpp:152:10:152:10 | d [b] | A.cpp:152:13:152:13 | b | | A.cpp:153:10:153:10 | d [b, c] | A.cpp:153:13:153:13 | b [c] | | A.cpp:153:13:153:13 | b [c] | A.cpp:153:16:153:16 | c | +| A.cpp:154:10:154:10 | b [c] | A.cpp:154:13:154:13 | c | | A.cpp:159:12:159:18 | new | A.cpp:160:29:160:29 | b | | A.cpp:160:18:160:60 | call to MyList [head] | A.cpp:161:38:161:39 | l1 [head] | | A.cpp:160:29:160:29 | b | A.cpp:160:18:160:60 | call to MyList [head] | @@ -96,6 +103,34 @@ edges | aliasing.cpp:60:3:60:22 | ... = ... | aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | ... = ... | | aliasing.cpp:62:8:62:12 | copy2 [m1] | aliasing.cpp:62:14:62:15 | m1 | +| aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | aliasing.cpp:93:8:93:8 | w [s, m1] | +| aliasing.cpp:92:3:92:23 | ... = ... | aliasing.cpp:92:5:92:5 | s [post update] [m1] | +| aliasing.cpp:92:5:92:5 | s [post update] [m1] | aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | +| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:92:3:92:23 | ... = ... | +| aliasing.cpp:93:8:93:8 | w [s, m1] | aliasing.cpp:93:10:93:10 | s [m1] | +| aliasing.cpp:93:10:93:10 | s [m1] | aliasing.cpp:93:12:93:13 | m1 | +| complex.cpp:34:15:34:15 | b [f, a_] | complex.cpp:44:8:44:8 | b [f, a_] | +| complex.cpp:34:15:34:15 | b [f, b_] | complex.cpp:45:8:45:8 | b [f, b_] | +| complex.cpp:44:8:44:8 | b [f, a_] | complex.cpp:44:10:44:10 | f [a_] | +| complex.cpp:44:10:44:10 | f [a_] | complex.cpp:44:12:44:12 | call to a | +| complex.cpp:45:8:45:8 | b [f, b_] | complex.cpp:45:10:45:10 | f [b_] | +| complex.cpp:45:10:45:10 | f [b_] | complex.cpp:45:12:45:12 | call to b | +| complex.cpp:55:3:55:4 | b1 [post update] [f, a_] | complex.cpp:61:7:61:8 | b1 [f, a_] | +| complex.cpp:55:6:55:6 | f [post update] [a_] | complex.cpp:55:3:55:4 | b1 [post update] [f, a_] | +| complex.cpp:55:13:55:22 | call to user_input | complex.cpp:55:6:55:6 | f [post update] [a_] | +| complex.cpp:56:3:56:4 | b2 [post update] [f, b_] | complex.cpp:64:7:64:8 | b2 [f, b_] | +| complex.cpp:56:6:56:6 | f [post update] [b_] | complex.cpp:56:3:56:4 | b2 [post update] [f, b_] | +| complex.cpp:56:13:56:22 | call to user_input | complex.cpp:56:6:56:6 | f [post update] [b_] | +| complex.cpp:57:3:57:4 | b3 [post update] [f, a_] | complex.cpp:67:7:67:8 | b3 [f, a_] | +| complex.cpp:57:6:57:6 | f [post update] [a_] | complex.cpp:57:3:57:4 | b3 [post update] [f, a_] | +| complex.cpp:57:13:57:22 | call to user_input | complex.cpp:57:6:57:6 | f [post update] [a_] | +| complex.cpp:58:3:58:4 | b3 [post update] [f, b_] | complex.cpp:67:7:67:8 | b3 [f, b_] | +| complex.cpp:58:6:58:6 | f [post update] [b_] | complex.cpp:58:3:58:4 | b3 [post update] [f, b_] | +| complex.cpp:58:13:58:22 | call to user_input | complex.cpp:58:6:58:6 | f [post update] [b_] | +| complex.cpp:61:7:61:8 | b1 [f, a_] | complex.cpp:34:15:34:15 | b [f, a_] | +| complex.cpp:64:7:64:8 | b2 [f, b_] | complex.cpp:34:15:34:15 | b [f, b_] | +| complex.cpp:67:7:67:8 | b3 [f, a_] | complex.cpp:34:15:34:15 | b [f, a_] | +| complex.cpp:67:7:67:8 | b3 [f, b_] | complex.cpp:34:15:34:15 | b [f, b_] | | constructors.cpp:26:15:26:15 | f [a_] | constructors.cpp:28:10:28:10 | f [a_] | | constructors.cpp:26:15:26:15 | f [b_] | constructors.cpp:29:10:29:10 | f [b_] | | constructors.cpp:28:10:28:10 | f [a_] | constructors.cpp:28:12:28:12 | call to a | @@ -145,9 +180,11 @@ edges | A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new | | A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new | | A.cpp:120:16:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:16:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new | +| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new | | A.cpp:152:13:152:13 | b | A.cpp:143:25:143:31 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new | new | | A.cpp:152:13:152:13 | b | A.cpp:150:12:150:18 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new | new | | A.cpp:153:16:153:16 | c | A.cpp:142:14:142:20 | new | A.cpp:153:16:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new | +| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new | | A.cpp:165:26:165:29 | head | A.cpp:159:12:159:18 | new | A.cpp:165:26:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new | | A.cpp:169:15:169:18 | head | A.cpp:159:12:159:18 | new | A.cpp:169:15:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new | | B.cpp:9:20:9:24 | elem1 | B.cpp:6:15:6:24 | new | B.cpp:9:20:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new | new | @@ -157,6 +194,11 @@ edges | aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input | | aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input | | aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input | +| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input | +| complex.cpp:44:12:44:12 | call to a | complex.cpp:55:13:55:22 | call to user_input | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:55:13:55:22 | call to user_input | call to user_input | +| complex.cpp:44:12:44:12 | call to a | complex.cpp:57:13:57:22 | call to user_input | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:57:13:57:22 | call to user_input | call to user_input | +| complex.cpp:45:12:45:12 | call to b | complex.cpp:56:13:56:22 | call to user_input | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:56:13:56:22 | call to user_input | call to user_input | +| complex.cpp:45:12:45:12 | call to b | complex.cpp:58:13:58:22 | call to user_input | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:58:13:58:22 | call to user_input | call to user_input | | constructors.cpp:28:12:28:12 | call to a | constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:34:11:34:20 | call to user_input | call to user_input | | constructors.cpp:28:12:28:12 | call to a | constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:36:11:36:20 | call to user_input | call to user_input | | constructors.cpp:29:12:29:12 | call to b | constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:35:14:35:23 | call to user_input | call to user_input | diff --git a/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.cpp b/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.cpp new file mode 100644 index 00000000000..4ee706a1902 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.cpp @@ -0,0 +1,16 @@ + +struct MyStruct +{ + int x; + struct MySubStruct { + int z; + } y; +}; + +void test() +{ + MyStruct s; + + s.x = 1; + s.y.z = 1; +} diff --git a/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.expected b/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.expected new file mode 100644 index 00000000000..2ad9e47f1b1 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.expected @@ -0,0 +1,3 @@ +| partialdefinitions.cpp:14:2:14:2 | partial def of s | partialdefinitions.cpp:14:2:14:2 | s | partialdefinitions.cpp:14:2:14:8 | ... = ... | +| partialdefinitions.cpp:15:2:15:2 | partial def of s | partialdefinitions.cpp:15:2:15:2 | s | partialdefinitions.cpp:15:2:15:10 | ... = ... | +| partialdefinitions.cpp:15:4:15:4 | partial def of y | partialdefinitions.cpp:15:4:15:4 | y | partialdefinitions.cpp:15:2:15:10 | ... = ... | diff --git a/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.ql b/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.ql new file mode 100644 index 00000000000..db34eb16cb8 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/partialdefinitions/partialdefinitions.ql @@ -0,0 +1,4 @@ +import semmle.code.cpp.dataflow.internal.FlowVar + +from PartialDefinition def +select def, def.getDefinedExpr(), def.getSubBasicBlockStart() diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index ab23866fe0e..4895cf71112 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -133,6 +133,7 @@ | taint.cpp:165:22:165:25 | {...} | taint.cpp:172:10:172:15 | buffer | | | taint.cpp:165:22:165:25 | {...} | taint.cpp:173:8:173:13 | buffer | | | taint.cpp:165:24:165:24 | 0 | taint.cpp:165:22:165:25 | {...} | TAINT | +| taint.cpp:168:8:168:14 | ref arg tainted | taint.cpp:172:18:172:24 | tainted | | | taint.cpp:170:10:170:15 | buffer | taint.cpp:170:3:170:8 | call to strcpy | | | taint.cpp:170:10:170:15 | ref arg buffer | taint.cpp:170:3:170:8 | call to strcpy | | | taint.cpp:170:10:170:15 | ref arg buffer | taint.cpp:171:8:171:13 | buffer | | @@ -188,11 +189,11 @@ | taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field t | TAINT | | taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field u | TAINT | | taint.cpp:228:11:228:11 | `this` parameter in (constructor) | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | | -| taint.cpp:228:11:228:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | | +| taint.cpp:228:11:228:11 | constructor init of field t [post-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | | +| taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | | | taint.cpp:228:11:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | | | taint.cpp:228:11:232:2 | {...} | taint.cpp:228:11:232:2 | [...](...){...} | | | taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | | -| taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | | | taint.cpp:229:3:229:6 | this | taint.cpp:230:3:230:6 | this | | | taint.cpp:230:3:230:6 | this | taint.cpp:231:3:231:11 | this | | | taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field t | TAINT | @@ -211,11 +212,11 @@ | taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | | | taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT | | taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT | -| taint.cpp:243:11:243:11 | `this` parameter in (constructor) | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | | | taint.cpp:243:11:243:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | | +| taint.cpp:243:11:243:11 | constructor init of field t [post-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | | +| taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | | | taint.cpp:243:11:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | | | taint.cpp:243:11:246:2 | {...} | taint.cpp:243:11:246:2 | [...](...){...} | | -| taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | | | taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | | | taint.cpp:244:3:244:6 | this | taint.cpp:245:3:245:6 | this | | | taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactDate.cpp b/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/ConstructorOrMethodWithExactDate.cpp similarity index 89% rename from cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactDate.cpp rename to cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/ConstructorOrMethodWithExactDate.cpp index a1eef2e3b90..2720aa8f403 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactDate.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/ConstructorOrMethodWithExactDate.cpp @@ -37,4 +37,7 @@ int Main() // GOOD: method call with the same parameters in a different order (we only track year, month, day) EraInfo * pDateTimeUtil4 = EraInfo::EraInfoFromDate(1, 2, 8, 1, 1989, L"\u5e73\u6210"); + + // BAD: constructor creating a EraInfo with exact Reiwa era start date + EraInfo * pDateTimeUtil5 = new EraInfo(2019, 5, 1); } \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/JapaneseEraDate.expected b/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/JapaneseEraDate.expected new file mode 100644 index 00000000000..58ac64cc308 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/JapaneseEraDate.expected @@ -0,0 +1,7 @@ +| ConstructorOrMethodWithExactDate.cpp:27:31:27:53 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. | +| ConstructorOrMethodWithExactDate.cpp:30:32:30:77 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. | +| ConstructorOrMethodWithExactDate.cpp:36:32:36:55 | call to EraInfoFromDate | Call that appears to have hard-coded Japanese era start date as parameter. | +| ConstructorOrMethodWithExactDate.cpp:42:32:42:54 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. | +| StructWithExactDate.cpp:31:13:31:19 | tm_year | A time struct that is initialized with exact Japanese calendar era start date. | +| StructWithExactDate.cpp:46:8:46:12 | wYear | A time struct that is initialized with exact Japanese calendar era start date. | +| StructWithExactDate.cpp:60:9:60:13 | wYear | A time struct that is initialized with exact Japanese calendar era start date. | diff --git a/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/JapaneseEraDate.qlref b/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/JapaneseEraDate.qlref new file mode 100644 index 00000000000..4240387a36c --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/JapaneseEraDate.qlref @@ -0,0 +1 @@ +Best Practices/Magic Constants/JapaneseEraDate.ql diff --git a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactDate.cpp b/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/StructWithExactDate.cpp similarity index 89% rename from cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactDate.cpp rename to cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/StructWithExactDate.cpp index 9c2b9eb0640..7bbf3397ff9 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactDate.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Magic Constants/Japanese Era/StructWithExactDate.cpp @@ -52,6 +52,13 @@ int main() st1.wMonth = 1; st1.wYear = 1990; + + // BAD: Creation of SYSTEMTIME stuct corresponding to the beginning of Reiwa era + SYSTEMTIME st2; + st2.wDay = 1; + st2.wMonth = 5; + st2.wYear = 2019; + return 0; } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactEraDate.expected b/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactEraDate.expected deleted file mode 100644 index 9b6c731ebd4..00000000000 --- a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactEraDate.expected +++ /dev/null @@ -1,3 +0,0 @@ -| ConstructorOrMethodWithExactDate.cpp:27:31:27:53 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. | -| ConstructorOrMethodWithExactDate.cpp:30:32:30:77 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. | -| ConstructorOrMethodWithExactDate.cpp:36:32:36:55 | call to EraInfoFromDate | Call that appears to have hard-coded Japanese era start date as parameter. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactEraDate.qlref b/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactEraDate.qlref deleted file mode 100644 index 2e5a8969872..00000000000 --- a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/ConstructorOrMethodWithExactEraDate.qlref +++ /dev/null @@ -1 +0,0 @@ -Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql diff --git a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactEraDate.expected b/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactEraDate.expected deleted file mode 100644 index c31c9cc4d7a..00000000000 --- a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactEraDate.expected +++ /dev/null @@ -1,2 +0,0 @@ -| StructWithExactDate.cpp:31:13:31:19 | tm_year | A time struct that is initialized with exact Japanese calendar era start date. | -| StructWithExactDate.cpp:46:8:46:12 | wYear | A time struct that is initialized with exact Japanese calendar era start date. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactEraDate.qlref b/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactEraDate.qlref deleted file mode 100644 index 443b15e6da3..00000000000 --- a/cpp/ql/test/query-tests/Likely Bugs/Japanese Era/StructWithExactEraDate.qlref +++ /dev/null @@ -1 +0,0 @@ -Likely Bugs/JapaneseEra/StructWithExactEraDate.ql diff --git a/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/old.dbscheme b/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/old.dbscheme new file mode 100644 index 00000000000..81a312e6daf --- /dev/null +++ b/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/old.dbscheme @@ -0,0 +1,1904 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + 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 + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#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 + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_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 +); + +/** + * 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 data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +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 +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: 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 +); + +/* + 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 +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + + + +fun_decls( + unique int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +var_decls( + unique int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +membervariables( + unique int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +globalvariables( + unique int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + unique int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; +successors( + int from: @cfgnode ref, + int to: @cfgnode ref +); + +truecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +falsecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* 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; diff --git a/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/semmlecode.cpp.dbscheme b/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/semmlecode.cpp.dbscheme new file mode 100644 index 00000000000..c4c27a2661b --- /dev/null +++ b/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/semmlecode.cpp.dbscheme @@ -0,0 +1,1909 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + 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 + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#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 + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_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 +); + +/** + * 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 data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +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 +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: 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 +); + +/* + 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 +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + + + +fun_decls( + unique int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +var_decls( + unique int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +membervariables( + unique int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +globalvariables( + unique int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + unique int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; +successors( + int from: @cfgnode ref, + int to: @cfgnode ref +); + +truecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +falsecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* 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; diff --git a/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/upgrade.properties b/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/upgrade.properties new file mode 100644 index 00000000000..e07968876ca --- /dev/null +++ b/cpp/upgrades/81a312e6dafdffb650e1c7e3dc02cc37505e2505/upgrade.properties @@ -0,0 +1,3 @@ +description: Add name mangling table +compatibility: partial + diff --git a/csharp/ql/src/Language Abuse/UselessUpcast.ql b/csharp/ql/src/Language Abuse/UselessUpcast.ql index df2775494b7..932f14d09c6 100644 --- a/csharp/ql/src/Language Abuse/UselessUpcast.ql +++ b/csharp/ql/src/Language Abuse/UselessUpcast.ql @@ -75,7 +75,6 @@ private class ConstructorCall extends Call { /** An explicit upcast. */ class ExplicitUpcast extends ExplicitCast { ValueOrRefType src; - ValueOrRefType dest; ExplicitUpcast() { diff --git a/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql b/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql index ba7a9d55754..6c0d4e1a708 100644 --- a/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql +++ b/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql @@ -19,7 +19,6 @@ import semmle.code.csharp.commons.ComparisonTest /** A comparison of an index variable with the length of an array. */ class IndexGuard extends ComparisonTest { VariableAccess indexAccess; - Variable array; IndexGuard() { diff --git a/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql b/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql index c098cfc8d64..caa36fe89d2 100644 --- a/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql +++ b/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql @@ -30,11 +30,8 @@ class NestedForConditions extends SC::StructuralComparisonConfiguration { /** A nested `for` statement that shares the same iteration variable as an outer `for` statement. */ class NestedForLoopSameVariable extends ForStmt { ForStmt outer; - Variable iteration; - MutatorOperation innerUpdate; - MutatorOperation outerUpdate; NestedForLoopSameVariable() { diff --git a/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll b/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll index 30ff5a8d9a2..a2c6d482c1c 100644 --- a/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll +++ b/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll @@ -6,7 +6,6 @@ import csharp */ class Package extends XMLElement { string name; - Version version; Package() { diff --git a/csharp/ql/src/semmle/code/cil/CallableReturns.qll b/csharp/ql/src/semmle/code/cil/CallableReturns.qll index 1efef31e03c..ee60713b801 100644 --- a/csharp/ql/src/semmle/code/cil/CallableReturns.qll +++ b/csharp/ql/src/semmle/code/cil/CallableReturns.qll @@ -28,6 +28,7 @@ private module Cached { forex(Throw ex | ex = m.getImplementation().getAnInstruction() | t = ex.getExpr().getType()) } } + import Cached pragma[noinline] diff --git a/csharp/ql/src/semmle/code/cil/DataFlow.qll b/csharp/ql/src/semmle/code/cil/DataFlow.qll index d5e7f6139e0..a01ecab5e3b 100644 --- a/csharp/ql/src/semmle/code/cil/DataFlow.qll +++ b/csharp/ql/src/semmle/code/cil/DataFlow.qll @@ -204,6 +204,7 @@ module DefUse { exists(VariableUpdate vu | def = vu.getSource() | variableUpdateUse(target, vu, use)) } } + private import DefUse abstract library class VariableUpdate extends Instruction { diff --git a/csharp/ql/src/semmle/code/cil/Method.qll b/csharp/ql/src/semmle/code/cil/Method.qll index 455459e9918..40aeb78b173 100644 --- a/csharp/ql/src/semmle/code/cil/Method.qll +++ b/csharp/ql/src/semmle/code/cil/Method.qll @@ -85,9 +85,7 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN override Location getLocation() { result = Element.super.getLocation() } - override Location getALocation() { - cil_method_location(this.getSourceDeclaration(), result) - } + override Location getALocation() { cil_method_location(this.getSourceDeclaration(), result) } override Parameter getRawParameter(int n) { cil_parameter(result, this, n, _) } diff --git a/csharp/ql/src/semmle/code/cil/Stubs.qll b/csharp/ql/src/semmle/code/cil/Stubs.qll index dc3d47654eb..d2a0fe736a0 100644 --- a/csharp/ql/src/semmle/code/cil/Stubs.qll +++ b/csharp/ql/src/semmle/code/cil/Stubs.qll @@ -40,6 +40,7 @@ private module Cached { exists(mi.getAnInstruction()) } } + private import Cached predicate assemblyIsStub = assemblyIsStubImpl/1; diff --git a/csharp/ql/src/semmle/code/cil/Type.qll b/csharp/ql/src/semmle/code/cil/Type.qll index 635c097e588..9d6cbecf1ef 100644 --- a/csharp/ql/src/semmle/code/cil/Type.qll +++ b/csharp/ql/src/semmle/code/cil/Type.qll @@ -57,9 +57,7 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { qualifier = this.getParent().getQualifiedName() } - override Location getALocation() { - cil_type_location(this.getSourceDeclaration(), result) - } + override Location getALocation() { cil_type_location(this.getSourceDeclaration(), result) } /** Holds if this type is a class. */ predicate isClass() { cil_class(this) } diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index faa6b04dd55..14a88830ad2 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -175,7 +175,6 @@ private newtype TAnnotatedType = /** A type with additional information. */ class AnnotatedType extends TAnnotatedType { Type type; - Annotations::TypeAnnotations annotations; AnnotatedType() { this = TAnnotatedTypeNullability(type, annotations) } diff --git a/csharp/ql/src/semmle/code/csharp/Assignable.qll b/csharp/ql/src/semmle/code/csharp/Assignable.qll index 7297275c7f6..63667018f1e 100644 --- a/csharp/ql/src/semmle/code/csharp/Assignable.qll +++ b/csharp/ql/src/semmle/code/csharp/Assignable.qll @@ -154,7 +154,6 @@ class AssignableWrite extends AssignableAccess { */ private class RefArg extends AssignableAccess { private Expr call; - private int position; RefArg() { @@ -379,8 +378,10 @@ module AssignableInternal { ) } } + import Cached } + private import AssignableInternal /** @@ -526,7 +527,6 @@ module AssignableDefinitions { */ class TupleAssignmentDefinition extends AssignableDefinition, TTupleAssignmentDefinition { AssignExpr ae; - Expr leaf; TupleAssignmentDefinition() { this = TTupleAssignmentDefinition(ae, leaf) } diff --git a/csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll b/csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll index d31623bd283..a18df55226e 100644 --- a/csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll +++ b/csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll @@ -372,4 +372,5 @@ private module Cached { ) } } + import Cached diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index 98f9e6db361..bdd28d8a0af 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -949,7 +949,6 @@ class TupleType extends ValueType, @tuple_type { */ class TypeMention extends @type_mention { Type type; - @type_mention_parent parent; TypeMention() { type_mention(this, getTypeRef(type), parent) } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll b/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll index 475b6bb9b87..9aa4ffa0ab6 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll @@ -208,7 +208,6 @@ class VSTestAssertNonNullMethod extends AssertNonNullMethod { /** A method that forwards to another assertion method. */ class ForwarderAssertMethod extends AssertMethod { Assertion a; - Parameter p; ForwarderAssertMethod() { diff --git a/csharp/ql/src/semmle/code/csharp/commons/Diagnostics.qll b/csharp/ql/src/semmle/code/csharp/commons/Diagnostics.qll index 221b13624db..edbc31b5292 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Diagnostics.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Diagnostics.qll @@ -9,13 +9,9 @@ class Diagnostic extends @diagnostic { Compilation getCompilation() { diagnostic_for(this, result, _, _) } int severity; - string tag; - string message; - string fullMessage; - Location location; Diagnostic() { diagnostics(this, severity, tag, message, fullMessage, location) } @@ -67,15 +63,10 @@ class CompilerError extends Diagnostic { /** A message from an extractor. */ class ExtractorMessage extends @extractor_message { int severity; - string origin; - string text; - string element; - string stackTrace; - Location location; ExtractorMessage() { diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll b/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll index a3508c8d307..d2e2879fc99 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll @@ -338,6 +338,7 @@ private module Internal { predicate bbIPostDominates(BasicBlock dom, BasicBlock bb) = idominance(exitBB/1, predBB/2)(_, dom, bb) } + private import Internal /** diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll index 628947c1b5e..85e5fa27cb7 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll @@ -282,7 +282,6 @@ module ControlFlow { */ class ElementNode extends Node, TElementNode { private Splits splits; - private ControlFlowElement cfe; ElementNode() { this = TElementNode(cfe, splits) } @@ -1891,6 +1890,7 @@ module ControlFlow { ) } } + import Successor cached @@ -1954,6 +1954,7 @@ module ControlFlow { cached ControlFlowElement getAControlFlowExitNode(ControlFlowElement cfe) { result = last(cfe, _) } } + import Cached /** A control flow element that is split into multiple control flow nodes. */ @@ -1961,5 +1962,6 @@ module ControlFlow { SplitControlFlowElement() { strictcount(this.getAControlFlowNode()) > 1 } } } + private import Internal } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll index 4b6afbeaf18..cb1af75ddfd 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll @@ -194,6 +194,7 @@ module AbstractValues { override string toString() { if this.isEmpty() then result = "empty" else result = "non-empty" } } } + private import AbstractValues /** @@ -480,9 +481,7 @@ private AssignableAccess getATrackedAccess(Ssa::Definition def, ControlFlow::Nod */ class GuardedExpr extends AccessOrCallExpr { private Guard g; - private AccessOrCallExpr sub0; - private AbstractValue v0; GuardedExpr() { isGuardedByExpr(this, g, sub0, v0) } @@ -545,9 +544,7 @@ class GuardedExpr extends AccessOrCallExpr { */ class GuardedControlFlowNode extends ControlFlow::Nodes::ElementNode { private Guard g; - private AccessOrCallExpr sub0; - private AbstractValue v0; GuardedControlFlowNode() { g.controlsNode(this, sub0, v0) } @@ -597,9 +594,7 @@ class GuardedControlFlowNode extends ControlFlow::Nodes::ElementNode { */ class GuardedDataFlowNode extends DataFlow::ExprNode { private Guard g; - private AccessOrCallExpr sub0; - private AbstractValue v0; GuardedDataFlowNode() { @@ -1455,8 +1450,10 @@ module Internal { ).getARead() } } + import CachedWithCFG } + import PreCFG /** @@ -1576,6 +1573,7 @@ module Internal { ) } } + import Cached /** @@ -1612,4 +1610,5 @@ module Internal { ) } } + private import Internal diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll index 177cb03a9c9..0fea41321d4 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll @@ -659,7 +659,6 @@ class BreakNormalCompletion extends NormalCompletion, TBreakNormalCompletion { */ class NestedCompletion extends Completion, TNestedCompletion { private NormalCompletion inner; - private Completion outer; NestedCompletion() { this = TNestedCompletion(inner, outer) } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index 7b752ea747e..c937fc92fed 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -74,6 +74,7 @@ private module Cached { ) } } + private import Cached /** @@ -902,7 +903,6 @@ module BooleanSplitting { */ class BooleanSplitImpl extends SplitImpl, TBooleanSplit { private BooleanSplitSubKind kind; - private boolean branch; BooleanSplitImpl() { this = TBooleanSplit(kind, branch) } @@ -1393,6 +1393,7 @@ private module SuccSplits { case2(pred, predSplits, succ, succSplits, c) } } + import SuccSplits /** Provides logic for calculating reachable control flow nodes. */ diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll b/csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll index b7ee3403ff8..c36bcc0dc8a 100755 --- a/csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll @@ -66,7 +66,6 @@ class NonDelegateCallArgumentCallContext extends ArgumentCallContext, TArgNonDel /** An argument of a delegate call. */ class DelegateCallArgumentCallContext extends ArgumentCallContext, TArgDelegateCallContext { DelegateCall dc; - int arg; DelegateCallArgumentCallContext() { this = TArgDelegateCallContext(dc, arg) } @@ -93,7 +92,6 @@ class DelegateCallArgumentCallContext extends ArgumentCallContext, TArgDelegateC class DelegateArgumentToLibraryCallableArgumentContext extends ArgumentCallContext, TDelegateToLibraryCallableArgCallContext { Expr delegate; - int arg; DelegateArgumentToLibraryCallableArgumentContext() { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index fdf73c8c5bd..6d9bab44f46 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -111,6 +111,7 @@ private module Cached { ) } } + import Cached /** An unbound callable. */ diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll b/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll index 8d279df6afd..9c7db07e149 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll @@ -345,11 +345,8 @@ abstract class PathNode extends TPathNode { private class SourcePathNode extends PathNode, TSourcePathNode { private Ssa::Definition def; - private string msg; - private Element reason; - private boolean isNullArgument; SourcePathNode() { this = TSourcePathNode(def, msg, reason, isNullArgument) } @@ -385,7 +382,6 @@ private class SourcePathNode extends PathNode, TSourcePathNode { private class InternalPathNode extends PathNode, TInternalPathNode { private Ssa::Definition def; - private BasicBlock bb; InternalPathNode() { this = TInternalPathNode(def, bb) } @@ -405,11 +401,8 @@ private class InternalPathNode extends PathNode, TInternalPathNode { private class SinkPathNode extends PathNode, TSinkPathNode { private Ssa::Definition def; - private BasicBlock bb; - private int i; - private Dereference d; SinkPathNode() { this = TSinkPathNode(def, bb, i, d) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index d63dee77a84..a4a5bfed774 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -76,6 +76,7 @@ module Ssa { ) } } + import Cached /** @@ -359,6 +360,7 @@ module Ssa { exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk, rk)) } } + private import SourceVariableImpl /** @@ -490,6 +492,7 @@ module Ssa { override string toString() { result = getQualifier() + "." + getAssignable() } } } + private import SourceVariables private module TrackedVariablesImpl { @@ -536,6 +539,7 @@ module Ssa { ) } } + private import TrackedVariablesImpl /** @@ -874,8 +878,10 @@ module Ssa { ) } } + import Cached } + private import SsaDefReaches /** @@ -1339,6 +1345,7 @@ module Ssa { ) } } + private import FieldOrPropsImpl /** @@ -1538,6 +1545,7 @@ module Ssa { ) } } + private import CapturedVariableImpl /** @@ -1797,6 +1805,7 @@ module Ssa { liveAfterWriteCapturedIn(bb, i, v, _, _, _) } } + private import CapturedVariableLivenessImpl cached @@ -1955,6 +1964,7 @@ module Ssa { ) } } + private import SsaImpl private string getSplitString(Definition def) { @@ -2289,7 +2299,6 @@ module Ssa { */ class ExplicitDefinition extends Definition, TSsaExplicitDef { TrackedVar tv; - AssignableDefinition ad; ExplicitDefinition() { this = TSsaExplicitDef(tv, ad, _, _) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll index 7ad04949c82..96f3a67bf98 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll @@ -227,6 +227,7 @@ private module Cached { ) } } + import Cached predicate viableCallable = viableImpl/1; @@ -321,7 +322,6 @@ abstract class DataFlowCall extends TDataFlowCall { /** A non-delegate C# call relevant for data flow. */ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall { private ControlFlow::Nodes::ElementNode cfn; - private DispatchCall dc; NonDelegateDataFlowCall() { this = TNonDelegateCall(cfn, dc) } @@ -352,7 +352,6 @@ abstract class DelegateDataFlowCall extends DataFlowCall { /** An explicit delegate call relevant for data flow. */ class ExplicitDelegateDataFlowCall extends DelegateDataFlowCall, TExplicitDelegateCall { private ControlFlow::Nodes::ElementNode cfn; - private DelegateCall dc; ExplicitDelegateDataFlowCall() { this = TExplicitDelegateCall(cfn, dc) } @@ -379,7 +378,6 @@ class ExplicitDelegateDataFlowCall extends DelegateDataFlowCall, TExplicitDelega */ class ImplicitDelegateDataFlowCall extends DelegateDataFlowCall, TImplicitDelegateCall { private ControlFlow::Nodes::ElementNode cfn; - private DelegateArgumentToLibraryCallable arg; ImplicitDelegateDataFlowCall() { this = TImplicitDelegateCall(cfn, arg) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index e248fa0dae6..740f4812bdc 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index e248fa0dae6..740f4812bdc 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index e248fa0dae6..740f4812bdc 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index e248fa0dae6..740f4812bdc 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index e248fa0dae6..740f4812bdc 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -1655,11 +1655,8 @@ module PathGraph { */ private class PathNodeMid extends PathNode, TPathNodeMid { Node node; - CallContext cc; - AccessPath ap; - Configuration config; PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) } @@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid { */ private class PathNodeSink extends PathNode, TPathNodeSink { Node node; - Configuration config; PathNodeSink() { this = TPathNodeSink(node, config) } @@ -2190,11 +2186,8 @@ private module FlowExploration { private class PartialPathNodePriv extends PartialPathNode { Node node; - CallContext cc; - PartialAccessPath ap; - Configuration config; PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) } @@ -2459,6 +2452,7 @@ private module FlowExploration { ) } } + import FlowExploration private predicate partialFlow( diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 9bb6a70c742..97052e80004 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -363,6 +363,7 @@ private module ImplCommon { newtype TReturnPosition = TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) } } + import ImplCommon pragma[noinline] @@ -418,7 +419,6 @@ class CallContextReturn extends CallContext, TReturn { /** A callable tagged with a relevant return kind. */ class ReturnPosition extends TReturnPosition0 { private DataFlowCallable c; - private ReturnKind kind; ReturnPosition() { this = TReturnPosition0(c, kind) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 5d120641723..7c1fdf4e033 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -269,7 +269,6 @@ module LocalFlow { /** An argument of a C# call. */ private class Argument extends Expr { private Expr call; - private int arg; Argument() { @@ -442,6 +441,7 @@ private module Cached { ) } } + import Cached /** An SSA definition, viewed as a node in a data flow graph. */ @@ -589,6 +589,7 @@ private module ParameterNodes { ) } } + private import ImplicitCapturedParameterNodeImpl /** @@ -622,6 +623,7 @@ private module ParameterNodes { } } } + import ParameterNodes /** A data flow node that represents a call argument. */ @@ -753,7 +755,6 @@ private module ArgumentNodes { */ class ImplicitCapturedArgumentNode extends ArgumentNode, TImplicitCapturedArgumentNode { private LocalScopeVariable v; - private ControlFlow::Nodes::ElementNode cfn; ImplicitCapturedArgumentNode() { this = TImplicitCapturedArgumentNode(cfn, v) } @@ -824,6 +825,7 @@ private module ArgumentNodes { override string toString() { result = "malloc" } } } + import ArgumentNodes /** A data flow node that represents a value returned by a callable. */ @@ -937,6 +939,7 @@ private module ReturnNodes { } } } + import ReturnNodes /** A data flow node that represents the output of a call. */ @@ -1017,7 +1020,6 @@ private module OutNodes { */ class ImplicitDelegateOutNode extends OutNode, TImplicitDelegateOutNode { private ControlFlow::Nodes::ElementNode cfn; - private ControlFlow::Nodes::ElementNode call; ImplicitDelegateOutNode() { this = TImplicitDelegateOutNode(cfn, call) } @@ -1045,6 +1047,7 @@ private module OutNodes { override string toString() { result = "[output] " + cfn } } } + import OutNodes private class FlowThroughLibraryCallableOutRefConfiguration extends ControlFlowReachabilityConfiguration { @@ -1146,9 +1149,7 @@ private predicate hasNonlocalValue(FieldLikeRead flr) { /** A write to a static field/property. */ private class StaticFieldLikeJumpNode extends NonLocalJumpNode, ExprNode { FieldLike fl; - FieldLikeRead flr; - ExprNode succ; StaticFieldLikeJumpNode() { @@ -1300,6 +1301,7 @@ private module PostUpdateNodes { override string toString() { result = "[post] " + cfn.toString() } } } + private import PostUpdateNodes /** A node that performs a type cast. */ diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll index 89c2a5fa4bf..abb4a7bec37 100755 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll @@ -103,7 +103,6 @@ library class DelegateCallExpr extends DelegateFlowSink { /** A delegate expression that is passed as the argument to a library callable. */ library class DelegateArgumentToLibraryCallable extends Expr { DelegateType dt; - Call call; DelegateArgumentToLibraryCallable() { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll index 4d0bc59d2a2..425724f3a22 100755 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll @@ -170,4 +170,5 @@ module Cached { flowThroughLibraryCallableOutRef(_, nodeFrom, nodeTo, false) } } + import Cached diff --git a/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll index dc658b43471..15420c7fcaf 100644 --- a/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll @@ -91,6 +91,7 @@ private module Internal { result = dc.(DispatchCallImpl).getADynamicTarget() } } + import Cached /** @@ -384,6 +385,7 @@ private module Internal { ) } } + private import SimpleTypeDataFlow /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll index e7b21f0f6ec..650c15f189a 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll @@ -76,7 +76,6 @@ DefaultEdge defaultEdge() { result = TDefaultEdge() } */ class CaseEdge extends EdgeKind, TCaseEdge { string minValue; - string maxValue; CaseEdge() { this = TCaseEdge(minValue, maxValue) } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll index 2c1b43672fc..a7ca4593ac4 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll @@ -59,7 +59,6 @@ abstract class IRVariable extends TIRVariable { */ class IRUserVariable extends IRVariable, TIRUserVariable { Language::Variable var; - Language::Type type; IRUserVariable() { this = TIRUserVariable(var, type, func) } @@ -110,9 +109,7 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { Language::AST ast; - TempVariableTag tag; - Language::Type type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index ea0a3f72998..43f9663d2cd 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -922,7 +922,6 @@ class ConvertInstruction extends UnaryInstruction { */ class InheritanceConversionInstruction extends UnaryInstruction { Language::Class baseClass; - Language::Class derivedClass; InheritanceConversionInstruction() { 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 fda04820848..1ced8ef3282 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 @@ -196,9 +196,7 @@ class MemoryOperand extends Operand { */ class NonPhiOperand extends Operand { Instruction useInstr; - Instruction defInstr; - OperandTag tag; NonPhiOperand() { @@ -231,7 +229,6 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand { class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - Overlap overlap; NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) } @@ -359,7 +356,6 @@ class ThisArgumentOperand extends ArgumentOperand { */ class PositionalArgumentOperand extends ArgumentOperand { override PositionalArgumentOperandTag tag; - int argIndex; PositionalArgumentOperand() { argIndex = tag.getArgIndex() } @@ -413,11 +409,8 @@ class SideEffectOperand extends TypedOperand { */ class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; - Instruction defInstr; - IRBlock predecessorBlock; - Overlap overlap; PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll index ccd5b8f8a0c..4ab9f89a42b 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll @@ -16,6 +16,7 @@ TranslatedElement getInstructionTranslatedElement(Instruction instruction) { } InstructionTag getInstructionTag(Instruction instruction) { instruction = MkInstruction(_, result) } + import Cached cached @@ -304,6 +305,7 @@ private module Cached { cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instr) { none() } } + import CachedForDebugging cached diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll index 823103b069f..bc2d7ba152f 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll @@ -29,7 +29,6 @@ class BuiltInOperation extends TBuiltInOperation { class ClassDerivation extends MkClassDerivation { Class baseClass; - Class derivedClass; ClassDerivation() { this = MkClassDerivation(baseClass, derivedClass) } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/HardcodedCredentials.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/HardcodedCredentials.qll index c83e5b9b2cf..f36f90d7063 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/HardcodedCredentials.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/HardcodedCredentials.qll @@ -166,9 +166,7 @@ module HardcodedCredentials { */ class HardcodedCredentialsSinkExpr extends Sink { private string description; - private Element supplementaryElement; - private string sinkName; HardcodedCredentialsSinkExpr() { diff --git a/docs/language/README.rst b/docs/language/README.rst index ac6edf8d5e5..c2fe8019908 100644 --- a/docs/language/README.rst +++ b/docs/language/README.rst @@ -48,9 +48,12 @@ For more information, see Building and previewing the QL language documentation ***************************************************** -To build and preview the QL documentation locally, you need to install Sphinx. +To build and preview the QL documentation and QL training presentations locally, you need to +install Sphinx 1.7.9. More recent versions of Sphinx do not work with hieroglyph, +the Sphinx extension that we use to generate HTML slides, as explained below. For installation options, see https://github.com/sphinx-doc/sphinx. + Using ``sphinx-build`` ---------------------- diff --git a/docs/language/global-sphinx-files/_templates/layout.html b/docs/language/global-sphinx-files/_templates/layout.html index e9bba0343e5..d5a714aa5e1 100644 --- a/docs/language/global-sphinx-files/_templates/layout.html +++ b/docs/language/global-sphinx-files/_templates/layout.html @@ -60,7 +60,7 @@