diff --git a/change-notes/1.19/analysis-cpp.md b/change-notes/1.19/analysis-cpp.md index f22f5dc638f..6d274150621 100644 --- a/change-notes/1.19/analysis-cpp.md +++ b/change-notes/1.19/analysis-cpp.md @@ -9,21 +9,33 @@ | Cast between `HRESULT` and a Boolean type (`cpp/hresult-boolean-conversion`) | external/cwe/cwe-253 | Finds logic errors caused by mistakenly treating the Windows `HRESULT` type as a Boolean instead of testing it with the appropriate macros. Enabled by default. | | Setting a DACL to `NULL` in a `SECURITY_DESCRIPTOR` (`cpp/unsafe-dacl-security-descriptor`) | external/cwe/cwe-732 | This query finds code that creates world-writable objects on Windows by setting their DACL to `NULL`. Enabled by default. | | Cast from `char*` to `wchar_t*` | security, external/cwe/cwe-704 | Detects potentially dangerous casts from `char*` to `wchar_t*`. Enabled by default on LGTM. | -| Dead code due to `goto` or `break` statement (`cpp/dead-code-goto`) | maintainability, external/cwe/cwe-561 | Detects dead code following a goto or break statement. Enabled by default on LGTM. | +| Dead code due to `goto` or `break` statement (`cpp/dead-code-goto`) | maintainability, external/cwe/cwe-561 | Detects dead code following a `goto` or `break` statement. Enabled by default on LGTM. | +| Inconsistent direction of for loop | correctness, external/cwe/cwe-835 | This query detects `for` loops where the increment and guard condition don't appear to correspond. Enabled by default on LGTM. | +| Incorrect Not Operator Usage | security, external/cwe/cwe-480 | This query finds uses of the logical not (`!`) operator that look like they should be bit-wise not (`~`). Available but not displayed by default on LGTM. | +| NULL application name with an unquoted path in call to CreateProcess | security, external/cwe/cwe-428 | This query finds unsafe uses of the `CreateProcess` function. Available but not displayed by default on LGTM. | ## Changes to existing queries | **Query** | **Expected impact** | **Change** | |----------------------------|------------------------|------------------------------------------------------------------| +| Array offset used before range check | More results and fewer false positive results | The query now recognizes array accesses in different positions within the expression. False positives where the range is checked before and after the array access have been fixed. | | Empty branch of conditional | Fewer false positive results | The query now recognizes commented blocks more reliably. | | Expression has no effect | Fewer false positive results | Expressions in template instantiations are now excluded from this query. | +| Global could be static | Fewer false positive results | Variables with declarations in header files are now excluded from this query. | | Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. Also fixed an issue where false positives could occur if the destructor body was not in the snapshot. | | Missing return statement (`cpp/missing-return`) | Visible by default | The precision of this query has been increased from 'medium' to 'high', which makes it visible by default in LGTM. It was 'medium' in release 1.17 and 1.18 because it had false positives due to an extractor bug that was fixed in 1.18. | -| Missing return statement | Fewer false positive results | The query is now produces correct results when a function returns a template-dependent type. | +| Missing return statement | Fewer false positive results | The query is now produces correct results when a function returns a template-dependent type, or makes a non-returning call to another function. | +| Static array access may cause overflow | More correct results | Data flow to the size argument of a buffer operation is now checked in this query. | | Call to memory access function may overflow buffer | More correct results | Array indexing with a negative index is now detected by this query. | +| Self comparison | Fewer false positive results | Code inside macro invocations is now excluded from the query. | | Suspicious call to memset | Fewer false positive results | Types involving decltype are now correctly compared. | | Suspicious add with sizeof | Fewer false positive results | Arithmetic with void pointers (where allowed) is now excluded from this query. | | Wrong type of arguments to formatting function | Fewer false positive results | False positive results involving typedefs have been removed. Expected argument types are determined more accurately, especially for wide string and pointer types. Custom (non-standard) formatting functions are also identified more accurately. | +| AV Rule 164 | Fewer false positive results | This query now accounts for explicit casts. | +| Negation of unsigned value | Fewer false positive results | This query now accounts for explicit casts. | +| Variable scope too large | Fewer false positive results | Variables with declarations in header files, or that are used at file scope, are now excluded from this query. | +| Comparison result is always the same | Fewer false positive results | Comparisons in template instantiations are now excluded from this query. | +| Unsigned comparison to zero | Fewer false positive results | Comparisons in template instantiations are now excluded from this query. | ## Changes to QL libraries diff --git a/change-notes/1.19/analysis-csharp.md b/change-notes/1.19/analysis-csharp.md index f650fcc5813..d5ace2e7bff 100644 --- a/change-notes/1.19/analysis-csharp.md +++ b/change-notes/1.19/analysis-csharp.md @@ -29,3 +29,7 @@ * `getArgument()` on `AccessorCall` has been improved so it now takes tuple assignments into account. For example, the argument for the implicit `value` parameter in the setter of property `P` is `0` in `(P, x) = (0, 1)`. Additionally, the argument for the `value` parameter in compound assignments is now only the expanded value, for example, in `P += 7` the argument is `P + 7` and not `7`. * The predicate `isInArgument()` has been added to the `AssignableAccess` class. This holds for expressions that are passed as arguments using `in`. + +## Changes to the autobuilder + +* When determining the target of `msbuild` or `dotnet build`, first look for `.proj` files, then `.sln` files, and finally `.csproj`/`.vcxproj` files. In all three cases, choose the project/solution file closest to the root. diff --git a/change-notes/1.19/analysis-java.md b/change-notes/1.19/analysis-java.md index 6458ff1d010..e9594966b6e 100644 --- a/change-notes/1.19/analysis-java.md +++ b/change-notes/1.19/analysis-java.md @@ -16,6 +16,7 @@ | **Query** | **Expected impact** | **Change** | |----------------------------|------------------------|------------------------------------------------------------------| | Array index out of bounds (`java/index-out-of-bounds`) | Fewer false positive results | False positives involving arrays with a length evenly divisible by 3 or some greater number and an index being increased with a similar stride length are no longer reported. | +| Confusing overloading of methods (`java/confusing-method-signature`) | Fewer false positive results | A bugfix in the inheritance relation ensures that spurious results on certain generic classes no longer occur. | | Query built from user-controlled sources (`java/sql-injection`) | More results | Sql injection sinks from the Spring JDBC, MyBatis, and Hibernate frameworks are now reported. | | Query built without neutralizing special characters (`java/concatenated-sql-query`) | More results | Sql injection sinks from the Spring JDBC, MyBatis, and Hibernate frameworks are now reported. | | Unreachable catch clause (`java/unreachable-catch-clause`) | Fewer false positive results | This rule now accounts for calls to generic methods that throw generic exceptions. | diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md index 63679cb0174..b45cb8ad8f7 100644 --- a/change-notes/1.19/analysis-javascript.md +++ b/change-notes/1.19/analysis-javascript.md @@ -4,8 +4,6 @@ * Modelling of taint flow through array operations has been improved. This may give additional results for the security queries. -* The taint tracking library now recognizes additional sanitization patterns. This may give fewer false-positive results for the security queries. - * Support for AMD modules has been improved. This may give additional results for the security queries as well as any queries that use type inference on code bases that use such modules. * Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following features: @@ -13,6 +11,8 @@ - outbound network access, for example through the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) - the [lodash](https://lodash.com), [underscore](https://underscorejs.org/), [async](https://www.npmjs.com/package/async) and [async-es](https://www.npmjs.com/package/async-es) libraries +* The taint tracking library now recognizes additional sanitization patterns. This may give fewer false-positive results for the security queries. + * Type inference for function calls has been improved. This may give additional results for queries that rely on type inference. * Where applicable, path explanations have been added to the security queries. @@ -35,29 +35,38 @@ | **Query** | **Expected impact** | **Change** | |--------------------------------|----------------------------|----------------------------------------------| +| Ambiguous HTML id attribute | Lower severity | The severity of this rule has been revised to "warning". | +| Clear-text logging of sensitive information | Fewer results | This rule now tracks flow more precisely. | | Client side cross-site scripting | More results | This rule now also flags HTML injection in the body of an email. | +| Client-side URL redirect | Fewer false-positive results | This rule now recognizes safe redirects in more cases. | +| Conflicting HTML element attributes | Lower severity | The severity of this rule has been revised to "warning". | +| Duplicate 'if' condition | Lower severity | The severity of this rule has been revised to "warning". | +| Duplicate switch case | Lower severity | The severity of this rule has been revised to "warning". | | Information exposure through a stack trace | More results | This rule now also flags cases where the entire exception object (including the stack trace) may be exposed. | | Missing CSRF middleware | Fewer false-positive results | This rule now recognizes additional CSRF protection middlewares. | +| Missing 'this' qualifier | Fewer false-positive results | This rule now recognizes additional intentional calls to global functions. | +| Missing variable declaration | Lower severity | The severity of this rule has been revised to "warning". | | Regular expression injection | Fewer false-positive results | This rule now identifies calls to `String.prototype.search` with more precision. | | Remote property injection | Fewer results | The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. | | Self assignment | Fewer false-positive results | This rule now ignores self-assignments preceded by a JSDoc comment with a `@type` tag. | +| Server-side URL redirect | Fewer false-positive results | This rule now recognizes safe redirects in more cases. | | Server-side URL redirect | More results | This rule now recognizes redirection calls in more cases. | | Unbound event handler receiver | Fewer false-positive results | This rule now recognizes additional ways class methods can be bound. | | Uncontrolled data used in remote request | More results | This rule now recognizes additional kinds of requests. | +| Unknown directive | Fewer false positives results | This rule now recognizes YUI compressor directives. | | Unused import | Fewer false-positive results | This rule no longer flags imports used by the `transform-react-jsx` Babel plugin. | | Unused variable, import, function or class | Fewer false-positive results | This rule now flags fewer variables that may be used by `eval` calls. | | Unused variable, import, function or class | Fewer results | This rule now flags import statements with multiple unused imports once. | | Useless assignment to local variable | Fewer false-positive results | This rule now recognizes additional ways default values can be set. | | Whitespace contradicts operator precedence | Fewer false-positive results | This rule no longer flags operators with asymmetric whitespace. | -| Client-side URL redirect | Fewer false-positive results | This rule now recognizes safe redirects in more cases. | -| Server-side URL redirect | Fewer false-positive results | This rule now recognizes safe redirects in more cases. | +| Wrong use of 'this' for static method | More results, fewer false-positive results | This rule now recognizes inherited methods. | ## Changes to QL libraries -* The flow configuration framework now supports distinguishing and tracking different kinds of taint, specified by an extensible class `FlowLabel` (which can also be referred to by its alias `TaintKind`). - -* The `DataFlow::ThisNode` class now corresponds to the implicit receiver parameter of a function, as opposed to an indivdual `this` expression. This means `getALocalSource` now maps all `this` expressions within a given function to the same source. The data-flow node associated with a `ThisExpr` can no longer be cast to `DataFlow::SourceNode` or `DataFlow::ThisNode` - it is recomended to use `getALocalSource` before casting or instead of casting. +* A `DataFlow::ParameterNode` instance now exists for all function parameters. Previously, unused parameters did not have a corresponding dataflow node. * `ReactComponent::getAThisAccess` has been renamed to `getAThisNode`. The old name is still usable but is deprecated. It no longer gets individual `this` expressions, but the `ThisNode` mentioned above. -* A `DataFlow::ParameterNode` instance now exists for all function parameters. Previously, unused parameters did not have a corresponding dataflow node. +* The `DataFlow::ThisNode` class now corresponds to the implicit receiver parameter of a function, as opposed to an indivdual `this` expression. This means `getALocalSource` now maps all `this` expressions within a given function to the same source. The data-flow node associated with a `ThisExpr` can no longer be cast to `DataFlow::SourceNode` or `DataFlow::ThisNode` - it is recomended to use `getALocalSource` before casting or instead of casting. + +* The flow configuration framework now supports distinguishing and tracking different kinds of taint, specified by an extensible class `FlowLabel` (which can also be referred to by its alias `TaintKind`). diff --git a/change-notes/1.19/extractor-javascript.md b/change-notes/1.19/extractor-javascript.md index 4b8a4842892..8aa278e623c 100644 --- a/change-notes/1.19/extractor-javascript.md +++ b/change-notes/1.19/extractor-javascript.md @@ -16,8 +16,16 @@ ## General improvements -> Changes that affect alerts in many files or from many queries -> For example, changes to file classification +* On LGTM, files whose name ends in `.min.js` or `-min.js` are no longer extracted by default, since they most likely contain minified code and results in these files would be hidden by default anyway. To extract such files anyway, you can add the following filters to your `lgtm.yml` file (or add them to existing filters): + +```yaml +extraction: + javascript: + index: + filters: + - include: "**/*.min.js" + - include: "**/*-min.js" +``` ## Changes to code extraction diff --git a/cpp/ql/src/Architecture/General Top-Level Information/GeneralStatistics.qhelp b/cpp/ql/src/Architecture/General Top-Level Information/GeneralStatistics.qhelp index a8230232c93..1bb15f10ed3 100644 --- a/cpp/ql/src/Architecture/General Top-Level Information/GeneralStatistics.qhelp +++ b/cpp/ql/src/Architecture/General Top-Level Information/GeneralStatistics.qhelp @@ -15,20 +15,9 @@ functions, and the total number of source code resp. comment lines.

depends on third-party libraries: low self-containedness means that many dependencies are to library classes (as opposed to source classes within the same application).

- -
-

The results of this query are purely informative and more useful for getting an overall impression of the application than for -identifying particular defects.

+identifying particular problems with the code.

+ - - - -
- - - - - diff --git a/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql b/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql index 872f01d4421..7a7e589fb34 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql @@ -5,6 +5,7 @@ * @kind problem * @id cpp/offset-use-before-range-check * @problem.severity warning + * @precision medium * @tags reliability * security * external/cwe/cwe-120 @@ -13,10 +14,29 @@ import cpp -from Variable v, LogicalAndExpr andexpr, ArrayExpr access, LTExpr rangecheck -where access.getArrayOffset() = v.getAnAccess() - and andexpr.getLeftOperand().getAChild() = access - and andexpr.getRightOperand() = rangecheck - and rangecheck.getLeftOperand() = v.getAnAccess() - and not access.isInMacroExpansion() +predicate beforeArrayAccess(Variable v, ArrayExpr access, Expr before) { + exists(LogicalAndExpr andexpr | + access.getArrayOffset() = v.getAnAccess() and + andexpr.getRightOperand().getAChild*() = access and + andexpr.getLeftOperand() = before + ) +} + +predicate afterArrayAccess(Variable v, ArrayExpr access, Expr after) { + exists(LogicalAndExpr andexpr | + access.getArrayOffset() = v.getAnAccess() and + andexpr.getLeftOperand().getAChild*() = access and + andexpr.getRightOperand() = after + ) +} + +from Variable v, ArrayExpr access, LTExpr rangecheck +where + afterArrayAccess(v, access, rangecheck) and + rangecheck.getLeftOperand() = v.getAnAccess() and + not access.isInMacroExpansion() and + not exists(LTExpr altcheck | + beforeArrayAccess(v, access, altcheck) and + altcheck.getLeftOperand() = v.getAnAccess() + ) select access, "This use of offset '" + v.getName() + "' should follow the $@.", rangecheck, "range check" diff --git a/cpp/ql/src/Best Practices/Magic Constants/MagicNumbersUseConstant.ql b/cpp/ql/src/Best Practices/Magic Constants/MagicNumbersUseConstant.ql index 1a9852990ff..2c8ceac2753 100644 --- a/cpp/ql/src/Best Practices/Magic Constants/MagicNumbersUseConstant.ql +++ b/cpp/ql/src/Best Practices/Magic Constants/MagicNumbersUseConstant.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/use-number-constant * @problem.severity recommendation + * @precision low + * @tags maintainability */ import cpp import MagicConstants diff --git a/cpp/ql/src/Best Practices/Magic Constants/MagicStringsUseConstant.ql b/cpp/ql/src/Best Practices/Magic Constants/MagicStringsUseConstant.ql index 990de6048e5..9cd129c88dc 100644 --- a/cpp/ql/src/Best Practices/Magic Constants/MagicStringsUseConstant.ql +++ b/cpp/ql/src/Best Practices/Magic Constants/MagicStringsUseConstant.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/use-string-constant * @problem.severity recommendation + * @precision low + * @tags maintainability */ import cpp import MagicConstants diff --git a/cpp/ql/src/Best Practices/NVI.ql b/cpp/ql/src/Best Practices/NVI.ql index 5e5a20fd15a..723395769c3 100644 --- a/cpp/ql/src/Best Practices/NVI.ql +++ b/cpp/ql/src/Best Practices/NVI.ql @@ -4,7 +4,9 @@ * to enforce invariants that should hold for the whole hierarchy. * @kind problem * @id cpp/nvi - * @problem.severity warning + * @problem.severity recommendation + * @precision low + * @tags maintainability */ import cpp diff --git a/cpp/ql/src/Best Practices/NVIHub.ql b/cpp/ql/src/Best Practices/NVIHub.ql index 6d4600b68f9..a5e67a2cbee 100644 --- a/cpp/ql/src/Best Practices/NVIHub.ql +++ b/cpp/ql/src/Best Practices/NVIHub.ql @@ -4,8 +4,11 @@ * to enforce invariants that should hold for the whole hierarchy. * This is especially problematic in classes with many * dependencies or dependents. - * @kind table + * @kind problem * @id cpp/nvi-hub + * @problem.severity recommendation + * @precision low + * @tags maintainability */ import cpp @@ -19,4 +22,4 @@ where f.hasSpecifier("public") and fclass = f.getDeclaringType() and hubIndex = fclass.getMetrics().getAfferentCoupling() * fclass.getMetrics().getEfferentCoupling() and hubIndex > 100 -select f.getFile(), f, "Avoid having public virtual methods (NVI idiom)" +select f, "Avoid having public virtual methods (NVI idiom)" diff --git a/cpp/ql/src/Best Practices/Unused Entities/UnusedIncludes.ql b/cpp/ql/src/Best Practices/Unused Entities/UnusedIncludes.ql index c8480a037b6..42d5d910fb7 100644 --- a/cpp/ql/src/Best Practices/Unused Entities/UnusedIncludes.ql +++ b/cpp/ql/src/Best Practices/Unused Entities/UnusedIncludes.ql @@ -4,7 +4,10 @@ * the included elements are used. * @kind problem * @id cpp/unused-includes - * @problem.severity warning + * @problem.severity recommendation + * @precision low + * @tags maintainability + * useless-code */ import cpp diff --git a/cpp/ql/src/Critical/OverflowStatic.ql b/cpp/ql/src/Critical/OverflowStatic.ql index e8503d3a25d..386212cb676 100644 --- a/cpp/ql/src/Critical/OverflowStatic.ql +++ b/cpp/ql/src/Critical/OverflowStatic.ql @@ -82,22 +82,31 @@ class CallWithBufferSize extends FunctionCall Expr buffer() { exists(int i | bufferAndSizeFunction(this.getTarget(), i, _) and - result = this.getArgument(i)) + result = this.getArgument(i) + ) } - Expr statedSize() { + Expr statedSizeExpr() { exists(int i | bufferAndSizeFunction(this.getTarget(), _, i) and - result = this.getArgument(i)) + result = this.getArgument(i) + ) + } + int statedSizeValue() { + exists(Expr statedSizeSrc | + DataFlow::localFlow(DataFlow::exprNode(statedSizeSrc), DataFlow::exprNode(statedSizeExpr())) and + result = statedSizeSrc.getValue().toInt() + ) } } predicate wrongBufferSize(Expr error, string msg) { - exists(CallWithBufferSize call, int bufsize, Variable buf | + exists(CallWithBufferSize call, int bufsize, Variable buf, int statedSize | staticBuffer(call.buffer(), buf, bufsize) and - call.statedSize().getValue().toInt() > bufsize and - error = call.statedSize() and + statedSize = min(call.statedSizeValue()) and + statedSize > bufsize and + error = call.statedSizeExpr() and msg = "Potential buffer-overflow: '" + buf.getName() + - "' has size " + bufsize.toString() + " not " + call.statedSize().getValue() + ".") + "' has size " + bufsize.toString() + " not " + statedSize + ".") } predicate outOfBounds(BufferAccess bufaccess, string msg) diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql index a895174e215..8367fb996fe 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql @@ -12,5 +12,6 @@ from GlobalVariable v where forex(VariableAccess va | va.getTarget() = v | va.getFile() = v.getDefinitionLocation().getFile()) and not v.hasSpecifier("static") and strictcount(v.getAnAccess().getEnclosingFunction()) > 1 // If = 1, variable should be function-scope. + and not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere select v, "The global variable " + v.getName() + " is not accessed outside of " + v.getFile().getBaseName() + " and could be made static." diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql index 40fa3b48a2d..b54e824be05 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql @@ -10,5 +10,7 @@ import cpp from GlobalVariable v, Function f where v.getAnAccess().getEnclosingFunction() = f and - strictcount(v.getAnAccess().getEnclosingFunction()) = 1 + strictcount(v.getAnAccess().getEnclosingFunction()) = 1 and + forall(VariableAccess a | a = v.getAnAccess() | exists(a.getEnclosingFunction())) and + not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere select v, "The variable " + v.getName() + " is only accessed in $@ and should be scoped accordingly.", f, f.getName() diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql index 4d0b4184e1d..9671508449a 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql @@ -18,4 +18,12 @@ from ComparisonOperation cmp where pointlessSelfComparison(cmp) and not nanTest(cmp) and not overflowTest(cmp) + and not exists(MacroInvocation mi | + // cmp is in mi + mi.getAnExpandedElement() = cmp and + + // and cmp was apparently not passed in as a macro parameter + cmp.getLocation().getStartLine() = mi.getLocation().getStartLine() and + cmp.getLocation().getStartColumn() = mi.getLocation().getStartColumn() + ) select cmp, "Self comparison." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql b/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql index c82d86aadfd..da5be6e494f 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/more-64-bit-waste * @problem.severity warning + * @tags maintainability + * portability */ import semmle.code.cpp.padding.Padding diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql b/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql index 95383e86fa5..1c1bce79457 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/non-portable-printf * @problem.severity warning + * @tags maintainability + * portability */ import cpp diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql b/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql index 8578324883a..1f52a265d0a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql @@ -4,7 +4,8 @@ * that by reordering them one could reduce the amount of internal padding on a 64-bit architecture. * @kind problem * @id cpp/suboptimal-64-bit-type - * @problem.severity warning + * @problem.severity recommendation + * @tags efficiency */ import semmle.code.cpp.padding.Padding diff --git a/cpp/ql/src/Metrics/History/HChurn.ql b/cpp/ql/src/Metrics/History/HChurn.ql index 40b4459caca..dc1f89b0e69 100644 --- a/cpp/ql/src/Metrics/History/HChurn.ql +++ b/cpp/ql/src/Metrics/History/HChurn.ql @@ -7,6 +7,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg sum max + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HLinesAdded.ql b/cpp/ql/src/Metrics/History/HLinesAdded.ql index 1a9fcc301e3..88d8565a4a3 100644 --- a/cpp/ql/src/Metrics/History/HLinesAdded.ql +++ b/cpp/ql/src/Metrics/History/HLinesAdded.ql @@ -7,6 +7,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg sum max + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HLinesDeleted.ql b/cpp/ql/src/Metrics/History/HLinesDeleted.ql index 72e54706056..b6851ce7e0e 100644 --- a/cpp/ql/src/Metrics/History/HLinesDeleted.ql +++ b/cpp/ql/src/Metrics/History/HLinesDeleted.ql @@ -7,6 +7,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg sum max + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HNumberOfAuthors.ql b/cpp/ql/src/Metrics/History/HNumberOfAuthors.ql index 1da244ff31a..cce61f855f0 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfAuthors.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfAuthors.ql @@ -6,6 +6,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg min max + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HNumberOfChanges.ql b/cpp/ql/src/Metrics/History/HNumberOfChanges.ql index e3b2396662c..adb553c0d39 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfChanges.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfChanges.ql @@ -7,6 +7,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg min max sum + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HNumberOfCoCommits.ql b/cpp/ql/src/Metrics/History/HNumberOfCoCommits.ql index 66dd1607163..e9547a58eab 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfCoCommits.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfCoCommits.ql @@ -7,6 +7,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg min max + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HNumberOfReCommits.ql b/cpp/ql/src/Metrics/History/HNumberOfReCommits.ql index de958ad32b5..31edabbaad2 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfReCommits.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfReCommits.ql @@ -7,6 +7,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg min max + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HNumberOfRecentAuthors.ql b/cpp/ql/src/Metrics/History/HNumberOfRecentAuthors.ql index c912897f404..5237b9e63aa 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfRecentAuthors.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfRecentAuthors.ql @@ -7,6 +7,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg min max + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql b/cpp/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql index 8009356cde9..ecf2ee48581 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql @@ -6,6 +6,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg min max sum + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Metrics/History/HNumberOfRecentChanges.ql b/cpp/ql/src/Metrics/History/HNumberOfRecentChanges.ql index 2ce984f40a1..e8f64e4f0a4 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfRecentChanges.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfRecentChanges.ql @@ -6,6 +6,7 @@ * @treemap.warnOn highValues * @metricType file * @metricAggregate avg min max sum + * @deprecated */ import cpp import external.VCS diff --git a/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql b/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql index ea3f09d1161..4335bf18cc4 100644 --- a/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql +++ b/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql @@ -12,5 +12,6 @@ from GlobalVariable v where forex(VariableAccess va | va.getTarget() = v | va.getFile() = v.getDefinitionLocation().getFile()) and not v.hasSpecifier("static") and strictcount(v.getAnAccess().getEnclosingFunction()) > 1 // If = 1, variable should be function-scope. + and not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere select v, "The global variable " + v.getName() + " is not accessed outside of " + v.getFile().getBaseName() + " and could be made static." diff --git a/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql b/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql index b6358d41c82..87c0e20e92c 100644 --- a/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql +++ b/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql @@ -10,5 +10,7 @@ import cpp from GlobalVariable v, Function f where v.getAnAccess().getEnclosingFunction() = f and - strictcount(v.getAnAccess().getEnclosingFunction()) = 1 + strictcount(v.getAnAccess().getEnclosingFunction()) = 1 and + forall(VariableAccess a | a = v.getAnAccess() | exists(a.getEnclosingFunction())) and + not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere select v, "The variable " + v.getName() + " is only accessed in $@ and should be scoped accordingly.", f, f.getName() diff --git a/cpp/ql/src/external/tests/DefectFilter.ql b/cpp/ql/src/external/tests/DefectFilter.ql index 7c9459f64ce..de372930845 100644 --- a/cpp/ql/src/external/tests/DefectFilter.ql +++ b/cpp/ql/src/external/tests/DefectFilter.ql @@ -4,7 +4,6 @@ */ import cpp import external.DefectFilter -import external.VCS from DefectResult res where res.getFile().getMetrics().getNumberOfLinesOfCode() > 200 diff --git a/cpp/ql/src/external/tests/DefectFromSVN.ql b/cpp/ql/src/external/tests/DefectFromSVN.ql index f58a6482ebc..863205834a2 100644 --- a/cpp/ql/src/external/tests/DefectFromSVN.ql +++ b/cpp/ql/src/external/tests/DefectFromSVN.ql @@ -3,6 +3,7 @@ * @description A test case for creating a defect from SVN data. * @kind problem * @problem.severity warning + * @deprecated */ import cpp diff --git a/cpp/ql/src/external/tests/MetricFromSVN.ql b/cpp/ql/src/external/tests/MetricFromSVN.ql index 32d27c7deaf..86d26323056 100644 --- a/cpp/ql/src/external/tests/MetricFromSVN.ql +++ b/cpp/ql/src/external/tests/MetricFromSVN.ql @@ -3,6 +3,7 @@ * @description Find number of commits for a file * @treemap.warnOn lowValues * @metricType file + * @deprecated */ import cpp diff --git a/cpp/ql/src/filters/RecentDefects.ql b/cpp/ql/src/filters/RecentDefects.ql index cf904d602ad..04c7afd0487 100644 --- a/cpp/ql/src/filters/RecentDefects.ql +++ b/cpp/ql/src/filters/RecentDefects.ql @@ -6,6 +6,7 @@ * before the date of the snapshot. * @kind problem * @id cpp/recent-defects-filter + * @deprecated */ import cpp import external.DefectFilter diff --git a/cpp/ql/src/filters/RecentDefectsForMetric.ql b/cpp/ql/src/filters/RecentDefectsForMetric.ql index 29515538388..00317d41750 100644 --- a/cpp/ql/src/filters/RecentDefectsForMetric.ql +++ b/cpp/ql/src/filters/RecentDefectsForMetric.ql @@ -6,6 +6,7 @@ * before the snapshot. * @kind treemap * @id cpp/recent-defects-for-metric-filter + * @deprecated */ import cpp import external.MetricFilter diff --git a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql index 5d7c1324319..e4f6524ae5f 100644 --- a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql +++ b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-1 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql index 81441a548fc..cf1b952e17c 100644 --- a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql +++ b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql @@ -4,6 +4,10 @@ * @kind problem * @id cpp/jsf/av-rule-2 * @problem.severity error + * @tags maintainability + * readability + * testability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql index 41aea8836d7..60f8cf8616f 100644 --- a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql +++ b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql @@ -3,7 +3,9 @@ * @description All functions shall have a cyclomatic complexity number of 20 or less. * @kind problem * @id cpp/jsf/av-rule-3 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql index c7ff2e29cd5..ac46a454101 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-11 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp import external.ExternalArtifact diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql index 704a605f7ad..b3460c5bc5f 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-12 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql index 1eeb9f0ef3e..6d03cd712aa 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-13 * @problem.severity error + * @tags maintainability + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql index f9da62380f6..792383baf77 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-14 * @problem.severity error + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 9.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 9.ql index 5ac20cfc5a6..9df1b72a736 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 9.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 9.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-9 * @problem.severity warning + * @tags maintainability + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql index 30a36d0ad96..520cb67a622 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-17 * @problem.severity error + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql index 8045b2bb604..a9eeb2e6639 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-18 * @problem.severity error + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql index ea4885b13a3..414ba2e969f 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-19 * @problem.severity error + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql index f5658511c13..fed2482a56c 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql @@ -4,6 +4,10 @@ * @kind problem * @id cpp/jsf/av-rule-20 * @problem.severity error + * @tags correctness + * portability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql index 388a717eebb..8d3ed394737 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-21 * @problem.severity error + * @tags correctness + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql index 4a8f075a7bd..8a1cb164e93 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-22 * @problem.severity error + * @tags maintainability + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql index 62b3b4c6539..1c0c84c7cdd 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-23 * @problem.severity error + * @tags correctness + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql index 1cec97180f7..42e456e3dd6 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql @@ -4,7 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-24 * @problem.severity warning - * @tags portability + * @tags correctness + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql index 659afa17cf4..09df5fa8b56 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-25 * @problem.severity error + * @tags correctness + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql index 095b7ecb80a..9561f452cd3 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-26 * @problem.severity error + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql index 43b483caa48..1aed7ddab59 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-27 * @problem.severity warning + * @tags maintainability + * portability + * external/jsf */ import cpp import semmle.code.cpp.headers.MultipleInclusion diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql index 8b044fdfc0e..9d22ab3c340 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-28 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp import semmle.code.cpp.headers.MultipleInclusion diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql index c6229e118b6..f3dc2a2e87f 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-29 * @problem.severity error + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql index dff8e58367b..ceedac6112f 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-30 * @problem.severity error + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql index 74b5eb9697b..9c8f389cf3f 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-31 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp import semmle.code.cpp.headers.MultipleInclusion diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql index 9dd2e5bfc22..59fef7909e0 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql @@ -7,6 +7,8 @@ * @id cpp/include-non-header * @tags maintainability * modularity + * readability + * external/jsf */ import cpp import semmle.code.cpp.AutogeneratedFile diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql index bdf802a85f7..2b416c4ce21 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-33 * @problem.severity error + * @tags maintainability + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql index 1f1ddef6a9c..b3b9dc19a95 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql @@ -10,6 +10,7 @@ * @tags efficiency * maintainability * modularity + * external/jsf */ import cpp import semmle.code.cpp.headers.MultipleInclusion diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql index 4a38b3807b6..0bf35a35f17 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-39 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql b/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql index fbc24554547..9ca933383df 100644 --- a/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql +++ b/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-40 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql index e3f6ce995c1..7167bb59cd5 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql @@ -3,7 +3,10 @@ * @description Source lines will be kept to a length of 120 characters or less. * @kind problem * @id cpp/jsf/av-rule-41 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql index 170ed0a4458..e7058321347 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql @@ -3,7 +3,10 @@ * @description Each expression-statement will be on a separate line. * @kind problem * @id cpp/jsf/av-rule-42 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql index c2094226871..ef9d5fbd748 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-43 * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql index 7b842e4edd7..540434cb718 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql @@ -3,7 +3,10 @@ * @description All indentations will be at least two spaces and be consistent within the same source file. * @kind problem * @id cpp/jsf/av-rule-44 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql index 79bdad085b8..b022760d806 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql @@ -3,7 +3,10 @@ * @description All words in an identifier will be separated by the underscore character. * @kind problem * @id cpp/jsf/av-rule-45 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql index 4511cbfe1f0..841b32df310 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql @@ -3,7 +3,10 @@ * @description User-specified identifiers (internal and external) will not rely on significance of more than 64 characters. * @kind problem * @id cpp/jsf/av-rule-46 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql index 49255f8347f..fb36adf66a9 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql @@ -3,7 +3,9 @@ * @description Identifiers will not begin with the underscore character. * @kind problem * @id cpp/jsf/av-rule-47 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql index 890245aafcd..1a900733330 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-48 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql index 68301d12c27..e422ee217fe 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql @@ -3,7 +3,10 @@ * @description All acronyms in an identifier will be composed of uppercase letters. * @kind problem * @id cpp/jsf/av-rule-49 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp import Naming diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql index 5ead6fe0236..ca45954eeb6 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql @@ -3,7 +3,10 @@ * @description The first word of the name of a class, structure, namespace, enumeration, or type created with typedef will begin with an uppercase letter. All other letters will be lowercase. * @kind problem * @id cpp/jsf/av-rule-50 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp import Naming diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql index 346e9c3ee4c..e6fe9828e88 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql @@ -3,7 +3,10 @@ * @description All letters contained in function and variable names will be lowercase. * @kind problem * @id cpp/jsf/av-rule-51 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp import Naming diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql index 93218392e92..3c1d3631843 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql @@ -3,7 +3,10 @@ * @description Identifiers for constant and enumerator values shall be lowercase. * @kind problem * @id cpp/jsf/av-rule-52 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp import Naming diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql index 77953c40c6d..d70e7ff48bc 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql @@ -3,7 +3,10 @@ * @description The following character sequences shall not appear in header file names: ', \, /*, //, or ". * @kind problem * @id cpp/jsf/av-rule-53-1 - * @problem.severity error + * @problem.severity warning + * @tags maintainability + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql index 862d9028de3..b5f2d223951 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql @@ -3,7 +3,10 @@ * @description Header files will always have a file name extension of .h. * @kind problem * @id cpp/jsf/av-rule-53 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql index cb40d30d51d..d7f10a88e57 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql @@ -3,7 +3,10 @@ * @description Implementation files will always have a file name extension of .cpp. * @kind problem * @id cpp/jsf/av-rule-54 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql index 2c205cc009f..fe629ce5a4c 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql @@ -3,7 +3,10 @@ * @description The public, protected, and private sections of a class will be declared in that order. * @kind problem * @id cpp/jsf/av-rule-57 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql index 08a6e2c81b3..80b6ec08004 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql @@ -3,7 +3,10 @@ * @description When declaring and defining functions with more than two parameters, the leading parenthesis and the first argument will be written on the same line as the function name. Each additional argument will be written on a separate line (with the closing parenthesis directly after the last argument). * @kind problem * @id cpp/jsf/av-rule-58 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql index ca598d20b2e..6baf82e3b32 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql @@ -3,7 +3,10 @@ * @description The statements forming the body of an if, else if, else, while, do-while or for statement shall always be enclosed in braces, even if the braces form an empty block. * @kind problem * @id cpp/jsf/av-rule-59 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql index 206eb7c5d99..c1b2729aec2 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql @@ -3,7 +3,10 @@ * @description Braces which enclose a block will be placed in the same column, on separate lines directly before and after the block. * @kind problem * @id cpp/jsf/av-rule-60 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql index e31e844a3a5..feee51df3de 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql @@ -3,7 +3,10 @@ * @description Braces which enclose a block will have nothing else on the line except comments (if necessary). * @kind problem * @id cpp/jsf/av-rule-61 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql index 2f65ce9ec83..4fa3ac5b8f0 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql @@ -3,7 +3,10 @@ * @description Spaces will not be used around '.' or '->', nor between unary operators and operands. * @kind problem * @id cpp/jsf/av-rule-63 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql index 1ef9a49bb23..bfe52e65a65 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql @@ -3,7 +3,9 @@ * @description Unneeded implicitly generated member functions shall be explicitly disallowed. * @kind problem * @id cpp/jsf/av-rule-68 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql index 1daec9c9cec..3f9b23311aa 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-69 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql index af544ae4610..1e08577217d 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql @@ -5,7 +5,9 @@ * for logical or efficiency reasons. * @kind problem * @id cpp/jsf/av-rule-70 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql index 354c165a5e9..01a6195c88e 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql @@ -8,6 +8,7 @@ * @tags reliability * readability * language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql index 8a1cc05eb72..2b0159e6452 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-71 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql index 2cce8b26646..4d7025d38a5 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql @@ -3,8 +3,10 @@ * @description Unnecessary default constructors shall not be defined. * @kind problem * @id cpp/jsf/av-rule-73 - * @problem.severity error + * @problem.severity recommendation * @precision low + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql index 7828fc02849..d0ec52033c1 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql @@ -6,6 +6,8 @@ * @kind problem * @id cpp/jsf/av-rule-74 * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql index ba78dec6486..c16f09dbb93 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql @@ -3,7 +3,10 @@ * @description Members of the initialization list shall be listed in the order in which they are declared in the class. * @kind problem * @id cpp/jsf/av-rule-75 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql index 9ab2a892b65..b065b75aed3 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql @@ -3,7 +3,9 @@ * @description A copy constructor and an assignment operator shall be declared for classes that contain pointers to data items or nontrivial destructors. If the copy constructor and assignment operators are not required, they should be explicitly disallowed. * @kind problem * @id cpp/jsf/av-rule-76 - * @problem.severity error + * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql index c268d3c4f7f..0b847e795c6 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql @@ -8,6 +8,7 @@ * @tags reliability * readability * language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql index 04a69db8ddd..5c05abec0cd 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql @@ -3,11 +3,11 @@ * @description All base classes with a virtual function should define a virtual destructor. If an application attempts to delete a derived class object through a base class pointer, the result is undefined if the base class destructor is non-virtual. * @kind problem * @problem.severity warning - * @precision high * @id cpp/jsf/av-rule-78 * @tags reliability * readability * language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql index 6ad499a8337..1b2f4080992 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql @@ -8,6 +8,7 @@ * @tags efficiency * readability * external/cwe/cwe-404 + * external/jsf */ import cpp import Critical.NewDelete diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql index a6bba73ebd4..c16da4309a5 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-81 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql index 47d95e14eca..4624cd29931 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql @@ -8,6 +8,7 @@ * @tags reliability * readability * language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql index 6ea435afe94..4f81c6518c1 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql @@ -4,7 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-85 * @problem.severity warning - * @tags reliability + * @tags maintainability + * reliability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql index a96697f1e5c..90efc3cba0f 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql @@ -3,7 +3,9 @@ * @description A stateful virtual base shall be explicitly declared in each derived class that accesses it. Explicitly declaring a stateful virtual base at each level in a hierarchy (where that base is used), documents that fact that no assumptions can be made with respect to the exclusive use of the data contained within the virtual base. * @kind problem * @id cpp/jsf/av-rule-88-1 - * @problem.severity error + * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql index 0bc3b17177b..bbd39779744 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql @@ -5,7 +5,9 @@ * @problem.severity recommendation * @precision high * @id cpp/undisciplined-multiple-inheritance - * @tags readability + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql index 7e39363e838..53d6b95b011 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql @@ -7,6 +7,7 @@ * @id cpp/inconsistent-virtual-inheritance * @tags maintainability * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql index 1bf0465486a..68b6c7fd506 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql @@ -3,7 +3,9 @@ * @description An inherited nonvirtual function shall not be redefined in a derived class. Such definitions would hide the function in the base class. * @kind problem * @id cpp/jsf/av-rule-94 - * @problem.severity error + * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.ql index a43c7b56a3b..f32fe58f0be 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.ql @@ -7,6 +7,7 @@ * @id cpp/redefined-default-parameter * @tags maintainability * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql index d577b649df8..839625f4d2c 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-96 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql index 455add085d5..02d0f169245 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-97-1 * @problem.severity error + * @tags correctness + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql index 256b1174ccb..781e3c922d3 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql @@ -8,6 +8,7 @@ * @tags reliability * readability * language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql b/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql index 920853145fc..4d4713026f1 100644 --- a/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql +++ b/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql @@ -3,7 +3,10 @@ * @description Namespaces will not be nested more than two levels deep * @kind problem * @id cpp/jsf/av-rule-99 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql b/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql index 2c4037770ba..a88a8f165e9 100644 --- a/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql +++ b/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-104 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql index 22341330150..a92a3d268f8 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql @@ -7,6 +7,7 @@ * @id cpp/function-in-block * @tags maintainability * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql index 1ece9be6fe8..b463e51afa7 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql @@ -3,7 +3,9 @@ * @description Functions with variable number of arguments shall not be used. * @kind problem * @id cpp/jsf/av-rule-108 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql index 16e24b9697b..9afa55ee4ca 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-110 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql index edc3f8c646d..6e6d8004a1c 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql @@ -4,7 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-111 * @problem.severity error - * @tags reliability + * @tags correctness + * reliability + * external/jsf */ import semmle.code.cpp.pointsto.PointsTo diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql index 938e8b3a81e..ca934aa84e1 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql @@ -3,7 +3,9 @@ * @description Functions will have a single exit point. * @kind problem * @id cpp/jsf/av-rule-113 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql index 600d4a6abf0..e4a79d378f5 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql @@ -8,6 +8,7 @@ * @tags reliability * readability * language-features + * external/jsf */ import cpp @@ -38,6 +39,8 @@ predicate functionImperfectlyExtracted(Function f) { exists(CompilerError e | f.getBlock().getLocation().subsumes(e.getLocation())) or exists(ErrorExpr ee | ee.getEnclosingFunction() = f) + or + count(f.getType()) > 1 } from Stmt stmt, string msg, Function f, ControlFlowNode blame diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql index af81266e1d8..2cec08f027b 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-115 * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql index e45afd24880..3e365d28ddf 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql @@ -3,7 +3,9 @@ * @description Functions shall not call themselves, either directly or indirectly (i.e. recursion shall not be allowed). * @kind problem * @id cpp/jsf/av-rule-119 - * @problem.severity error + * @problem.severity recommendation + * @tags resources + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql b/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql index 975489f30f2..bc0a6a4be1d 100644 --- a/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql +++ b/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql @@ -3,7 +3,10 @@ * @description Only valid C++ style comments shall be used. * @kind problem * @id cpp/jsf/av-rule-126 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * documentation + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.14 Comments/AV Rule 127.ql b/cpp/ql/src/jsf/4.14 Comments/AV Rule 127.ql index e8dfa01e54d..663efcc5bcd 100644 --- a/cpp/ql/src/jsf/4.14 Comments/AV Rule 127.ql +++ b/cpp/ql/src/jsf/4.14 Comments/AV Rule 127.ql @@ -3,7 +3,9 @@ * @description Code that is not used (commented out) shall be deleted. * @kind problem * @id cpp/jsf/av-rule-127 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql b/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql index 6de8e990e3e..94026501130 100644 --- a/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql +++ b/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql @@ -3,7 +3,10 @@ * @description Every source file will be documented with an introductory comment that provides information on the file name, its contents, and any program-required information (eg. legal statements, copyright information, etc) * @kind problem * @id cpp/jsf/av-rule-133 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * documentation + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql index d5fb20d4883..b7561398468 100644 --- a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql +++ b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql @@ -5,6 +5,7 @@ * @id cpp/jsf/av-rule-135 * @problem.severity recommendation * @tags maintainability + * external/jsf */ import cpp import Best_Practices.Hiding.Shadowing diff --git a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql index 0a6744aed2c..b1863aad849 100644 --- a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql +++ b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql @@ -3,7 +3,9 @@ * @description Identifiers shall not simultaneously have both internal and external linkage in the same translation unit. * @kind problem * @id cpp/jsf/av-rule-138 - * @problem.severity error + * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql index 1d8a8849ac1..83de729ba60 100644 --- a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql +++ b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql @@ -1,9 +1,11 @@ /** * @name AV Rule 139 - * @description External objects will not be declared in more than one file + * @description External objects will not be declared in more than one file. * @kind problem * @id cpp/jsf/av-rule-139 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql index 7a0e6f58661..0088664dcd8 100644 --- a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql +++ b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql @@ -4,7 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-140 * @problem.severity warning - * @tags portability + * @tags maintainability + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql index 570a3566d4a..4b8cd81eb63 100644 --- a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql +++ b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-142 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql index 595b414ee9b..9bac57b913a 100644 --- a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql +++ b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-143 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql index 858fbf9e123..0388e533650 100644 --- a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql +++ b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql @@ -8,6 +8,7 @@ * @tags reliability * readability * language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql b/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql index 072076080b1..c60c924460b 100644 --- a/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql +++ b/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql @@ -5,6 +5,7 @@ * @id cpp/jsf/av-rule-147 * @problem.severity error * @tags reliability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql b/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql index e76a52ce3cd..11a2e09ba96 100644 --- a/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql +++ b/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql @@ -8,6 +8,7 @@ * @tags maintainability * readability * language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql b/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql index d09fd2de3dc..1485bb67573 100644 --- a/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql +++ b/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql @@ -3,7 +3,9 @@ * @description Octal constants (other than zero) shall not be used. * @kind problem * @id cpp/jsf/av-rule-149 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql b/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql index 542d241721a..eaa41fc002f 100644 --- a/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql +++ b/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql @@ -3,7 +3,9 @@ * @description Hexadecimal constants will be represented using all uppercase letters. * @kind problem * @id cpp/jsf/av-rule-150 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql b/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql index 8411c8ebf3f..b541121139b 100644 --- a/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql +++ b/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql @@ -5,6 +5,7 @@ * @id cpp/jsf/av-rule-151-1 * @problem.severity error * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql b/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql index e4dad7e2e00..5cd0052b455 100644 --- a/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql +++ b/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql @@ -3,7 +3,9 @@ * @description Numeric values in code will not be used; symbolic values will be used instead. * @kind problem * @id cpp/jsf/av-rule-151 - * @problem.severity warning + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql b/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql index d57a9eb79b0..c83d96102a5 100644 --- a/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql +++ b/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql @@ -3,7 +3,10 @@ * @description Multiple variable declarations shall not be allowed on the same line. * @kind problem * @id cpp/jsf/av-rule-152 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql index 7f0298c3558..237ce784cd5 100644 --- a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql +++ b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql @@ -3,7 +3,9 @@ * @description Unions shall not be used. * @kind problem * @id cpp/jsf/av-rule-153 - * @problem.severity error + * @problem.severity recommendation + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql index 247a38130b5..1fe2b836f2d 100644 --- a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql +++ b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql @@ -6,9 +6,11 @@ * @problem.severity warning * @precision low * @id cpp/signed-bit-field - * @tags reliability - * readability + * @tags correctness + * portability + * reliability * language-features + * external/jsf * external/cwe/cwe-190 */ import cpp diff --git a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql index ba48fe3539a..784cc19d109 100644 --- a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql +++ b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-155 * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql index 2dcabc93098..223ba5877d4 100644 --- a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql +++ b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql @@ -4,7 +4,10 @@ * and shall only be accessed via their names. * @kind problem * @id cpp/jsf/av-rule-156 - * @problem.severity error + * @problem.severity warning + * @precision low + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql index 18cbc5118a1..7f99a96fb78 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql @@ -4,7 +4,10 @@ * contain side effects. * @kind problem * @id cpp/jsf/av-rule-157 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql index 6063f45073d..aea14943088 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql @@ -4,7 +4,10 @@ * if the operands contain binary operators. * @kind problem * @id cpp/jsf/av-rule-158 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql index ae3350aeece..eeccef02f38 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql @@ -3,7 +3,9 @@ * @description Operators ||, &&, and unary & shall not be overloaded * @kind problem * @id cpp/jsf/av-rule-159 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * external/jsf */ // See More Effective C++ item 7 // Note: Meyers allows unary & to be overloaded but not comma diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql index e34673b9070..f339291976c 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql @@ -3,7 +3,10 @@ * @description An assignment expression shall be used only as the expression in an expression statement. * @kind problem * @id cpp/jsf/av-rule-160 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql index e9f1fa4f08f..757eb78292e 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql @@ -3,7 +3,9 @@ * @description Signed and unsigned values shall not be mixed in arithmetic or comparison operations. Mixing signed and unsigned values is error prone as it subjects operations to numerous arithmetic conversion and integral promotion rules. * @kind problem * @id cpp/jsf/av-rule-162 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql index d8a5a8930a9..51f970c912e 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql @@ -3,7 +3,9 @@ * @description Unsigned arithmetic shall not be used. * @kind problem * @id cpp/jsf/av-rule-163 - * @problem.severity error + * @problem.severity recommendation + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql index 5531028f466..d10ddfc61d4 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-164 * @problem.severity error + * @precision low + * @tags correctness + * external/jsf */ import cpp @@ -35,7 +38,7 @@ predicate constantValue(Expr e, int value) { predicate violation(BinaryBitwiseOperation op, int lhsBytes, int value) { (op instanceof LShiftExpr or op instanceof RShiftExpr) and constantValue(op.getRightOperand(), value) and - lhsBytes = op.getLeftOperand().getType().getSize() and + lhsBytes = op.getLeftOperand().getExplicitlyConverted().getType().getSize() and (value < 0 or value >= lhsBytes * 8) } diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql index ba2e452eade..4edae501c8a 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql @@ -4,13 +4,16 @@ * @kind problem * @id cpp/jsf/av-rule-165 * @problem.severity warning - * @tags reliability + * @precision low + * @tags correctness + * reliability + * external/jsf */ import cpp // see MISRA Rule 5-3-2 from UnaryMinusExpr ume -where ume.getOperand().getUnderlyingType().(IntegralType).isUnsigned() +where ume.getOperand().getExplicitlyConverted().getUnderlyingType().(IntegralType).isUnsigned() and not ume.getOperand() instanceof Literal select ume, "The unary minus operator should not be applied to an unsigned expression." diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql index 019e52e0e9f..9eea44cf016 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql @@ -7,6 +7,7 @@ * @id cpp/sizeof-side-effect * @tags reliability * correctness + * external/jsf */ import cpp import jsf.lib.section_4_21_Operators.AV_Rule_166 diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql index 6a47217fd1a..d8b0edf0bf8 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql @@ -3,7 +3,10 @@ * @description The comma operator shall not be used. * @kind problem * @id cpp/jsf/av-rule-168 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql index 1cd0a5a5a68..3dbc992773c 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql @@ -3,7 +3,10 @@ * @description More than two levels of pointer indirection shall not be used. * @kind problem * @id cpp/jsf/av-rule-170 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql index a5a282bd280..2ff8d5464c5 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-171 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp import semmle.code.cpp.pointsto.PointsTo diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql index 9bbc4f56388..5f615755478 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql @@ -6,6 +6,8 @@ * @kind problem * @id cpp/jsf/av-rule-173 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql index b9b19ca1236..3662d050c3d 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql @@ -3,7 +3,9 @@ * @description A pointer shall not be compared to NULL or be assigned NULL; use plain 0 instead. * @kind problem * @id cpp/jsf/av-rule-175 - * @problem.severity error + * @problem.severity recommendation + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql index 3b3369dff21..1ddce11dc2b 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-176 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql index 62bb5ac7207..d8738ccc158 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-178 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql index 007f6c9c80a..ea16c751592 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-179 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql index 7f3ecd38c99..a190874796e 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql @@ -4,7 +4,9 @@ * shall not be used. * @kind problem * @id cpp/jsf/av-rule-180 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql index cd32f6f4208..bad480ef016 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-181 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql index 0e5a345c198..cf2844519dd 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-182 * @problem.severity error + * @tags correctness + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql index b72c3803f06..828d655cd3d 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql @@ -5,7 +5,9 @@ * requirement or is necessary for a hardware interface. * @kind problem * @id cpp/jsf/av-rule-184 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql index 5a276d498c7..ad7aef37eb9 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql @@ -4,7 +4,9 @@ * instead of the traditional C-style cast. * @kind problem * @id cpp/jsf/av-rule-185 - * @problem.severity error + * @problem.severity recommendation + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql index 2ee5c35140a..9f56a1ab564 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql @@ -3,7 +3,10 @@ * @description There shall be no unreachable code. * @kind problem * @id cpp/jsf/av-rule-186 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * useless-code + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql index 6033c421a4f..f0435485ce7 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-187 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql index f01c15a9a0e..1c13ac90ef4 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-188 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql index fbf0a1b0b11..79c68166ae3 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql @@ -3,8 +3,10 @@ * @description The goto statement shall not be used. * @kind problem * @id cpp/jsf/av-rule-189 - * @problem.severity error + * @problem.severity warning * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql index 8e794081c2e..19a60dbc8f5 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql @@ -3,7 +3,9 @@ * @description The continue statement shall not be used. * @kind problem * @id cpp/jsf/av-rule-190 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql index 866dbcd2a22..4201256e09c 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql @@ -3,7 +3,9 @@ * @description The break statement shall not be used. * @kind problem * @id cpp/jsf/av-rule-191 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql index 8553d0a005a..b20f82241cc 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-192 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql index 6e589bb0fab..32754f6d20b 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql @@ -4,7 +4,10 @@ * shall be terminated with a break statement. * @kind problem * @id cpp/jsf/av-rule-193 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql index 4aa98eb85e6..82713fa58ea 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql @@ -3,7 +3,9 @@ * @description All switch statements that do not intend to test for every enumeration value shall contain a final default clause. * @kind problem * @id cpp/jsf/av-rule-194 - * @problem.severity error + * @problem.severity warning + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql index 8a8fa4b58e5..318a5879a4d 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-195 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql index b0f2627e655..33eaacee040 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql @@ -7,6 +7,7 @@ * @id cpp/trivial-switch * @tags maintainability * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql index 37fc05b5833..9230255a9a0 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql @@ -5,8 +5,9 @@ * @problem.severity recommendation * @precision high * @id cpp/loop-variable-float - * @tags reliability - * readability + * @tags correctness + * reliability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql index 9b973d40264..5b1058b42d7 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql @@ -5,6 +5,9 @@ * @kind problem * @id cpp/jsf/av-rule-198 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql index 258a6c1e2bf..2cb5e918c44 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql @@ -5,6 +5,9 @@ * @kind problem * @id cpp/jsf/av-rule-199 * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql index cbabf485265..159074279ea 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-200 * @problem.severity warning + * @tags maintainability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql index 060734ab0ec..fa9510681d5 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql @@ -7,6 +7,7 @@ * @id cpp/loop-variable-changed * @tags reliability * readability + * external/jsf */ import cpp import Likely_Bugs.NestedLoopSameVar diff --git a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql index 352993f2c17..ea19a9c4eb2 100644 --- a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql +++ b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-202 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql index d1c53d781ed..132084c0488 100644 --- a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql +++ b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql @@ -4,6 +4,8 @@ * @kind problem * @id cpp/jsf/av-rule-204-1 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql index d2bf1728a76..676e4789244 100644 --- a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql +++ b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql @@ -6,7 +6,10 @@ * condition, or as a part of a chained operation. * @kind problem * @id cpp/jsf/av-rule-204 - * @problem.severity error + * @problem.severity warning + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql index a269959daa2..e468e38a980 100644 --- a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql +++ b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql @@ -3,7 +3,9 @@ * @description The volatile keyword shall not be used unless directly interfacing with hardware. * @kind problem * @id cpp/jsf/av-rule-205 - * @problem.severity error + * @problem.severity warning + * @tags efficiency + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql b/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql index 30254488556..da5c599615a 100644 --- a/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql +++ b/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql @@ -4,7 +4,9 @@ * occur after initialization. * @kind problem * @id cpp/jsf/av-rule-206 - * @problem.severity error + * @problem.severity recommendation + * @tags resources + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql b/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql index 6628234ff0c..c9d4015cb40 100644 --- a/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql +++ b/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-207 * @problem.severity warning + * @tags maintainability + * modularity + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql b/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql index 172f8db58a8..26c2d25b784 100644 --- a/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql +++ b/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql @@ -3,7 +3,9 @@ * @description C++ exceptions shall not be used. * @kind problem * @id cpp/jsf/av-rule-208 - * @problem.severity error + * @problem.severity recommendation + * @tags language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql index 991026f4fa6..964eec6bbe4 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql @@ -5,7 +5,10 @@ * each compiler, and these type names used in the code. * @kind problem * @id cpp/jsf/av-rule-209 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql index c8fb016284d..113c039baec 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql @@ -6,6 +6,9 @@ * @id cpp/jsf/av-rule-210 * @problem.severity error * @precision low + * @tags correctness + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql index 5a05826fa19..5ab7e3598a1 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql @@ -5,6 +5,9 @@ * @kind problem * @id cpp/jsf/av-rule-212 * @problem.severity error + * @tags correctness + * portability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql index 7cdcc1e9e24..45672d33397 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql @@ -4,7 +4,10 @@ * below arithmetic operators, in expressions. * @kind problem * @id cpp/jsf/av-rule-213 - * @problem.severity error + * @problem.severity recommendation + * @tags maintainability + * readability + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql index 9b873f8e716..fb267186095 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql @@ -5,6 +5,8 @@ * @kind problem * @id cpp/jsf/av-rule-214 * @problem.severity error + * @tags correctness + * external/jsf */ import cpp diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql index 201ea073fd9..642feb697a7 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql @@ -4,6 +4,9 @@ * @kind problem * @id cpp/jsf/av-rule-215 * @problem.severity warning + * @tags correctness + * language-features + * external/jsf */ import cpp diff --git a/cpp/ql/src/semmle/code/cpp/PrintAST.qll b/cpp/ql/src/semmle/code/cpp/PrintAST.qll index 3956ac428c1..803758f986c 100644 --- a/cpp/ql/src/semmle/code/cpp/PrintAST.qll +++ b/cpp/ql/src/semmle/code/cpp/PrintAST.qll @@ -59,18 +59,36 @@ private predicate locationSortKeys(Locatable ast, string file, int line, ) } +private Function getEnclosingFunction(Locatable ast) { + result = ast.(Expr).getEnclosingFunction() or + result = ast.(Stmt).getEnclosingFunction() or + result = ast.(Initializer).getExpr().getEnclosingFunction() or + result = ast.(Parameter).getFunction() or + exists(DeclStmt stmt | + stmt.getADeclarationEntry() = ast and + result = stmt.getEnclosingFunction() + ) or + result = ast +} + /** * Most nodes are just a wrapper around `Locatable`, but we do synthesize new * nodes for things like parameter lists and constructor init lists. */ private newtype TPrintASTNode = - TASTNode(Locatable ast) or - TParametersNode(Function func) or + TASTNode(Locatable ast) { + shouldPrintFunction(getEnclosingFunction(ast)) + } or + TParametersNode(Function func) { + shouldPrintFunction(func) + } or TConstructorInitializersNode(Constructor ctor) { - ctor.hasEntryPoint() + ctor.hasEntryPoint() and + shouldPrintFunction(ctor) } or TDestructorDestructionsNode(Destructor dtor) { - dtor.hasEntryPoint() + dtor.hasEntryPoint() and + shouldPrintFunction(dtor) } /** diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index 958a50ebfc8..c93652f4d8a 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -291,7 +291,8 @@ class LocalVariable extends LocalScopeVariable, @localvariable { override Type getType() { localvariables(underlyingElement(this),unresolveElement(result),_) } override Function getFunction() { - exists(DeclStmt s | s.getADeclaration() = this and s.getEnclosingFunction() = result) + exists(DeclStmt s | s.getADeclaration() = this and s.getEnclosingFunction() = result) or + exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result) } } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll index e0a3f542731..0901f74ccd3 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll @@ -78,8 +78,8 @@ predicate isStdLibAllocationExpr(Expr e) */ predicate isAllocationExpr(Expr e) { allocationCall(e) - or e instanceof NewExpr - or e instanceof NewArrayExpr + or + e = any(NewOrNewArrayExpr new | not exists(new.getPlacementPointer())) } /** diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll index ccad37645cb..3d3d3c5cd3f 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll @@ -28,7 +28,8 @@ class Expr extends StmtParent, @expr { result = this.getParent().(Expr).getEnclosingStmt() or result = this.getParent().(Stmt) or exists(Expr other | result = other.getEnclosingStmt() and other.getConversion() = this) or - exists(DeclStmt d, LocalVariable v | d.getADeclaration() = v and v.getInitializer().getExpr() = this and result = d) + exists(DeclStmt d, LocalVariable v | d.getADeclaration() = v and v.getInitializer().getExpr() = this and result = d) or + exists(ConditionDeclExpr cde, LocalVariable v | cde.getVariable() = v and v.getInitializer().getExpr() = this and result = cde.getEnclosingStmt()) } /** Gets the enclosing variable of this expression, if any. */ @@ -663,6 +664,16 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr { * For `new int[5]` the result is `int[5]`. */ abstract Type getAllocatedType(); + + /** + * Gets the pointer `p` if this expression is of the form `new(p) T...`. + * Invocations of this form are non-allocating `new` expressions that may + * call the constructor of `T` but will not allocate memory. + */ + Expr getPlacementPointer() { + isStandardPlacementNewAllocator(this.getAllocator()) and + result = this.getAllocatorCall().getArgument(1) + } } /** @@ -960,3 +971,9 @@ private predicate convparents(Expr child, int idx, Element parent) { child = astChild.getFullyConverted() ) } + +private predicate isStandardPlacementNewAllocator(Function operatorNew) { + operatorNew.getName().matches("operator new%") and + operatorNew.getNumberOfParameters() = 2 and + operatorNew.getParameter(1).getType() instanceof VoidPointerType +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/IRConfiguration.qll b/cpp/ql/src/semmle/code/cpp/ir/IRConfiguration.qll new file mode 100644 index 00000000000..feb510b2ab8 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/IRConfiguration.qll @@ -0,0 +1,19 @@ +import cpp + +private newtype TIRConfiguration = MkIRConfiguration() + +/** + * The query can extend this class to control which functions have IR generated for them. + */ +class IRConfiguration extends TIRConfiguration { + string toString() { + result = "IRConfiguration" + } + + /** + * Holds if IR should be created for function `func`. By default, holds for all functions. + */ + predicate shouldCreateIRForFunction(Function func) { + any() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll index 478e92fac5c..8fb77621426 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll @@ -1,5 +1,40 @@ private import IR import cpp +import semmle.code.cpp.ir.IRConfiguration + +private newtype TPrintIRConfiguration = MkPrintIRConfiguration() + +/** + * The query can extend this class to control which functions are printed. + */ +class PrintIRConfiguration extends TPrintIRConfiguration { + string toString() { + result = "PrintIRConfiguration" + } + + /** + * Holds if the IR for `func` should be printed. By default, holds for all + * functions. + */ + predicate shouldPrintFunction(Function func) { + any() + } +} + +private predicate shouldPrintFunction(Function func) { + exists(PrintIRConfiguration config | + config.shouldPrintFunction(func) + ) +} + +/** + * Override of `IRConfiguration` to only create IR for the functions that are to be dumped. + */ +private class FilteredIRConfiguration extends IRConfiguration { + override predicate shouldCreateIRForFunction(Function func) { + shouldPrintFunction(func) + } +} private string getAdditionalInstructionProperty(Instruction instr, string key) { exists(IRPropertyProvider provider | @@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) { } private newtype TPrintableIRNode = - TPrintableFunctionIR(FunctionIR funcIR) or - TPrintableIRBlock(IRBlock block) or - TPrintableInstruction(Instruction instr) + TPrintableFunctionIR(FunctionIR funcIR) { + shouldPrintFunction(funcIR.getFunction()) + } or + TPrintableIRBlock(IRBlock block) { + shouldPrintFunction(block.getFunction()) + } or + TPrintableInstruction(Instruction instr) { + shouldPrintFunction(instr.getFunction()) + } /** * A node to be emitted in the IR graph. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll index 478e92fac5c..8fb77621426 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll @@ -1,5 +1,40 @@ private import IR import cpp +import semmle.code.cpp.ir.IRConfiguration + +private newtype TPrintIRConfiguration = MkPrintIRConfiguration() + +/** + * The query can extend this class to control which functions are printed. + */ +class PrintIRConfiguration extends TPrintIRConfiguration { + string toString() { + result = "PrintIRConfiguration" + } + + /** + * Holds if the IR for `func` should be printed. By default, holds for all + * functions. + */ + predicate shouldPrintFunction(Function func) { + any() + } +} + +private predicate shouldPrintFunction(Function func) { + exists(PrintIRConfiguration config | + config.shouldPrintFunction(func) + ) +} + +/** + * Override of `IRConfiguration` to only create IR for the functions that are to be dumped. + */ +private class FilteredIRConfiguration extends IRConfiguration { + override predicate shouldCreateIRForFunction(Function func) { + shouldPrintFunction(func) + } +} private string getAdditionalInstructionProperty(Instruction instr, string key) { exists(IRPropertyProvider provider | @@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) { } private newtype TPrintableIRNode = - TPrintableFunctionIR(FunctionIR funcIR) or - TPrintableIRBlock(IRBlock block) or - TPrintableInstruction(Instruction instr) + TPrintableFunctionIR(FunctionIR funcIR) { + shouldPrintFunction(funcIR.getFunction()) + } or + TPrintableIRBlock(IRBlock block) { + shouldPrintFunction(block.getFunction()) + } or + TPrintableInstruction(Instruction instr) { + shouldPrintFunction(instr.getFunction()) + } /** * A node to be emitted in the IR graph. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index cbddf84c890..da9a3f1c2dd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -10,8 +10,7 @@ private import TranslatedInitialization * Gets the `TranslatedDeclarationEntry` that represents the declaration * `entry`. */ -TranslatedDeclarationEntry getTranslatedDeclarationEntry( - DeclarationEntry entry) { +TranslatedDeclarationEntry getTranslatedDeclarationEntry(DeclarationEntry entry) { result.getAST() = entry } @@ -21,8 +20,7 @@ TranslatedDeclarationEntry getTranslatedDeclarationEntry( * it can also be the declaration of a static local variable, an extern * variable, or an extern function. */ -abstract class TranslatedDeclarationEntry extends TranslatedElement, - TTranslatedDeclarationEntry { +abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslatedDeclarationEntry { DeclarationEntry entry; TranslatedDeclarationEntry() { @@ -50,14 +48,13 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, * for declarations other than local variables. Since these have no semantic * effect, they are translated as `NoOp`. */ -class TranslatedNonVariableDeclaration extends - TranslatedDeclarationEntry { - TranslatedNonVariableDeclaration() { +class TranslatedNonVariableDeclarationEntry extends TranslatedDeclarationEntry { + TranslatedNonVariableDeclarationEntry() { not entry.getDeclaration() instanceof LocalVariable } override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + Type resultType, boolean isGLValue) { opcode instanceof Opcode::NoOp and tag = OnlyInstructionTag() and resultType instanceof VoidType and @@ -88,98 +85,11 @@ class TranslatedNonVariableDeclaration extends * Represents the IR translation of the declaration of a local variable, * including its initialization, if any. */ -abstract class TranslatedVariableDeclaration extends - TranslatedDeclarationEntry { - LocalVariable var; - - TranslatedVariableDeclaration() { - entry.getDeclaration() = var - } -} - -/** - * Represents the IR translation of a local variable with no initializer. The - * generated IR stores into the variable using an `Uninitialized` instruction, - * rather than a `Store`. - */ -class TranslatedUninitializedVariable extends - TranslatedVariableDeclaration { - TranslatedUninitializedVariable() { - not exists(Initializer init | - init.getDeclaration() = var - ) - } - - override TranslatedElement getChild(int id) { - none() - } - - override Instruction getFirstInstruction() { - result = getInstruction(InitializerVariableAddressTag()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - ( - tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = var.getType().getUnspecifiedType() and - isGLValue = true - ) or - ( - tag = InitializerStoreTag() and - opcode instanceof Opcode::Uninitialized and - resultType = var.getType().getUnspecifiedType() and - isGLValue = false - ) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - kind instanceof GotoEdge and - ( - ( - tag = InitializerVariableAddressTag() and - result = getInstruction(InitializerStoreTag()) - ) or - ( - tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = InitializerStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) - ) - ) - } - - override IRVariable getInstructionVariable(InstructionTag tag) { - tag = InitializerVariableAddressTag() and - result = getIRUserVariable(var.getFunction(), var) - } -} - -/** - * Represents the IR translation of a local variable with an initializer. - */ -class TranslatedInitializedVariable extends - TranslatedVariableDeclaration, InitializationContext { - Initializer init; - - TranslatedInitializedVariable() { - init.getDeclaration() = var - } +abstract class TranslatedVariableDeclaration extends TranslatedElement, InitializationContext { + /** + * Gets the local variable being declared. + */ + abstract LocalVariable getVariable(); override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() @@ -190,18 +100,41 @@ class TranslatedInitializedVariable extends } override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = var.getType().getUnspecifiedType() and - isGLValue = true + Type resultType, boolean isGLValue) { + ( + tag = InitializerVariableAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = getVariable().getType().getUnspecifiedType() and + isGLValue = true + ) or + ( + hasUninitializedInstruction() and + tag = InitializerStoreTag() and + opcode instanceof Opcode::Uninitialized and + resultType = getVariable().getType().getUnspecifiedType() and + isGLValue = false + ) } override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = InitializerVariableAddressTag() and - result = getInitialization().getFirstInstruction() and - kind instanceof GotoEdge + EdgeKind kind) { + ( + tag = InitializerVariableAddressTag() and + kind instanceof GotoEdge and + if hasUninitializedInstruction() then + result = getInstruction(InitializerStoreTag()) + else + result = getInitialization().getFirstInstruction() + ) or + ( + hasUninitializedInstruction() and + kind instanceof GotoEdge and + tag = InitializerStoreTag() and + ( + result = getInitialization().getFirstInstruction() or + not exists(getInitialization()) and result = getParent().getChildSuccessor(this) + ) + ) } override Instruction getChildSuccessor(TranslatedElement child) { @@ -210,7 +143,14 @@ class TranslatedInitializedVariable extends override IRVariable getInstructionVariable(InstructionTag tag) { tag = InitializerVariableAddressTag() and - result = getIRUserVariable(var.getFunction(), var) + result = getIRUserVariable(getFunction(), getVariable()) + } + + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + hasUninitializedInstruction() and + tag = InitializerStoreTag() and + operandTag instanceof AddressOperandTag and + result = getInstruction(InitializerVariableAddressTag()) } override Instruction getTargetAddress() { @@ -218,10 +158,67 @@ class TranslatedInitializedVariable extends } override Type getTargetType() { - result = var.getType().getUnspecifiedType() + result = getVariable().getType().getUnspecifiedType() } private TranslatedInitialization getInitialization() { - result = getTranslatedInitialization(init.getExpr().getFullyConverted()) + result = getTranslatedInitialization(getVariable().getInitializer().getExpr().getFullyConverted()) + } + + private predicate hasUninitializedInstruction() { + not exists(getInitialization()) or + getInitialization() instanceof TranslatedListInitialization + } +} + +/** + * Represents the IR translation of a local variable declaration within a declaration statement. + */ +class TranslatedVariableDeclarationEntry extends TranslatedVariableDeclaration, + TranslatedDeclarationEntry { + LocalVariable var; + + TranslatedVariableDeclarationEntry() { + var = entry.getDeclaration() + } + + override LocalVariable getVariable() { + result = var + } +} + +TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) { + result.getAST() = expr +} + +/** + * Represents the IR translation of the declaration portion of a `ConditionDeclExpr`, which + * represents the variable declared in code such as: + * ``` + * if (int* p = &x) { + * } + * ``` + */ +class TranslatedConditionDecl extends TranslatedVariableDeclaration, TTranslatedConditionDecl { + ConditionDeclExpr conditionDeclExpr; + + TranslatedConditionDecl() { + this = TTranslatedConditionDecl(conditionDeclExpr) + } + + override string toString() { + result = "decl: " + conditionDeclExpr.toString() + } + + override Locatable getAST() { + result = conditionDeclExpr + } + + override Function getFunction() { + result = conditionDeclExpr.getEnclosingFunction() + } + + override LocalVariable getVariable() { + result = conditionDeclExpr.getVariable() } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 1be620d1206..b701c1a3f5d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -1,5 +1,7 @@ import cpp +import cpp import semmle.code.cpp.ir.implementation.raw.IR +private import semmle.code.cpp.ir.IRConfiguration private import semmle.code.cpp.ir.implementation.Opcode private import semmle.code.cpp.ir.internal.OperandTag private import semmle.code.cpp.ir.internal.TempVariableTag @@ -83,7 +85,8 @@ private predicate ignoreExprOnly(Expr expr) { // Ignore the allocator call, because we always synthesize it. Don't ignore // its arguments, though, because we use them as part of the synthesis. newExpr.getAllocatorCall() = expr - ) + ) or + not translateFunction(expr.getEnclosingFunction()) } /** @@ -94,6 +97,49 @@ private predicate ignoreExpr(Expr expr) { ignoreExprAndDescendants(getRealParent*(expr)) } +/** + * Holds if `func` contains an AST that cannot be translated into IR. This is mostly used to work + * around extractor bugs. Once the relevant extractor bugs are fixed, this predicate can be removed. + */ +private predicate isInvalidFunction(Function func) { + exists(Literal literal | + // Constructor field inits within a compiler-generated copy constructor have a source expression + // that is a `Literal` with no value. + literal = func.(Constructor).getAnInitializer().(ConstructorFieldInit).getExpr() and + not exists(literal.getValue()) + ) or + exists(ThisExpr thisExpr | + // An instantiation of a member function template is not treated as a `MemberFunction` if it has + // only non-type template arguments. + thisExpr.getEnclosingFunction() = func and + not func instanceof MemberFunction + ) or + exists(Expr expr | + // Expression missing a type. + expr.getEnclosingFunction() = func and + not exists(expr.getType()) + ) +} + +/** + * Holds if `func` should be translated to IR. + */ +private predicate translateFunction(Function func) { + not func.isFromUninstantiatedTemplate(_) and + func.hasEntryPoint() and + not isInvalidFunction(func) and + exists(IRConfiguration config | + config.shouldCreateIRForFunction(func) + ) +} + +/** + * Holds if `stmt` should be translated to IR. + */ +private predicate translateStmt(Stmt stmt) { + translateFunction(stmt.getEnclosingFunction()) +} + /** * Holds if `expr` is most naturally evaluated as control flow, rather than as * a value. @@ -236,7 +282,7 @@ newtype TTranslatedElement = } or // The initialization of a field via a member of an initializer list. TTranslatedExplicitFieldInitialization(Expr ast, Field field, - Expr expr) { + Expr expr) { exists(ClassAggregateLiteral initList | not ignoreExpr(initList) and ast = initList and @@ -260,14 +306,14 @@ newtype TTranslatedElement = } or // The initialization of an array element via a member of an initializer list. TTranslatedExplicitElementInitialization( - ArrayAggregateLiteral initList, int elementIndex) { + ArrayAggregateLiteral initList, int elementIndex) { not ignoreExpr(initList) and exists(initList.getElementExpr(elementIndex)) } or // The value initialization of a range of array elements that were omitted // from an initializer list. TTranslatedElementValueInitialization(ArrayAggregateLiteral initList, - int elementIndex, int elementCount) { + int elementIndex, int elementCount) { not ignoreExpr(initList) and isFirstValueInitializedElementInRange(initList, elementIndex) and elementCount = @@ -287,28 +333,35 @@ newtype TTranslatedElement = not ignoreExpr(destruction) } or // A statement - TTranslatedStmt(Stmt stmt) or + TTranslatedStmt(Stmt stmt) { + translateStmt(stmt) + } or // A function TTranslatedFunction(Function func) { - func.hasEntryPoint() and - not func.isFromUninstantiatedTemplate(_) + translateFunction(func) } or // A constructor init list TTranslatedConstructorInitList(Function func) { - func.hasEntryPoint() + translateFunction(func) } or // A destructor destruction list TTranslatedDestructorDestructionList(Function func) { - func.hasEntryPoint() + translateFunction(func) } or // A function parameter TTranslatedParameter(Parameter param) { - param.getFunction().hasEntryPoint() or - exists(param.getCatchBlock()) + exists(Function func | + ( + func = param.getFunction() or + func = param.getCatchBlock().getEnclosingFunction() + ) and + translateFunction(func) + ) } or // A local declaration TTranslatedDeclarationEntry(DeclarationEntry entry) { exists(DeclStmt declStmt | + translateStmt(declStmt) and declStmt.getADeclarationEntry() = entry ) } or @@ -319,6 +372,10 @@ newtype TTranslatedElement = // An allocation size for a `new` or `new[]` expression TTranslatedAllocationSize(NewOrNewArrayExpr newExpr) { not ignoreExpr(newExpr) + } or + // The declaration/initialization part of a `ConditionDeclExpr` + TTranslatedConditionDecl(ConditionDeclExpr expr) { + not ignoreExpr(expr) } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index de70d44d17c..175f710f265 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -4,6 +4,7 @@ private import semmle.code.cpp.ir.internal.OperandTag private import semmle.code.cpp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedCondition +private import TranslatedDeclarationEntry private import TranslatedElement private import TranslatedFunction private import TranslatedInitialization @@ -2914,3 +2915,57 @@ class TranslatedNewArrayExpr extends TranslatedNewOrNewArrayExpr { none() } } + +/** + * The IR translation of a `ConditionDeclExpr`, which represents the value of the declared variable + * after conversion to `bool` in code such as: + * ``` + * if (int* p = &x) { + * } + * ``` + */ +class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr { + ConditionDeclExpr condDeclExpr; + + TranslatedConditionDeclExpr() { + condDeclExpr = expr + } + + override final Instruction getFirstInstruction() { + result = getDecl().getFirstInstruction() + } + + override final TranslatedElement getChild(int id) { + id = 0 and result = getDecl() or + id = 1 and result = getConditionExpr() + } + + override Instruction getResult() { + result = getConditionExpr().getResult() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + none() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + ( + child = getDecl() and + result = getConditionExpr().getFirstInstruction() + ) or + child = getConditionExpr() and result = getParent().getChildSuccessor(this) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, + boolean isGLValue) { + none() + } + + private TranslatedConditionDecl getDecl() { + result = getTranslatedConditionDecl(condDeclExpr) + } + + private TranslatedExpr getConditionExpr() { + result = getTranslatedExpr(condDeclExpr.getExpr().getFullyConverted()) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll index 478e92fac5c..8fb77621426 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll @@ -1,5 +1,40 @@ private import IR import cpp +import semmle.code.cpp.ir.IRConfiguration + +private newtype TPrintIRConfiguration = MkPrintIRConfiguration() + +/** + * The query can extend this class to control which functions are printed. + */ +class PrintIRConfiguration extends TPrintIRConfiguration { + string toString() { + result = "PrintIRConfiguration" + } + + /** + * Holds if the IR for `func` should be printed. By default, holds for all + * functions. + */ + predicate shouldPrintFunction(Function func) { + any() + } +} + +private predicate shouldPrintFunction(Function func) { + exists(PrintIRConfiguration config | + config.shouldPrintFunction(func) + ) +} + +/** + * Override of `IRConfiguration` to only create IR for the functions that are to be dumped. + */ +private class FilteredIRConfiguration extends IRConfiguration { + override predicate shouldCreateIRForFunction(Function func) { + shouldPrintFunction(func) + } +} private string getAdditionalInstructionProperty(Instruction instr, string key) { exists(IRPropertyProvider provider | @@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) { } private newtype TPrintableIRNode = - TPrintableFunctionIR(FunctionIR funcIR) or - TPrintableIRBlock(IRBlock block) or - TPrintableInstruction(Instruction instr) + TPrintableFunctionIR(FunctionIR funcIR) { + shouldPrintFunction(funcIR.getFunction()) + } or + TPrintableIRBlock(IRBlock block) { + shouldPrintFunction(block.getFunction()) + } or + TPrintableInstruction(Instruction instr) { + shouldPrintFunction(instr.getFunction()) + } /** * A node to be emitted in the IR graph. diff --git a/cpp/ql/test/library-tests/allocators/allocators.cpp b/cpp/ql/test/library-tests/allocators/allocators.cpp index 5f0a535e7f3..4b5775ab352 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.cpp +++ b/cpp/ql/test/library-tests/allocators/allocators.cpp @@ -109,3 +109,31 @@ void TestFailedInit(int n) { new(1.0f) FailedInitOveraligned(); new(1.0f) FailedInitOveraligned[10]; } + +// --- non-allocating placement new --- + +namespace std { + typedef unsigned long size_t; + struct nothrow_t {}; + extern const nothrow_t nothrow; +} + +void* operator new (std::size_t size, void* ptr) noexcept; +void* operator new[](std::size_t size, void* ptr) noexcept; +void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; + +int overloadedNew() { + char buf[sizeof(int)]; + + new(&buf[0]) int(5); + int five = *(int*)buf; + + new(buf) int[1]; + *(int*)buf = 4; + + new(std::nothrow) int(3); // memory leak + new(std::nothrow) int[2]; // memory leak + + return five; +} diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index 586b82c8664..5802b13f4e9 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -8,6 +8,8 @@ newExprs | allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned | | allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | | | allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned | +| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | | +| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | | newArrayExprs | allocators.cpp:68:3:68:12 | new[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | | allocators.cpp:69:3:69:18 | new[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | @@ -16,6 +18,8 @@ newArrayExprs | allocators.cpp:72:3:72:16 | new[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | | allocators.cpp:108:3:108:19 | new[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | | allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | +| allocators.cpp:132:3:132:17 | new[] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | +| allocators.cpp:136:3:136:26 | new[] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | newExprDeallocators | allocators.cpp:52:3:52:14 | new | String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:53:3:53:27 | new | String | operator delete(void *, float) -> void | 8 | 8 | | diff --git a/cpp/ql/test/library-tests/allocators/placement.expected b/cpp/ql/test/library-tests/allocators/placement.expected new file mode 100644 index 00000000000..5755e349eb3 --- /dev/null +++ b/cpp/ql/test/library-tests/allocators/placement.expected @@ -0,0 +1,2 @@ +| allocators.cpp:129:3:129:21 | new | allocators.cpp:129:7:129:13 | & ... | +| allocators.cpp:132:3:132:17 | new[] | allocators.cpp:132:7:132:9 | buf | diff --git a/cpp/ql/test/library-tests/allocators/placement.ql b/cpp/ql/test/library-tests/allocators/placement.ql new file mode 100644 index 00000000000..a632c3c5afe --- /dev/null +++ b/cpp/ql/test/library-tests/allocators/placement.ql @@ -0,0 +1,4 @@ +import cpp + +from NewOrNewArrayExpr new +select new, new.getPlacementPointer() as placement diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 8c098f79e11..b01c82d135d 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -38,6 +38,142 @@ #-----| Type = unsigned long #-----| 1: p#1 #-----| Type = align_val_t +bad_asts.cpp: +# 5| Bad::S::operator=(S &&) -> S & +# 5| params: +#-----| 0: p#0 +#-----| Type = S && +# 5| Bad::S::operator=(const S &) -> S & +# 5| params: +#-----| 0: p#0 +#-----| Type = const S & +# 9| Bad::S::MemberFunction(int) -> int +# 9| params: +# 9| 0: y +# 9| Type = int +# 9| body: { ... } +# 10| 0: return ... +# 10| 0: ... + ... +# 10| Type = int +# 10| ValueCategory = prvalue +# 10| 0: ... + ... +# 10| Type = int +# 10| ValueCategory = prvalue +# 10| 0: Unknown literal +# 10| Type = int +# 10| ValueCategory = prvalue +# 10| 1: x +# 10| Type = int +# 10| ValueCategory = prvalue(load) +#-----| -1: this +#-----| Type = S * +#-----| ValueCategory = prvalue(load) +# 10| 1: y +# 10| Type = int +# 10| ValueCategory = prvalue(load) +# 9| MemberFunction(int) -> int +# 9| params: +# 9| 0: y +# 9| Type = int +# 9| body: { ... } +# 10| 0: return ... +# 10| 0: ... + ... +# 10| Type = int +# 10| ValueCategory = prvalue +# 10| 0: ... + ... +# 10| Type = int +# 10| ValueCategory = prvalue +# 10| 0: 6 +# 10| Type = int +# 10| Value = 6 +# 10| ValueCategory = prvalue +# 10| 1: x +# 10| Type = int +# 10| ValueCategory = prvalue(load) +#-----| -1: this +#-----| Type = S * +#-----| ValueCategory = prvalue(load) +# 10| 1: y +# 10| Type = int +# 10| ValueCategory = prvalue(load) +# 14| Bad::CallBadMemberFunction() -> void +# 14| params: +# 14| body: { ... } +# 15| 0: declaration +# 15| 0: definition of s +# 15| Type = S +# 15| init: initializer for s +# 15| expr: {...} +# 15| Type = S +# 15| ValueCategory = prvalue +# 16| 1: ExprStmt +# 16| 0: call to MemberFunction +# 16| Type = int +# 16| ValueCategory = prvalue +# 16| -1: s +# 16| Type = S +# 16| ValueCategory = lvalue +# 16| 0: 1 +# 16| Type = int +# 16| Value = 1 +# 16| ValueCategory = prvalue +# 17| 2: return ... +# 19| Bad::Point::Point(Point &&) -> void +# 19| params: +#-----| 0: p#0 +#-----| Type = Point && +# 19| Bad::Point::Point(const Point &) -> void +# 19| params: +#-----| 0: p#0 +#-----| Type = const Point & +# 19| initializations: +# 19| 0: constructor init of field x +# 19| Type = int +# 19| ValueCategory = prvalue +# 19| 0: Unknown literal +# 19| Type = int +# 19| ValueCategory = prvalue +# 19| 1: constructor init of field y +# 19| Type = int +# 19| ValueCategory = prvalue +# 19| 0: Unknown literal +# 19| Type = int +# 19| ValueCategory = prvalue +# 19| body: { ... } +# 19| 0: return ... +# 19| Bad::Point::operator=(Point &&) -> Point & +# 19| params: +#-----| 0: p#0 +#-----| Type = Point && +# 19| Bad::Point::operator=(const Point &) -> Point & +# 19| params: +#-----| 0: p#0 +#-----| Type = const Point & +# 22| Bad::Point::Point() -> void +# 22| params: +# 22| initializations: +# 22| body: { ... } +# 23| 0: return ... +# 26| Bad::CallCopyConstructor(const Point &) -> void +# 26| params: +# 26| 0: a +# 26| Type = const Point & +# 26| body: { ... } +# 27| 0: declaration +# 27| 0: definition of b +# 27| Type = Point +# 27| init: initializer for b +# 27| expr: (Point)... +# 27| Conversion = glvalue conversion +# 27| Type = Point +# 27| ValueCategory = prvalue(load) +# 27| expr: (reference dereference) +# 27| Type = const Point +# 27| ValueCategory = lvalue +# 27| expr: a +# 27| Type = const Point & +# 27| ValueCategory = prvalue(load) +# 28| 1: return ... ir.cpp: # 1| Constants() -> void # 1| params: @@ -6339,3 +6475,119 @@ ir.cpp: # 963| Type = int # 963| Value = 900 # 963| ValueCategory = prvalue +# 966| IfStmtWithDeclaration(int, int) -> void +# 966| params: +# 966| 0: x +# 966| Type = int +# 966| 1: y +# 966| Type = int +# 966| body: { ... } +# 967| 0: if (...) ... +# 967| 0: (condition decl) +# 967| Type = bool +# 967| ValueCategory = prvalue +# 967| 0: b +# 967| Type = bool +# 967| ValueCategory = prvalue(load) +# 967| 1: { ... } +# 968| 0: ExprStmt +# 968| 0: ... = ... +# 968| Type = int +# 968| ValueCategory = lvalue +# 968| 0: x +# 968| Type = int +# 968| ValueCategory = lvalue +# 968| 1: 5 +# 968| Type = int +# 968| Value = 5 +# 968| ValueCategory = prvalue +# 970| 2: if (...) ... +# 970| 0: (condition decl) +# 970| Type = bool +# 970| ValueCategory = prvalue +# 970| 0: (bool)... +# 970| Conversion = conversion to bool +# 970| Type = bool +# 970| ValueCategory = prvalue +# 970| expr: z +# 970| Type = int +# 970| ValueCategory = prvalue(load) +# 970| 1: { ... } +# 971| 0: ExprStmt +# 971| 0: ... = ... +# 971| Type = int +# 971| ValueCategory = lvalue +# 971| 0: y +# 971| Type = int +# 971| ValueCategory = lvalue +# 971| 1: 7 +# 971| Type = int +# 971| Value = 7 +# 971| ValueCategory = prvalue +# 973| 2: if (...) ... +# 973| 0: (condition decl) +# 973| Type = bool +# 973| ValueCategory = prvalue +# 973| 0: (bool)... +# 973| Conversion = conversion to bool +# 973| Type = bool +# 973| ValueCategory = prvalue +# 973| expr: p +# 973| Type = int * +# 973| ValueCategory = prvalue(load) +# 973| 1: { ... } +# 974| 0: ExprStmt +# 974| 0: ... = ... +# 974| Type = int +# 974| ValueCategory = lvalue +# 974| 0: * ... +# 974| Type = int +# 974| ValueCategory = lvalue +# 974| 0: p +# 974| Type = int * +# 974| ValueCategory = prvalue(load) +# 974| 1: 2 +# 974| Type = int +# 974| Value = 2 +# 974| ValueCategory = prvalue +# 976| 1: return ... +# 978| WhileStmtWithDeclaration(int, int) -> void +# 978| params: +# 978| 0: x +# 978| Type = int +# 978| 1: y +# 978| Type = int +# 978| body: { ... } +# 979| 0: while (...) ... +# 979| 0: (condition decl) +# 979| Type = bool +# 979| ValueCategory = prvalue +# 979| 0: b +# 979| Type = bool +# 979| ValueCategory = prvalue(load) +# 979| 1: { ... } +# 981| 1: while (...) ... +# 981| 0: (condition decl) +# 981| Type = bool +# 981| ValueCategory = prvalue +# 981| 0: (bool)... +# 981| Conversion = conversion to bool +# 981| Type = bool +# 981| ValueCategory = prvalue +# 981| expr: z +# 981| Type = int +# 981| ValueCategory = prvalue(load) +# 981| 1: { ... } +# 983| 2: while (...) ... +# 983| 0: (condition decl) +# 983| Type = bool +# 983| ValueCategory = prvalue +# 983| 0: (bool)... +# 983| Conversion = conversion to bool +# 983| Type = bool +# 983| ValueCategory = prvalue +# 983| expr: p +# 983| Type = int * +# 983| ValueCategory = prvalue(load) +# 983| 1: { ... } +# 985| 3: return ... diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected index 5fbbec2afb7..ab7f7ae43cb 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected @@ -1,3 +1,49 @@ +bad_asts.cpp: +# 14| Bad::CallBadMemberFunction() -> void +# 14| Block 0 +# 14| v0_0(void) = EnterFunction : +# 14| mu0_1(unknown) = UnmodeledDefinition : +# 15| r0_2(glval) = VariableAddress[s] : +# 15| mu0_3(S) = Uninitialized : r0_2 +# 15| r0_4(glval) = FieldAddress[x] : r0_2 +# 15| r0_5(int) = Constant[0] : +# 15| mu0_6(int) = Store : r0_4, r0_5 +# 16| r0_7(glval) = VariableAddress[s] : +# 16| r0_8(glval) = FunctionAddress[MemberFunction] : +# 16| r0_9(int) = Constant[1] : +# 16| r0_10(int) = Call : r0_8, this:r0_7, r0_9 +# 17| v0_11(void) = NoOp : +# 14| v0_12(void) = ReturnVoid : +# 14| v0_13(void) = UnmodeledUse : mu* +# 14| v0_14(void) = ExitFunction : + +# 22| Bad::Point::Point() -> void +# 22| Block 0 +# 22| v0_0(void) = EnterFunction : +# 22| mu0_1(unknown) = UnmodeledDefinition : +# 22| r0_2(glval) = InitializeThis : +# 23| v0_3(void) = NoOp : +# 22| v0_4(void) = ReturnVoid : +# 22| v0_5(void) = UnmodeledUse : mu* +# 22| v0_6(void) = ExitFunction : + +# 26| Bad::CallCopyConstructor(const Point &) -> void +# 26| Block 0 +# 26| v0_0(void) = EnterFunction : +# 26| mu0_1(unknown) = UnmodeledDefinition : +# 26| r0_2(glval) = VariableAddress[a] : +# 26| m0_3(Point &) = InitializeParameter[a] : r0_2 +# 27| r0_4(glval) = VariableAddress[b] : +# 27| r0_5(glval) = VariableAddress[a] : +# 27| r0_6(Point &) = Load : r0_5, m0_3 +# 27| r0_7(glval) = Convert : r0_6 +# 27| r0_8(Point) = Load : r0_7, mu0_1 +# 27| m0_9(Point) = Store : r0_4, r0_8 +# 28| v0_10(void) = NoOp : +# 26| v0_11(void) = ReturnVoid : +# 26| v0_12(void) = UnmodeledUse : mu* +# 26| v0_13(void) = ExitFunction : + ir.cpp: # 1| Constants() -> void # 1| Block 0 @@ -2152,40 +2198,43 @@ ir.cpp: # 503| r0_4(glval) = VariableAddress[f] : # 503| m0_5(float) = InitializeParameter[f] : r0_4 # 504| r0_6(glval) = VariableAddress[pt1] : -# 504| r0_7(glval) = FieldAddress[x] : r0_6 -# 504| r0_8(glval) = VariableAddress[x] : -# 504| r0_9(int) = Load : r0_8, m0_3 -# 504| m0_10(int) = Store : r0_7, r0_9 -# 504| r0_11(glval) = FieldAddress[y] : r0_6 -# 504| r0_12(glval) = VariableAddress[f] : -# 504| r0_13(float) = Load : r0_12, m0_5 -# 504| r0_14(int) = Convert : r0_13 -# 504| mu0_15(int) = Store : r0_11, r0_14 -# 505| r0_16(glval) = VariableAddress[pt2] : -# 505| r0_17(glval) = FieldAddress[x] : r0_16 -# 505| r0_18(glval) = VariableAddress[x] : -# 505| r0_19(int) = Load : r0_18, m0_3 -# 505| m0_20(int) = Store : r0_17, r0_19 -# 505| r0_21(glval) = FieldAddress[y] : r0_16 -# 505| r0_22(int) = Constant[0] : -# 505| mu0_23(int) = Store : r0_21, r0_22 -# 506| r0_24(glval) = VariableAddress[pt3] : -# 506| r0_25(glval) = FieldAddress[x] : r0_24 -# 506| r0_26(int) = Constant[0] : -# 506| m0_27(int) = Store : r0_25, r0_26 -# 506| r0_28(glval) = FieldAddress[y] : r0_24 +# 504| m0_7(Point) = Uninitialized : r0_6 +# 504| r0_8(glval) = FieldAddress[x] : r0_6 +# 504| r0_9(glval) = VariableAddress[x] : +# 504| r0_10(int) = Load : r0_9, m0_3 +# 504| m0_11(int) = Store : r0_8, r0_10 +# 504| r0_12(glval) = FieldAddress[y] : r0_6 +# 504| r0_13(glval) = VariableAddress[f] : +# 504| r0_14(float) = Load : r0_13, m0_5 +# 504| r0_15(int) = Convert : r0_14 +# 504| mu0_16(int) = Store : r0_12, r0_15 +# 505| r0_17(glval) = VariableAddress[pt2] : +# 505| m0_18(Point) = Uninitialized : r0_17 +# 505| r0_19(glval) = FieldAddress[x] : r0_17 +# 505| r0_20(glval) = VariableAddress[x] : +# 505| r0_21(int) = Load : r0_20, m0_3 +# 505| m0_22(int) = Store : r0_19, r0_21 +# 505| r0_23(glval) = FieldAddress[y] : r0_17 +# 505| r0_24(int) = Constant[0] : +# 505| mu0_25(int) = Store : r0_23, r0_24 +# 506| r0_26(glval) = VariableAddress[pt3] : +# 506| m0_27(Point) = Uninitialized : r0_26 +# 506| r0_28(glval) = FieldAddress[x] : r0_26 # 506| r0_29(int) = Constant[0] : -# 506| mu0_30(int) = Store : r0_28, r0_29 -# 508| r0_31(glval) = VariableAddress[x1] : -# 508| r0_32(int) = Constant[1] : -# 508| m0_33(int) = Store : r0_31, r0_32 -# 509| r0_34(glval) = VariableAddress[x2] : -# 509| r0_35(int) = Constant[0] : -# 509| m0_36(int) = Store : r0_34, r0_35 -# 510| v0_37(void) = NoOp : -# 503| v0_38(void) = ReturnVoid : -# 503| v0_39(void) = UnmodeledUse : mu* -# 503| v0_40(void) = ExitFunction : +# 506| m0_30(int) = Store : r0_28, r0_29 +# 506| r0_31(glval) = FieldAddress[y] : r0_26 +# 506| r0_32(int) = Constant[0] : +# 506| mu0_33(int) = Store : r0_31, r0_32 +# 508| r0_34(glval) = VariableAddress[x1] : +# 508| r0_35(int) = Constant[1] : +# 508| m0_36(int) = Store : r0_34, r0_35 +# 509| r0_37(glval) = VariableAddress[x2] : +# 509| r0_38(int) = Constant[0] : +# 509| m0_39(int) = Store : r0_37, r0_38 +# 510| v0_40(void) = NoOp : +# 503| v0_41(void) = ReturnVoid : +# 503| v0_42(void) = UnmodeledUse : mu* +# 503| v0_43(void) = ExitFunction : # 512| NestedInitList(int, float) -> void # 512| Block 0 @@ -2196,68 +2245,72 @@ ir.cpp: # 512| r0_4(glval) = VariableAddress[f] : # 512| m0_5(float) = InitializeParameter[f] : r0_4 # 513| r0_6(glval) = VariableAddress[r1] : -# 513| r0_7(glval) = FieldAddress[topLeft] : r0_6 -# 513| r0_8(Point) = Constant[0] : -# 513| m0_9(Point) = Store : r0_7, r0_8 -# 513| r0_10(glval) = FieldAddress[bottomRight] : r0_6 -# 513| r0_11(Point) = Constant[0] : -# 513| mu0_12(Point) = Store : r0_10, r0_11 -# 514| r0_13(glval) = VariableAddress[r2] : -# 514| r0_14(glval) = FieldAddress[topLeft] : r0_13 -# 514| r0_15(glval) = FieldAddress[x] : r0_14 -# 514| r0_16(glval) = VariableAddress[x] : -# 514| r0_17(int) = Load : r0_16, m0_3 -# 514| m0_18(int) = Store : r0_15, r0_17 -# 514| r0_19(glval) = FieldAddress[y] : r0_14 -# 514| r0_20(glval) = VariableAddress[f] : -# 514| r0_21(float) = Load : r0_20, m0_5 -# 514| r0_22(int) = Convert : r0_21 -# 514| mu0_23(int) = Store : r0_19, r0_22 -# 514| r0_24(glval) = FieldAddress[bottomRight] : r0_13 -# 514| r0_25(Point) = Constant[0] : -# 514| mu0_26(Point) = Store : r0_24, r0_25 -# 515| r0_27(glval) = VariableAddress[r3] : -# 515| r0_28(glval) = FieldAddress[topLeft] : r0_27 -# 515| r0_29(glval) = FieldAddress[x] : r0_28 -# 515| r0_30(glval) = VariableAddress[x] : -# 515| r0_31(int) = Load : r0_30, m0_3 -# 515| m0_32(int) = Store : r0_29, r0_31 -# 515| r0_33(glval) = FieldAddress[y] : r0_28 -# 515| r0_34(glval) = VariableAddress[f] : -# 515| r0_35(float) = Load : r0_34, m0_5 -# 515| r0_36(int) = Convert : r0_35 -# 515| mu0_37(int) = Store : r0_33, r0_36 -# 515| r0_38(glval) = FieldAddress[bottomRight] : r0_27 -# 515| r0_39(glval) = FieldAddress[x] : r0_38 -# 515| r0_40(glval) = VariableAddress[x] : -# 515| r0_41(int) = Load : r0_40, m0_3 -# 515| mu0_42(int) = Store : r0_39, r0_41 -# 515| r0_43(glval) = FieldAddress[y] : r0_38 -# 515| r0_44(glval) = VariableAddress[f] : -# 515| r0_45(float) = Load : r0_44, m0_5 -# 515| r0_46(int) = Convert : r0_45 -# 515| mu0_47(int) = Store : r0_43, r0_46 -# 516| r0_48(glval) = VariableAddress[r4] : -# 516| r0_49(glval) = FieldAddress[topLeft] : r0_48 -# 516| r0_50(glval) = FieldAddress[x] : r0_49 -# 516| r0_51(glval) = VariableAddress[x] : -# 516| r0_52(int) = Load : r0_51, m0_3 -# 516| m0_53(int) = Store : r0_50, r0_52 -# 516| r0_54(glval) = FieldAddress[y] : r0_49 -# 516| r0_55(int) = Constant[0] : -# 516| mu0_56(int) = Store : r0_54, r0_55 -# 516| r0_57(glval) = FieldAddress[bottomRight] : r0_48 -# 516| r0_58(glval) = FieldAddress[x] : r0_57 -# 516| r0_59(glval) = VariableAddress[x] : -# 516| r0_60(int) = Load : r0_59, m0_3 -# 516| mu0_61(int) = Store : r0_58, r0_60 -# 516| r0_62(glval) = FieldAddress[y] : r0_57 -# 516| r0_63(int) = Constant[0] : -# 516| mu0_64(int) = Store : r0_62, r0_63 -# 517| v0_65(void) = NoOp : -# 512| v0_66(void) = ReturnVoid : -# 512| v0_67(void) = UnmodeledUse : mu* -# 512| v0_68(void) = ExitFunction : +# 513| m0_7(Rect) = Uninitialized : r0_6 +# 513| r0_8(glval) = FieldAddress[topLeft] : r0_6 +# 513| r0_9(Point) = Constant[0] : +# 513| m0_10(Point) = Store : r0_8, r0_9 +# 513| r0_11(glval) = FieldAddress[bottomRight] : r0_6 +# 513| r0_12(Point) = Constant[0] : +# 513| mu0_13(Point) = Store : r0_11, r0_12 +# 514| r0_14(glval) = VariableAddress[r2] : +# 514| m0_15(Rect) = Uninitialized : r0_14 +# 514| r0_16(glval) = FieldAddress[topLeft] : r0_14 +# 514| r0_17(glval) = FieldAddress[x] : r0_16 +# 514| r0_18(glval) = VariableAddress[x] : +# 514| r0_19(int) = Load : r0_18, m0_3 +# 514| m0_20(int) = Store : r0_17, r0_19 +# 514| r0_21(glval) = FieldAddress[y] : r0_16 +# 514| r0_22(glval) = VariableAddress[f] : +# 514| r0_23(float) = Load : r0_22, m0_5 +# 514| r0_24(int) = Convert : r0_23 +# 514| mu0_25(int) = Store : r0_21, r0_24 +# 514| r0_26(glval) = FieldAddress[bottomRight] : r0_14 +# 514| r0_27(Point) = Constant[0] : +# 514| mu0_28(Point) = Store : r0_26, r0_27 +# 515| r0_29(glval) = VariableAddress[r3] : +# 515| m0_30(Rect) = Uninitialized : r0_29 +# 515| r0_31(glval) = FieldAddress[topLeft] : r0_29 +# 515| r0_32(glval) = FieldAddress[x] : r0_31 +# 515| r0_33(glval) = VariableAddress[x] : +# 515| r0_34(int) = Load : r0_33, m0_3 +# 515| m0_35(int) = Store : r0_32, r0_34 +# 515| r0_36(glval) = FieldAddress[y] : r0_31 +# 515| r0_37(glval) = VariableAddress[f] : +# 515| r0_38(float) = Load : r0_37, m0_5 +# 515| r0_39(int) = Convert : r0_38 +# 515| mu0_40(int) = Store : r0_36, r0_39 +# 515| r0_41(glval) = FieldAddress[bottomRight] : r0_29 +# 515| r0_42(glval) = FieldAddress[x] : r0_41 +# 515| r0_43(glval) = VariableAddress[x] : +# 515| r0_44(int) = Load : r0_43, m0_3 +# 515| mu0_45(int) = Store : r0_42, r0_44 +# 515| r0_46(glval) = FieldAddress[y] : r0_41 +# 515| r0_47(glval) = VariableAddress[f] : +# 515| r0_48(float) = Load : r0_47, m0_5 +# 515| r0_49(int) = Convert : r0_48 +# 515| mu0_50(int) = Store : r0_46, r0_49 +# 516| r0_51(glval) = VariableAddress[r4] : +# 516| m0_52(Rect) = Uninitialized : r0_51 +# 516| r0_53(glval) = FieldAddress[topLeft] : r0_51 +# 516| r0_54(glval) = FieldAddress[x] : r0_53 +# 516| r0_55(glval) = VariableAddress[x] : +# 516| r0_56(int) = Load : r0_55, m0_3 +# 516| m0_57(int) = Store : r0_54, r0_56 +# 516| r0_58(glval) = FieldAddress[y] : r0_53 +# 516| r0_59(int) = Constant[0] : +# 516| mu0_60(int) = Store : r0_58, r0_59 +# 516| r0_61(glval) = FieldAddress[bottomRight] : r0_51 +# 516| r0_62(glval) = FieldAddress[x] : r0_61 +# 516| r0_63(glval) = VariableAddress[x] : +# 516| r0_64(int) = Load : r0_63, m0_3 +# 516| mu0_65(int) = Store : r0_62, r0_64 +# 516| r0_66(glval) = FieldAddress[y] : r0_61 +# 516| r0_67(int) = Constant[0] : +# 516| mu0_68(int) = Store : r0_66, r0_67 +# 517| v0_69(void) = NoOp : +# 512| v0_70(void) = ReturnVoid : +# 512| v0_71(void) = UnmodeledUse : mu* +# 512| v0_72(void) = ExitFunction : # 519| ArrayInit(int, float) -> void # 519| Block 0 @@ -2268,40 +2321,43 @@ ir.cpp: # 519| r0_4(glval) = VariableAddress[f] : # 519| m0_5(float) = InitializeParameter[f] : r0_4 # 520| r0_6(glval) = VariableAddress[a1] : -# 520| r0_7(int) = Constant[0] : -# 520| r0_8(glval) = PointerAdd : r0_6, r0_7 -# 520| r0_9(unknown[12]) = Constant[0] : -# 520| mu0_10(unknown[12]) = Store : r0_8, r0_9 -# 521| r0_11(glval) = VariableAddress[a2] : -# 521| r0_12(int) = Constant[0] : -# 521| r0_13(glval) = PointerAdd : r0_11, r0_12 -# 521| r0_14(glval) = VariableAddress[x] : -# 521| r0_15(int) = Load : r0_14, m0_3 -# 521| mu0_16(int) = Store : r0_13, r0_15 -# 521| r0_17(int) = Constant[1] : -# 521| r0_18(glval) = PointerAdd : r0_11, r0_17 -# 521| r0_19(glval) = VariableAddress[f] : -# 521| r0_20(float) = Load : r0_19, m0_5 -# 521| r0_21(int) = Convert : r0_20 -# 521| mu0_22(int) = Store : r0_18, r0_21 -# 521| r0_23(int) = Constant[2] : -# 521| r0_24(glval) = PointerAdd : r0_11, r0_23 -# 521| r0_25(int) = Constant[0] : -# 521| mu0_26(int) = Store : r0_24, r0_25 -# 522| r0_27(glval) = VariableAddress[a3] : -# 522| r0_28(int) = Constant[0] : -# 522| r0_29(glval) = PointerAdd : r0_27, r0_28 -# 522| r0_30(glval) = VariableAddress[x] : -# 522| r0_31(int) = Load : r0_30, m0_3 -# 522| mu0_32(int) = Store : r0_29, r0_31 -# 522| r0_33(int) = Constant[1] : -# 522| r0_34(glval) = PointerAdd : r0_27, r0_33 -# 522| r0_35(unknown[8]) = Constant[0] : -# 522| mu0_36(unknown[8]) = Store : r0_34, r0_35 -# 523| v0_37(void) = NoOp : -# 519| v0_38(void) = ReturnVoid : -# 519| v0_39(void) = UnmodeledUse : mu* -# 519| v0_40(void) = ExitFunction : +# 520| mu0_7(int[3]) = Uninitialized : r0_6 +# 520| r0_8(int) = Constant[0] : +# 520| r0_9(glval) = PointerAdd : r0_6, r0_8 +# 520| r0_10(unknown[12]) = Constant[0] : +# 520| mu0_11(unknown[12]) = Store : r0_9, r0_10 +# 521| r0_12(glval) = VariableAddress[a2] : +# 521| mu0_13(int[3]) = Uninitialized : r0_12 +# 521| r0_14(int) = Constant[0] : +# 521| r0_15(glval) = PointerAdd : r0_12, r0_14 +# 521| r0_16(glval) = VariableAddress[x] : +# 521| r0_17(int) = Load : r0_16, m0_3 +# 521| mu0_18(int) = Store : r0_15, r0_17 +# 521| r0_19(int) = Constant[1] : +# 521| r0_20(glval) = PointerAdd : r0_12, r0_19 +# 521| r0_21(glval) = VariableAddress[f] : +# 521| r0_22(float) = Load : r0_21, m0_5 +# 521| r0_23(int) = Convert : r0_22 +# 521| mu0_24(int) = Store : r0_20, r0_23 +# 521| r0_25(int) = Constant[2] : +# 521| r0_26(glval) = PointerAdd : r0_12, r0_25 +# 521| r0_27(int) = Constant[0] : +# 521| mu0_28(int) = Store : r0_26, r0_27 +# 522| r0_29(glval) = VariableAddress[a3] : +# 522| mu0_30(int[3]) = Uninitialized : r0_29 +# 522| r0_31(int) = Constant[0] : +# 522| r0_32(glval) = PointerAdd : r0_29, r0_31 +# 522| r0_33(glval) = VariableAddress[x] : +# 522| r0_34(int) = Load : r0_33, m0_3 +# 522| mu0_35(int) = Store : r0_32, r0_34 +# 522| r0_36(int) = Constant[1] : +# 522| r0_37(glval) = PointerAdd : r0_29, r0_36 +# 522| r0_38(unknown[8]) = Constant[0] : +# 522| mu0_39(unknown[8]) = Store : r0_37, r0_38 +# 523| v0_40(void) = NoOp : +# 519| v0_41(void) = ReturnVoid : +# 519| v0_42(void) = UnmodeledUse : mu* +# 519| v0_43(void) = ExitFunction : # 530| UnionInit(int, float) -> void # 530| Block 0 @@ -2312,15 +2368,16 @@ ir.cpp: # 530| r0_4(glval) = VariableAddress[f] : # 530| m0_5(float) = InitializeParameter[f] : r0_4 # 531| r0_6(glval) = VariableAddress[u1] : -# 531| r0_7(glval) = FieldAddress[d] : r0_6 -# 531| r0_8(glval) = VariableAddress[f] : -# 531| r0_9(float) = Load : r0_8, m0_5 -# 531| r0_10(double) = Convert : r0_9 -# 531| m0_11(double) = Store : r0_7, r0_10 -# 533| v0_12(void) = NoOp : -# 530| v0_13(void) = ReturnVoid : -# 530| v0_14(void) = UnmodeledUse : mu* -# 530| v0_15(void) = ExitFunction : +# 531| m0_7(U) = Uninitialized : r0_6 +# 531| r0_8(glval) = FieldAddress[d] : r0_6 +# 531| r0_9(glval) = VariableAddress[f] : +# 531| r0_10(float) = Load : r0_9, m0_5 +# 531| r0_11(double) = Convert : r0_10 +# 531| m0_12(double) = Store : r0_8, r0_11 +# 533| v0_13(void) = NoOp : +# 530| v0_14(void) = ReturnVoid : +# 530| v0_15(void) = UnmodeledUse : mu* +# 530| v0_16(void) = ExitFunction : # 535| EarlyReturn(int, int) -> void # 535| Block 0 @@ -2479,41 +2536,45 @@ ir.cpp: # 575| r0_18(glval) = VariableAddress[b] : # 575| m0_19(char[2]) = Uninitialized : r0_18 # 576| r0_20(glval) = VariableAddress[c] : -# 576| r0_21(int) = Constant[0] : -# 576| r0_22(glval) = PointerAdd : r0_20, r0_21 -# 576| r0_23(unknown[2]) = Constant[0] : -# 576| mu0_24(unknown[2]) = Store : r0_22, r0_23 -# 577| r0_25(glval) = VariableAddress[d] : -# 577| r0_26(int) = Constant[0] : -# 577| r0_27(glval) = PointerAdd : r0_25, r0_26 -# 577| r0_28(char) = Constant[0] : -# 577| mu0_29(char) = Store : r0_27, r0_28 -# 577| r0_30(int) = Constant[1] : -# 577| r0_31(glval) = PointerAdd : r0_25, r0_30 -# 577| r0_32(char) = Constant[0] : -# 577| mu0_33(char) = Store : r0_31, r0_32 -# 578| r0_34(glval) = VariableAddress[e] : -# 578| r0_35(int) = Constant[0] : -# 578| r0_36(glval) = PointerAdd : r0_34, r0_35 -# 578| r0_37(char) = Constant[0] : -# 578| mu0_38(char) = Store : r0_36, r0_37 -# 578| r0_39(int) = Constant[1] : -# 578| r0_40(glval) = PointerAdd : r0_34, r0_39 -# 578| r0_41(char) = Constant[1] : -# 578| mu0_42(char) = Store : r0_40, r0_41 -# 579| r0_43(glval) = VariableAddress[f] : -# 579| r0_44(int) = Constant[0] : -# 579| r0_45(glval) = PointerAdd : r0_43, r0_44 -# 579| r0_46(char) = Constant[0] : -# 579| mu0_47(char) = Store : r0_45, r0_46 -# 579| r0_48(int) = Constant[1] : -# 579| r0_49(glval) = PointerAdd : r0_43, r0_48 -# 579| r0_50(unknown[2]) = Constant[0] : -# 579| mu0_51(unknown[2]) = Store : r0_49, r0_50 -# 580| v0_52(void) = NoOp : -# 571| v0_53(void) = ReturnVoid : -# 571| v0_54(void) = UnmodeledUse : mu* -# 571| v0_55(void) = ExitFunction : +# 576| mu0_21(char[2]) = Uninitialized : r0_20 +# 576| r0_22(int) = Constant[0] : +# 576| r0_23(glval) = PointerAdd : r0_20, r0_22 +# 576| r0_24(unknown[2]) = Constant[0] : +# 576| mu0_25(unknown[2]) = Store : r0_23, r0_24 +# 577| r0_26(glval) = VariableAddress[d] : +# 577| mu0_27(char[2]) = Uninitialized : r0_26 +# 577| r0_28(int) = Constant[0] : +# 577| r0_29(glval) = PointerAdd : r0_26, r0_28 +# 577| r0_30(char) = Constant[0] : +# 577| mu0_31(char) = Store : r0_29, r0_30 +# 577| r0_32(int) = Constant[1] : +# 577| r0_33(glval) = PointerAdd : r0_26, r0_32 +# 577| r0_34(char) = Constant[0] : +# 577| mu0_35(char) = Store : r0_33, r0_34 +# 578| r0_36(glval) = VariableAddress[e] : +# 578| mu0_37(char[2]) = Uninitialized : r0_36 +# 578| r0_38(int) = Constant[0] : +# 578| r0_39(glval) = PointerAdd : r0_36, r0_38 +# 578| r0_40(char) = Constant[0] : +# 578| mu0_41(char) = Store : r0_39, r0_40 +# 578| r0_42(int) = Constant[1] : +# 578| r0_43(glval) = PointerAdd : r0_36, r0_42 +# 578| r0_44(char) = Constant[1] : +# 578| mu0_45(char) = Store : r0_43, r0_44 +# 579| r0_46(glval) = VariableAddress[f] : +# 579| mu0_47(char[3]) = Uninitialized : r0_46 +# 579| r0_48(int) = Constant[0] : +# 579| r0_49(glval) = PointerAdd : r0_46, r0_48 +# 579| r0_50(char) = Constant[0] : +# 579| mu0_51(char) = Store : r0_49, r0_50 +# 579| r0_52(int) = Constant[1] : +# 579| r0_53(glval) = PointerAdd : r0_46, r0_52 +# 579| r0_54(unknown[2]) = Constant[0] : +# 579| mu0_55(unknown[2]) = Store : r0_53, r0_54 +# 580| v0_56(void) = NoOp : +# 571| v0_57(void) = ReturnVoid : +# 571| v0_58(void) = UnmodeledUse : mu* +# 571| v0_59(void) = ExitFunction : # 584| VarArgs() -> void # 584| Block 0 @@ -3912,10 +3973,11 @@ ir.cpp: # 961| v0_0(void) = EnterFunction : # 961| mu0_1(unknown) = UnmodeledDefinition : # 962| r0_2(glval) = VariableAddress[a1] : -# 962| r0_3(int) = Constant[0] : -# 962| r0_4(glval) = PointerAdd : r0_2, r0_3 -# 962| r0_5(unknown[8]) = Constant[0] : -# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5 +# 962| mu0_3(int[1000]) = Uninitialized : r0_2 +# 962| r0_4(int) = Constant[0] : +# 962| r0_5(glval) = PointerAdd : r0_2, r0_4 +# 962| r0_6(unknown[8]) = Constant[0] : +# 962| mu0_7(unknown[8]) = Store : r0_5, r0_6 #-----| Goto -> Block 2 # 962| Block 1 @@ -3952,3 +4014,147 @@ ir.cpp: # 962| r3_6(unknown[3588]) = Constant[0] : # 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6 #-----| Goto -> Block 2 + +# 966| IfStmtWithDeclaration(int, int) -> void +# 966| Block 0 +# 966| v0_0(void) = EnterFunction : +# 966| mu0_1(unknown) = UnmodeledDefinition : +# 966| r0_2(glval) = VariableAddress[x] : +# 966| m0_3(int) = InitializeParameter[x] : r0_2 +# 966| r0_4(glval) = VariableAddress[y] : +# 966| m0_5(int) = InitializeParameter[y] : r0_4 +# 967| r0_6(glval) = VariableAddress[b] : +# 967| r0_7(glval) = VariableAddress[x] : +# 967| r0_8(int) = Load : r0_7, m0_3 +# 967| r0_9(glval) = VariableAddress[y] : +# 967| r0_10(int) = Load : r0_9, m0_5 +# 967| r0_11(bool) = CompareLT : r0_8, r0_10 +# 967| m0_12(bool) = Store : r0_6, r0_11 +# 967| r0_13(glval) = VariableAddress[b] : +# 967| r0_14(bool) = Load : r0_13, m0_12 +# 967| v0_15(void) = ConditionalBranch : r0_14 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 968| Block 1 +# 968| r1_0(int) = Constant[5] : +# 968| r1_1(glval) = VariableAddress[x] : +# 968| m1_2(int) = Store : r1_1, r1_0 +#-----| Goto -> Block 6 + +# 970| Block 2 +# 970| r2_0(glval) = VariableAddress[z] : +# 970| r2_1(glval) = VariableAddress[x] : +# 970| r2_2(int) = Load : r2_1, m0_3 +# 970| r2_3(glval) = VariableAddress[y] : +# 970| r2_4(int) = Load : r2_3, m0_5 +# 970| r2_5(int) = Add : r2_2, r2_4 +# 970| m2_6(int) = Store : r2_0, r2_5 +# 970| r2_7(glval) = VariableAddress[z] : +# 970| r2_8(int) = Load : r2_7, m2_6 +# 970| r2_9(int) = Constant[0] : +# 970| r2_10(bool) = CompareNE : r2_8, r2_9 +# 970| v2_11(void) = ConditionalBranch : r2_10 +#-----| False -> Block 4 +#-----| True -> Block 3 + +# 971| Block 3 +# 971| r3_0(int) = Constant[7] : +# 971| r3_1(glval) = VariableAddress[y] : +# 971| m3_2(int) = Store : r3_1, r3_0 +#-----| Goto -> Block 6 + +# 973| Block 4 +# 973| r4_0(glval) = VariableAddress[p] : +# 973| r4_1(glval) = VariableAddress[x] : +# 973| m4_2(int *) = Store : r4_0, r4_1 +# 973| r4_3(glval) = VariableAddress[p] : +# 973| r4_4(int *) = Load : r4_3, m4_2 +# 973| r4_5(int *) = Constant[0] : +# 973| r4_6(bool) = CompareNE : r4_4, r4_5 +# 973| v4_7(void) = ConditionalBranch : r4_6 +#-----| False -> Block 6 +#-----| True -> Block 5 + +# 974| Block 5 +# 974| r5_0(int) = Constant[2] : +# 974| r5_1(glval) = VariableAddress[p] : +# 974| r5_2(int *) = Load : r5_1, m4_2 +# 974| m5_3(int) = Store : r5_2, r5_0 +#-----| Goto -> Block 6 + +# 976| Block 6 +# 976| v6_0(void) = NoOp : +# 966| v6_1(void) = ReturnVoid : +# 966| v6_2(void) = UnmodeledUse : mu* +# 966| v6_3(void) = ExitFunction : + +# 978| WhileStmtWithDeclaration(int, int) -> void +# 978| Block 0 +# 978| v0_0(void) = EnterFunction : +# 978| mu0_1(unknown) = UnmodeledDefinition : +# 978| r0_2(glval) = VariableAddress[x] : +# 978| m0_3(int) = InitializeParameter[x] : r0_2 +# 978| r0_4(glval) = VariableAddress[y] : +# 978| m0_5(int) = InitializeParameter[y] : r0_4 +#-----| Goto -> Block 7 + +# 979| Block 1 +# 979| v1_0(void) = NoOp : +#-----| Goto -> Block 7 + +# 981| Block 2 +# 981| r2_0(glval) = VariableAddress[z] : +# 981| r2_1(glval) = VariableAddress[x] : +# 981| r2_2(int) = Load : r2_1, m0_3 +# 981| r2_3(glval) = VariableAddress[y] : +# 981| r2_4(int) = Load : r2_3, m0_5 +# 981| r2_5(int) = Add : r2_2, r2_4 +# 981| m2_6(int) = Store : r2_0, r2_5 +# 981| r2_7(glval) = VariableAddress[z] : +# 981| r2_8(int) = Load : r2_7, m2_6 +# 981| r2_9(int) = Constant[0] : +# 981| r2_10(bool) = CompareNE : r2_8, r2_9 +# 981| v2_11(void) = ConditionalBranch : r2_10 +#-----| False -> Block 4 +#-----| True -> Block 3 + +# 981| Block 3 +# 981| v3_0(void) = NoOp : +#-----| Goto -> Block 2 + +# 983| Block 4 +# 983| r4_0(glval) = VariableAddress[p] : +# 983| r4_1(glval) = VariableAddress[x] : +# 983| m4_2(int *) = Store : r4_0, r4_1 +# 983| r4_3(glval) = VariableAddress[p] : +# 983| r4_4(int *) = Load : r4_3, m4_2 +# 983| r4_5(int *) = Constant[0] : +# 983| r4_6(bool) = CompareNE : r4_4, r4_5 +# 983| v4_7(void) = ConditionalBranch : r4_6 +#-----| False -> Block 6 +#-----| True -> Block 5 + +# 983| Block 5 +# 983| v5_0(void) = NoOp : +#-----| Goto -> Block 4 + +# 985| Block 6 +# 985| v6_0(void) = NoOp : +# 978| v6_1(void) = ReturnVoid : +# 978| v6_2(void) = UnmodeledUse : mu* +# 978| v6_3(void) = ExitFunction : + +# 979| Block 7 +# 979| r7_0(glval) = VariableAddress[b] : +# 979| r7_1(glval) = VariableAddress[x] : +# 979| r7_2(int) = Load : r7_1, m0_3 +# 979| r7_3(glval) = VariableAddress[y] : +# 979| r7_4(int) = Load : r7_3, m0_5 +# 979| r7_5(bool) = CompareLT : r7_2, r7_4 +# 979| m7_6(bool) = Store : r7_0, r7_5 +# 979| r7_7(glval) = VariableAddress[b] : +# 979| r7_8(bool) = Load : r7_7, m7_6 +# 979| v7_9(void) = ConditionalBranch : r7_8 +#-----| False -> Block 2 +#-----| True -> Block 1 diff --git a/cpp/ql/test/library-tests/ir/ir/bad_asts.cpp b/cpp/ql/test/library-tests/ir/ir/bad_asts.cpp new file mode 100644 index 00000000000..6bd726959c7 --- /dev/null +++ b/cpp/ql/test/library-tests/ir/ir/bad_asts.cpp @@ -0,0 +1,29 @@ +// semmle-extractor-options: -std=c++17 + +// Test cases that illustrate known bad ASTs that we have to work around in IR generation. +namespace Bad { + struct S { + int x; + + template + int MemberFunction(int y) { + return t + x + y; + } + }; + + void CallBadMemberFunction() { + S s = {}; + s.MemberFunction<6>(1); // Not marked as member function in AST. + } + + struct Point { + int x; + int y; + Point() { + } + }; + + void CallCopyConstructor(const Point& a) { + Point b = a; // Copy constructor contains literal expressions with no values. + } +} diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index 3ff4c53c17e..95486aa55e1 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -963,6 +963,27 @@ int designatedInit() { return a1[900]; } +void IfStmtWithDeclaration(int x, int y) { + if (bool b = x < y) { + x = 5; + } + else if (int z = x + y) { + y = 7; + } + else if (int* p = &x) { + *p = 2; + } +} + +void WhileStmtWithDeclaration(int x, int y) { + while (bool b = x < y) { + } + while (int z = x + y) { + } + while (int* p = &x) { + } +} + #if 0 void OperatorDelete() { delete static_cast(nullptr); // No destructor diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 5f5dc4d3f5d..15f3f0867ac 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,3 +1,49 @@ +bad_asts.cpp: +# 14| Bad::CallBadMemberFunction() -> void +# 14| Block 0 +# 14| v0_0(void) = EnterFunction : +# 14| mu0_1(unknown) = UnmodeledDefinition : +# 15| r0_2(glval) = VariableAddress[s] : +# 15| mu0_3(S) = Uninitialized : r0_2 +# 15| r0_4(glval) = FieldAddress[x] : r0_2 +# 15| r0_5(int) = Constant[0] : +# 15| mu0_6(int) = Store : r0_4, r0_5 +# 16| r0_7(glval) = VariableAddress[s] : +# 16| r0_8(glval) = FunctionAddress[MemberFunction] : +# 16| r0_9(int) = Constant[1] : +# 16| r0_10(int) = Call : r0_8, this:r0_7, r0_9 +# 17| v0_11(void) = NoOp : +# 14| v0_12(void) = ReturnVoid : +# 14| v0_13(void) = UnmodeledUse : mu* +# 14| v0_14(void) = ExitFunction : + +# 22| Bad::Point::Point() -> void +# 22| Block 0 +# 22| v0_0(void) = EnterFunction : +# 22| mu0_1(unknown) = UnmodeledDefinition : +# 22| r0_2(glval) = InitializeThis : +# 23| v0_3(void) = NoOp : +# 22| v0_4(void) = ReturnVoid : +# 22| v0_5(void) = UnmodeledUse : mu* +# 22| v0_6(void) = ExitFunction : + +# 26| Bad::CallCopyConstructor(const Point &) -> void +# 26| Block 0 +# 26| v0_0(void) = EnterFunction : +# 26| mu0_1(unknown) = UnmodeledDefinition : +# 26| r0_2(glval) = VariableAddress[a] : +# 26| mu0_3(Point &) = InitializeParameter[a] : r0_2 +# 27| r0_4(glval) = VariableAddress[b] : +# 27| r0_5(glval) = VariableAddress[a] : +# 27| r0_6(Point &) = Load : r0_5, mu0_1 +# 27| r0_7(glval) = Convert : r0_6 +# 27| r0_8(Point) = Load : r0_7, mu0_1 +# 27| mu0_9(Point) = Store : r0_4, r0_8 +# 28| v0_10(void) = NoOp : +# 26| v0_11(void) = ReturnVoid : +# 26| v0_12(void) = UnmodeledUse : mu* +# 26| v0_13(void) = ExitFunction : + ir.cpp: # 1| Constants() -> void # 1| Block 0 @@ -2135,40 +2181,43 @@ ir.cpp: # 503| r0_4(glval) = VariableAddress[f] : # 503| mu0_5(float) = InitializeParameter[f] : r0_4 # 504| r0_6(glval) = VariableAddress[pt1] : -# 504| r0_7(glval) = FieldAddress[x] : r0_6 -# 504| r0_8(glval) = VariableAddress[x] : -# 504| r0_9(int) = Load : r0_8, mu0_1 -# 504| mu0_10(int) = Store : r0_7, r0_9 -# 504| r0_11(glval) = FieldAddress[y] : r0_6 -# 504| r0_12(glval) = VariableAddress[f] : -# 504| r0_13(float) = Load : r0_12, mu0_1 -# 504| r0_14(int) = Convert : r0_13 -# 504| mu0_15(int) = Store : r0_11, r0_14 -# 505| r0_16(glval) = VariableAddress[pt2] : -# 505| r0_17(glval) = FieldAddress[x] : r0_16 -# 505| r0_18(glval) = VariableAddress[x] : -# 505| r0_19(int) = Load : r0_18, mu0_1 -# 505| mu0_20(int) = Store : r0_17, r0_19 -# 505| r0_21(glval) = FieldAddress[y] : r0_16 -# 505| r0_22(int) = Constant[0] : -# 505| mu0_23(int) = Store : r0_21, r0_22 -# 506| r0_24(glval) = VariableAddress[pt3] : -# 506| r0_25(glval) = FieldAddress[x] : r0_24 -# 506| r0_26(int) = Constant[0] : -# 506| mu0_27(int) = Store : r0_25, r0_26 -# 506| r0_28(glval) = FieldAddress[y] : r0_24 +# 504| mu0_7(Point) = Uninitialized : r0_6 +# 504| r0_8(glval) = FieldAddress[x] : r0_6 +# 504| r0_9(glval) = VariableAddress[x] : +# 504| r0_10(int) = Load : r0_9, mu0_1 +# 504| mu0_11(int) = Store : r0_8, r0_10 +# 504| r0_12(glval) = FieldAddress[y] : r0_6 +# 504| r0_13(glval) = VariableAddress[f] : +# 504| r0_14(float) = Load : r0_13, mu0_1 +# 504| r0_15(int) = Convert : r0_14 +# 504| mu0_16(int) = Store : r0_12, r0_15 +# 505| r0_17(glval) = VariableAddress[pt2] : +# 505| mu0_18(Point) = Uninitialized : r0_17 +# 505| r0_19(glval) = FieldAddress[x] : r0_17 +# 505| r0_20(glval) = VariableAddress[x] : +# 505| r0_21(int) = Load : r0_20, mu0_1 +# 505| mu0_22(int) = Store : r0_19, r0_21 +# 505| r0_23(glval) = FieldAddress[y] : r0_17 +# 505| r0_24(int) = Constant[0] : +# 505| mu0_25(int) = Store : r0_23, r0_24 +# 506| r0_26(glval) = VariableAddress[pt3] : +# 506| mu0_27(Point) = Uninitialized : r0_26 +# 506| r0_28(glval) = FieldAddress[x] : r0_26 # 506| r0_29(int) = Constant[0] : # 506| mu0_30(int) = Store : r0_28, r0_29 -# 508| r0_31(glval) = VariableAddress[x1] : -# 508| r0_32(int) = Constant[1] : -# 508| mu0_33(int) = Store : r0_31, r0_32 -# 509| r0_34(glval) = VariableAddress[x2] : -# 509| r0_35(int) = Constant[0] : -# 509| mu0_36(int) = Store : r0_34, r0_35 -# 510| v0_37(void) = NoOp : -# 503| v0_38(void) = ReturnVoid : -# 503| v0_39(void) = UnmodeledUse : mu* -# 503| v0_40(void) = ExitFunction : +# 506| r0_31(glval) = FieldAddress[y] : r0_26 +# 506| r0_32(int) = Constant[0] : +# 506| mu0_33(int) = Store : r0_31, r0_32 +# 508| r0_34(glval) = VariableAddress[x1] : +# 508| r0_35(int) = Constant[1] : +# 508| mu0_36(int) = Store : r0_34, r0_35 +# 509| r0_37(glval) = VariableAddress[x2] : +# 509| r0_38(int) = Constant[0] : +# 509| mu0_39(int) = Store : r0_37, r0_38 +# 510| v0_40(void) = NoOp : +# 503| v0_41(void) = ReturnVoid : +# 503| v0_42(void) = UnmodeledUse : mu* +# 503| v0_43(void) = ExitFunction : # 512| NestedInitList(int, float) -> void # 512| Block 0 @@ -2179,68 +2228,72 @@ ir.cpp: # 512| r0_4(glval) = VariableAddress[f] : # 512| mu0_5(float) = InitializeParameter[f] : r0_4 # 513| r0_6(glval) = VariableAddress[r1] : -# 513| r0_7(glval) = FieldAddress[topLeft] : r0_6 -# 513| r0_8(Point) = Constant[0] : -# 513| mu0_9(Point) = Store : r0_7, r0_8 -# 513| r0_10(glval) = FieldAddress[bottomRight] : r0_6 -# 513| r0_11(Point) = Constant[0] : -# 513| mu0_12(Point) = Store : r0_10, r0_11 -# 514| r0_13(glval) = VariableAddress[r2] : -# 514| r0_14(glval) = FieldAddress[topLeft] : r0_13 -# 514| r0_15(glval) = FieldAddress[x] : r0_14 -# 514| r0_16(glval) = VariableAddress[x] : -# 514| r0_17(int) = Load : r0_16, mu0_1 -# 514| mu0_18(int) = Store : r0_15, r0_17 -# 514| r0_19(glval) = FieldAddress[y] : r0_14 -# 514| r0_20(glval) = VariableAddress[f] : -# 514| r0_21(float) = Load : r0_20, mu0_1 -# 514| r0_22(int) = Convert : r0_21 -# 514| mu0_23(int) = Store : r0_19, r0_22 -# 514| r0_24(glval) = FieldAddress[bottomRight] : r0_13 -# 514| r0_25(Point) = Constant[0] : -# 514| mu0_26(Point) = Store : r0_24, r0_25 -# 515| r0_27(glval) = VariableAddress[r3] : -# 515| r0_28(glval) = FieldAddress[topLeft] : r0_27 -# 515| r0_29(glval) = FieldAddress[x] : r0_28 -# 515| r0_30(glval) = VariableAddress[x] : -# 515| r0_31(int) = Load : r0_30, mu0_1 -# 515| mu0_32(int) = Store : r0_29, r0_31 -# 515| r0_33(glval) = FieldAddress[y] : r0_28 -# 515| r0_34(glval) = VariableAddress[f] : -# 515| r0_35(float) = Load : r0_34, mu0_1 -# 515| r0_36(int) = Convert : r0_35 -# 515| mu0_37(int) = Store : r0_33, r0_36 -# 515| r0_38(glval) = FieldAddress[bottomRight] : r0_27 -# 515| r0_39(glval) = FieldAddress[x] : r0_38 -# 515| r0_40(glval) = VariableAddress[x] : -# 515| r0_41(int) = Load : r0_40, mu0_1 -# 515| mu0_42(int) = Store : r0_39, r0_41 -# 515| r0_43(glval) = FieldAddress[y] : r0_38 -# 515| r0_44(glval) = VariableAddress[f] : -# 515| r0_45(float) = Load : r0_44, mu0_1 -# 515| r0_46(int) = Convert : r0_45 -# 515| mu0_47(int) = Store : r0_43, r0_46 -# 516| r0_48(glval) = VariableAddress[r4] : -# 516| r0_49(glval) = FieldAddress[topLeft] : r0_48 -# 516| r0_50(glval) = FieldAddress[x] : r0_49 -# 516| r0_51(glval) = VariableAddress[x] : -# 516| r0_52(int) = Load : r0_51, mu0_1 -# 516| mu0_53(int) = Store : r0_50, r0_52 -# 516| r0_54(glval) = FieldAddress[y] : r0_49 -# 516| r0_55(int) = Constant[0] : -# 516| mu0_56(int) = Store : r0_54, r0_55 -# 516| r0_57(glval) = FieldAddress[bottomRight] : r0_48 -# 516| r0_58(glval) = FieldAddress[x] : r0_57 -# 516| r0_59(glval) = VariableAddress[x] : -# 516| r0_60(int) = Load : r0_59, mu0_1 -# 516| mu0_61(int) = Store : r0_58, r0_60 -# 516| r0_62(glval) = FieldAddress[y] : r0_57 -# 516| r0_63(int) = Constant[0] : -# 516| mu0_64(int) = Store : r0_62, r0_63 -# 517| v0_65(void) = NoOp : -# 512| v0_66(void) = ReturnVoid : -# 512| v0_67(void) = UnmodeledUse : mu* -# 512| v0_68(void) = ExitFunction : +# 513| mu0_7(Rect) = Uninitialized : r0_6 +# 513| r0_8(glval) = FieldAddress[topLeft] : r0_6 +# 513| r0_9(Point) = Constant[0] : +# 513| mu0_10(Point) = Store : r0_8, r0_9 +# 513| r0_11(glval) = FieldAddress[bottomRight] : r0_6 +# 513| r0_12(Point) = Constant[0] : +# 513| mu0_13(Point) = Store : r0_11, r0_12 +# 514| r0_14(glval) = VariableAddress[r2] : +# 514| mu0_15(Rect) = Uninitialized : r0_14 +# 514| r0_16(glval) = FieldAddress[topLeft] : r0_14 +# 514| r0_17(glval) = FieldAddress[x] : r0_16 +# 514| r0_18(glval) = VariableAddress[x] : +# 514| r0_19(int) = Load : r0_18, mu0_1 +# 514| mu0_20(int) = Store : r0_17, r0_19 +# 514| r0_21(glval) = FieldAddress[y] : r0_16 +# 514| r0_22(glval) = VariableAddress[f] : +# 514| r0_23(float) = Load : r0_22, mu0_1 +# 514| r0_24(int) = Convert : r0_23 +# 514| mu0_25(int) = Store : r0_21, r0_24 +# 514| r0_26(glval) = FieldAddress[bottomRight] : r0_14 +# 514| r0_27(Point) = Constant[0] : +# 514| mu0_28(Point) = Store : r0_26, r0_27 +# 515| r0_29(glval) = VariableAddress[r3] : +# 515| mu0_30(Rect) = Uninitialized : r0_29 +# 515| r0_31(glval) = FieldAddress[topLeft] : r0_29 +# 515| r0_32(glval) = FieldAddress[x] : r0_31 +# 515| r0_33(glval) = VariableAddress[x] : +# 515| r0_34(int) = Load : r0_33, mu0_1 +# 515| mu0_35(int) = Store : r0_32, r0_34 +# 515| r0_36(glval) = FieldAddress[y] : r0_31 +# 515| r0_37(glval) = VariableAddress[f] : +# 515| r0_38(float) = Load : r0_37, mu0_1 +# 515| r0_39(int) = Convert : r0_38 +# 515| mu0_40(int) = Store : r0_36, r0_39 +# 515| r0_41(glval) = FieldAddress[bottomRight] : r0_29 +# 515| r0_42(glval) = FieldAddress[x] : r0_41 +# 515| r0_43(glval) = VariableAddress[x] : +# 515| r0_44(int) = Load : r0_43, mu0_1 +# 515| mu0_45(int) = Store : r0_42, r0_44 +# 515| r0_46(glval) = FieldAddress[y] : r0_41 +# 515| r0_47(glval) = VariableAddress[f] : +# 515| r0_48(float) = Load : r0_47, mu0_1 +# 515| r0_49(int) = Convert : r0_48 +# 515| mu0_50(int) = Store : r0_46, r0_49 +# 516| r0_51(glval) = VariableAddress[r4] : +# 516| mu0_52(Rect) = Uninitialized : r0_51 +# 516| r0_53(glval) = FieldAddress[topLeft] : r0_51 +# 516| r0_54(glval) = FieldAddress[x] : r0_53 +# 516| r0_55(glval) = VariableAddress[x] : +# 516| r0_56(int) = Load : r0_55, mu0_1 +# 516| mu0_57(int) = Store : r0_54, r0_56 +# 516| r0_58(glval) = FieldAddress[y] : r0_53 +# 516| r0_59(int) = Constant[0] : +# 516| mu0_60(int) = Store : r0_58, r0_59 +# 516| r0_61(glval) = FieldAddress[bottomRight] : r0_51 +# 516| r0_62(glval) = FieldAddress[x] : r0_61 +# 516| r0_63(glval) = VariableAddress[x] : +# 516| r0_64(int) = Load : r0_63, mu0_1 +# 516| mu0_65(int) = Store : r0_62, r0_64 +# 516| r0_66(glval) = FieldAddress[y] : r0_61 +# 516| r0_67(int) = Constant[0] : +# 516| mu0_68(int) = Store : r0_66, r0_67 +# 517| v0_69(void) = NoOp : +# 512| v0_70(void) = ReturnVoid : +# 512| v0_71(void) = UnmodeledUse : mu* +# 512| v0_72(void) = ExitFunction : # 519| ArrayInit(int, float) -> void # 519| Block 0 @@ -2251,40 +2304,43 @@ ir.cpp: # 519| r0_4(glval) = VariableAddress[f] : # 519| mu0_5(float) = InitializeParameter[f] : r0_4 # 520| r0_6(glval) = VariableAddress[a1] : -# 520| r0_7(int) = Constant[0] : -# 520| r0_8(glval) = PointerAdd : r0_6, r0_7 -# 520| r0_9(unknown[12]) = Constant[0] : -# 520| mu0_10(unknown[12]) = Store : r0_8, r0_9 -# 521| r0_11(glval) = VariableAddress[a2] : -# 521| r0_12(int) = Constant[0] : -# 521| r0_13(glval) = PointerAdd : r0_11, r0_12 -# 521| r0_14(glval) = VariableAddress[x] : -# 521| r0_15(int) = Load : r0_14, mu0_1 -# 521| mu0_16(int) = Store : r0_13, r0_15 -# 521| r0_17(int) = Constant[1] : -# 521| r0_18(glval) = PointerAdd : r0_11, r0_17 -# 521| r0_19(glval) = VariableAddress[f] : -# 521| r0_20(float) = Load : r0_19, mu0_1 -# 521| r0_21(int) = Convert : r0_20 -# 521| mu0_22(int) = Store : r0_18, r0_21 -# 521| r0_23(int) = Constant[2] : -# 521| r0_24(glval) = PointerAdd : r0_11, r0_23 -# 521| r0_25(int) = Constant[0] : -# 521| mu0_26(int) = Store : r0_24, r0_25 -# 522| r0_27(glval) = VariableAddress[a3] : -# 522| r0_28(int) = Constant[0] : -# 522| r0_29(glval) = PointerAdd : r0_27, r0_28 -# 522| r0_30(glval) = VariableAddress[x] : -# 522| r0_31(int) = Load : r0_30, mu0_1 -# 522| mu0_32(int) = Store : r0_29, r0_31 -# 522| r0_33(int) = Constant[1] : -# 522| r0_34(glval) = PointerAdd : r0_27, r0_33 -# 522| r0_35(unknown[8]) = Constant[0] : -# 522| mu0_36(unknown[8]) = Store : r0_34, r0_35 -# 523| v0_37(void) = NoOp : -# 519| v0_38(void) = ReturnVoid : -# 519| v0_39(void) = UnmodeledUse : mu* -# 519| v0_40(void) = ExitFunction : +# 520| mu0_7(int[3]) = Uninitialized : r0_6 +# 520| r0_8(int) = Constant[0] : +# 520| r0_9(glval) = PointerAdd : r0_6, r0_8 +# 520| r0_10(unknown[12]) = Constant[0] : +# 520| mu0_11(unknown[12]) = Store : r0_9, r0_10 +# 521| r0_12(glval) = VariableAddress[a2] : +# 521| mu0_13(int[3]) = Uninitialized : r0_12 +# 521| r0_14(int) = Constant[0] : +# 521| r0_15(glval) = PointerAdd : r0_12, r0_14 +# 521| r0_16(glval) = VariableAddress[x] : +# 521| r0_17(int) = Load : r0_16, mu0_1 +# 521| mu0_18(int) = Store : r0_15, r0_17 +# 521| r0_19(int) = Constant[1] : +# 521| r0_20(glval) = PointerAdd : r0_12, r0_19 +# 521| r0_21(glval) = VariableAddress[f] : +# 521| r0_22(float) = Load : r0_21, mu0_1 +# 521| r0_23(int) = Convert : r0_22 +# 521| mu0_24(int) = Store : r0_20, r0_23 +# 521| r0_25(int) = Constant[2] : +# 521| r0_26(glval) = PointerAdd : r0_12, r0_25 +# 521| r0_27(int) = Constant[0] : +# 521| mu0_28(int) = Store : r0_26, r0_27 +# 522| r0_29(glval) = VariableAddress[a3] : +# 522| mu0_30(int[3]) = Uninitialized : r0_29 +# 522| r0_31(int) = Constant[0] : +# 522| r0_32(glval) = PointerAdd : r0_29, r0_31 +# 522| r0_33(glval) = VariableAddress[x] : +# 522| r0_34(int) = Load : r0_33, mu0_1 +# 522| mu0_35(int) = Store : r0_32, r0_34 +# 522| r0_36(int) = Constant[1] : +# 522| r0_37(glval) = PointerAdd : r0_29, r0_36 +# 522| r0_38(unknown[8]) = Constant[0] : +# 522| mu0_39(unknown[8]) = Store : r0_37, r0_38 +# 523| v0_40(void) = NoOp : +# 519| v0_41(void) = ReturnVoid : +# 519| v0_42(void) = UnmodeledUse : mu* +# 519| v0_43(void) = ExitFunction : # 530| UnionInit(int, float) -> void # 530| Block 0 @@ -2295,15 +2351,16 @@ ir.cpp: # 530| r0_4(glval) = VariableAddress[f] : # 530| mu0_5(float) = InitializeParameter[f] : r0_4 # 531| r0_6(glval) = VariableAddress[u1] : -# 531| r0_7(glval) = FieldAddress[d] : r0_6 -# 531| r0_8(glval) = VariableAddress[f] : -# 531| r0_9(float) = Load : r0_8, mu0_1 -# 531| r0_10(double) = Convert : r0_9 -# 531| mu0_11(double) = Store : r0_7, r0_10 -# 533| v0_12(void) = NoOp : -# 530| v0_13(void) = ReturnVoid : -# 530| v0_14(void) = UnmodeledUse : mu* -# 530| v0_15(void) = ExitFunction : +# 531| mu0_7(U) = Uninitialized : r0_6 +# 531| r0_8(glval) = FieldAddress[d] : r0_6 +# 531| r0_9(glval) = VariableAddress[f] : +# 531| r0_10(float) = Load : r0_9, mu0_1 +# 531| r0_11(double) = Convert : r0_10 +# 531| mu0_12(double) = Store : r0_8, r0_11 +# 533| v0_13(void) = NoOp : +# 530| v0_14(void) = ReturnVoid : +# 530| v0_15(void) = UnmodeledUse : mu* +# 530| v0_16(void) = ExitFunction : # 535| EarlyReturn(int, int) -> void # 535| Block 0 @@ -2460,41 +2517,45 @@ ir.cpp: # 575| r0_18(glval) = VariableAddress[b] : # 575| mu0_19(char[2]) = Uninitialized : r0_18 # 576| r0_20(glval) = VariableAddress[c] : -# 576| r0_21(int) = Constant[0] : -# 576| r0_22(glval) = PointerAdd : r0_20, r0_21 -# 576| r0_23(unknown[2]) = Constant[0] : -# 576| mu0_24(unknown[2]) = Store : r0_22, r0_23 -# 577| r0_25(glval) = VariableAddress[d] : -# 577| r0_26(int) = Constant[0] : -# 577| r0_27(glval) = PointerAdd : r0_25, r0_26 -# 577| r0_28(char) = Constant[0] : -# 577| mu0_29(char) = Store : r0_27, r0_28 -# 577| r0_30(int) = Constant[1] : -# 577| r0_31(glval) = PointerAdd : r0_25, r0_30 -# 577| r0_32(char) = Constant[0] : -# 577| mu0_33(char) = Store : r0_31, r0_32 -# 578| r0_34(glval) = VariableAddress[e] : -# 578| r0_35(int) = Constant[0] : -# 578| r0_36(glval) = PointerAdd : r0_34, r0_35 -# 578| r0_37(char) = Constant[0] : -# 578| mu0_38(char) = Store : r0_36, r0_37 -# 578| r0_39(int) = Constant[1] : -# 578| r0_40(glval) = PointerAdd : r0_34, r0_39 -# 578| r0_41(char) = Constant[1] : -# 578| mu0_42(char) = Store : r0_40, r0_41 -# 579| r0_43(glval) = VariableAddress[f] : -# 579| r0_44(int) = Constant[0] : -# 579| r0_45(glval) = PointerAdd : r0_43, r0_44 -# 579| r0_46(char) = Constant[0] : -# 579| mu0_47(char) = Store : r0_45, r0_46 -# 579| r0_48(int) = Constant[1] : -# 579| r0_49(glval) = PointerAdd : r0_43, r0_48 -# 579| r0_50(unknown[2]) = Constant[0] : -# 579| mu0_51(unknown[2]) = Store : r0_49, r0_50 -# 580| v0_52(void) = NoOp : -# 571| v0_53(void) = ReturnVoid : -# 571| v0_54(void) = UnmodeledUse : mu* -# 571| v0_55(void) = ExitFunction : +# 576| mu0_21(char[2]) = Uninitialized : r0_20 +# 576| r0_22(int) = Constant[0] : +# 576| r0_23(glval) = PointerAdd : r0_20, r0_22 +# 576| r0_24(unknown[2]) = Constant[0] : +# 576| mu0_25(unknown[2]) = Store : r0_23, r0_24 +# 577| r0_26(glval) = VariableAddress[d] : +# 577| mu0_27(char[2]) = Uninitialized : r0_26 +# 577| r0_28(int) = Constant[0] : +# 577| r0_29(glval) = PointerAdd : r0_26, r0_28 +# 577| r0_30(char) = Constant[0] : +# 577| mu0_31(char) = Store : r0_29, r0_30 +# 577| r0_32(int) = Constant[1] : +# 577| r0_33(glval) = PointerAdd : r0_26, r0_32 +# 577| r0_34(char) = Constant[0] : +# 577| mu0_35(char) = Store : r0_33, r0_34 +# 578| r0_36(glval) = VariableAddress[e] : +# 578| mu0_37(char[2]) = Uninitialized : r0_36 +# 578| r0_38(int) = Constant[0] : +# 578| r0_39(glval) = PointerAdd : r0_36, r0_38 +# 578| r0_40(char) = Constant[0] : +# 578| mu0_41(char) = Store : r0_39, r0_40 +# 578| r0_42(int) = Constant[1] : +# 578| r0_43(glval) = PointerAdd : r0_36, r0_42 +# 578| r0_44(char) = Constant[1] : +# 578| mu0_45(char) = Store : r0_43, r0_44 +# 579| r0_46(glval) = VariableAddress[f] : +# 579| mu0_47(char[3]) = Uninitialized : r0_46 +# 579| r0_48(int) = Constant[0] : +# 579| r0_49(glval) = PointerAdd : r0_46, r0_48 +# 579| r0_50(char) = Constant[0] : +# 579| mu0_51(char) = Store : r0_49, r0_50 +# 579| r0_52(int) = Constant[1] : +# 579| r0_53(glval) = PointerAdd : r0_46, r0_52 +# 579| r0_54(unknown[2]) = Constant[0] : +# 579| mu0_55(unknown[2]) = Store : r0_53, r0_54 +# 580| v0_56(void) = NoOp : +# 571| v0_57(void) = ReturnVoid : +# 571| v0_58(void) = UnmodeledUse : mu* +# 571| v0_59(void) = ExitFunction : # 584| VarArgs() -> void # 584| Block 0 @@ -3891,10 +3952,11 @@ ir.cpp: # 961| v0_0(void) = EnterFunction : # 961| mu0_1(unknown) = UnmodeledDefinition : # 962| r0_2(glval) = VariableAddress[a1] : -# 962| r0_3(int) = Constant[0] : -# 962| r0_4(glval) = PointerAdd : r0_2, r0_3 -# 962| r0_5(unknown[8]) = Constant[0] : -# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5 +# 962| mu0_3(int[1000]) = Uninitialized : r0_2 +# 962| r0_4(int) = Constant[0] : +# 962| r0_5(glval) = PointerAdd : r0_2, r0_4 +# 962| r0_6(unknown[8]) = Constant[0] : +# 962| mu0_7(unknown[8]) = Store : r0_5, r0_6 #-----| Goto -> Block 2 # 962| Block 1 @@ -3931,3 +3993,147 @@ ir.cpp: # 962| r3_6(unknown[3588]) = Constant[0] : # 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6 #-----| Goto -> Block 2 + +# 966| IfStmtWithDeclaration(int, int) -> void +# 966| Block 0 +# 966| v0_0(void) = EnterFunction : +# 966| mu0_1(unknown) = UnmodeledDefinition : +# 966| r0_2(glval) = VariableAddress[x] : +# 966| mu0_3(int) = InitializeParameter[x] : r0_2 +# 966| r0_4(glval) = VariableAddress[y] : +# 966| mu0_5(int) = InitializeParameter[y] : r0_4 +# 967| r0_6(glval) = VariableAddress[b] : +# 967| r0_7(glval) = VariableAddress[x] : +# 967| r0_8(int) = Load : r0_7, mu0_1 +# 967| r0_9(glval) = VariableAddress[y] : +# 967| r0_10(int) = Load : r0_9, mu0_1 +# 967| r0_11(bool) = CompareLT : r0_8, r0_10 +# 967| mu0_12(bool) = Store : r0_6, r0_11 +# 967| r0_13(glval) = VariableAddress[b] : +# 967| r0_14(bool) = Load : r0_13, mu0_1 +# 967| v0_15(void) = ConditionalBranch : r0_14 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 968| Block 1 +# 968| r1_0(int) = Constant[5] : +# 968| r1_1(glval) = VariableAddress[x] : +# 968| mu1_2(int) = Store : r1_1, r1_0 +#-----| Goto -> Block 6 + +# 970| Block 2 +# 970| r2_0(glval) = VariableAddress[z] : +# 970| r2_1(glval) = VariableAddress[x] : +# 970| r2_2(int) = Load : r2_1, mu0_1 +# 970| r2_3(glval) = VariableAddress[y] : +# 970| r2_4(int) = Load : r2_3, mu0_1 +# 970| r2_5(int) = Add : r2_2, r2_4 +# 970| mu2_6(int) = Store : r2_0, r2_5 +# 970| r2_7(glval) = VariableAddress[z] : +# 970| r2_8(int) = Load : r2_7, mu0_1 +# 970| r2_9(int) = Constant[0] : +# 970| r2_10(bool) = CompareNE : r2_8, r2_9 +# 970| v2_11(void) = ConditionalBranch : r2_10 +#-----| False -> Block 4 +#-----| True -> Block 3 + +# 971| Block 3 +# 971| r3_0(int) = Constant[7] : +# 971| r3_1(glval) = VariableAddress[y] : +# 971| mu3_2(int) = Store : r3_1, r3_0 +#-----| Goto -> Block 6 + +# 973| Block 4 +# 973| r4_0(glval) = VariableAddress[p] : +# 973| r4_1(glval) = VariableAddress[x] : +# 973| mu4_2(int *) = Store : r4_0, r4_1 +# 973| r4_3(glval) = VariableAddress[p] : +# 973| r4_4(int *) = Load : r4_3, mu0_1 +# 973| r4_5(int *) = Constant[0] : +# 973| r4_6(bool) = CompareNE : r4_4, r4_5 +# 973| v4_7(void) = ConditionalBranch : r4_6 +#-----| False -> Block 6 +#-----| True -> Block 5 + +# 974| Block 5 +# 974| r5_0(int) = Constant[2] : +# 974| r5_1(glval) = VariableAddress[p] : +# 974| r5_2(int *) = Load : r5_1, mu0_1 +# 974| mu5_3(int) = Store : r5_2, r5_0 +#-----| Goto -> Block 6 + +# 976| Block 6 +# 976| v6_0(void) = NoOp : +# 966| v6_1(void) = ReturnVoid : +# 966| v6_2(void) = UnmodeledUse : mu* +# 966| v6_3(void) = ExitFunction : + +# 978| WhileStmtWithDeclaration(int, int) -> void +# 978| Block 0 +# 978| v0_0(void) = EnterFunction : +# 978| mu0_1(unknown) = UnmodeledDefinition : +# 978| r0_2(glval) = VariableAddress[x] : +# 978| mu0_3(int) = InitializeParameter[x] : r0_2 +# 978| r0_4(glval) = VariableAddress[y] : +# 978| mu0_5(int) = InitializeParameter[y] : r0_4 +#-----| Goto -> Block 7 + +# 979| Block 1 +# 979| v1_0(void) = NoOp : +#-----| Goto -> Block 7 + +# 981| Block 2 +# 981| r2_0(glval) = VariableAddress[z] : +# 981| r2_1(glval) = VariableAddress[x] : +# 981| r2_2(int) = Load : r2_1, mu0_1 +# 981| r2_3(glval) = VariableAddress[y] : +# 981| r2_4(int) = Load : r2_3, mu0_1 +# 981| r2_5(int) = Add : r2_2, r2_4 +# 981| mu2_6(int) = Store : r2_0, r2_5 +# 981| r2_7(glval) = VariableAddress[z] : +# 981| r2_8(int) = Load : r2_7, mu0_1 +# 981| r2_9(int) = Constant[0] : +# 981| r2_10(bool) = CompareNE : r2_8, r2_9 +# 981| v2_11(void) = ConditionalBranch : r2_10 +#-----| False -> Block 4 +#-----| True -> Block 3 + +# 981| Block 3 +# 981| v3_0(void) = NoOp : +#-----| Goto -> Block 2 + +# 983| Block 4 +# 983| r4_0(glval) = VariableAddress[p] : +# 983| r4_1(glval) = VariableAddress[x] : +# 983| mu4_2(int *) = Store : r4_0, r4_1 +# 983| r4_3(glval) = VariableAddress[p] : +# 983| r4_4(int *) = Load : r4_3, mu0_1 +# 983| r4_5(int *) = Constant[0] : +# 983| r4_6(bool) = CompareNE : r4_4, r4_5 +# 983| v4_7(void) = ConditionalBranch : r4_6 +#-----| False -> Block 6 +#-----| True -> Block 5 + +# 983| Block 5 +# 983| v5_0(void) = NoOp : +#-----| Goto -> Block 4 + +# 985| Block 6 +# 985| v6_0(void) = NoOp : +# 978| v6_1(void) = ReturnVoid : +# 978| v6_2(void) = UnmodeledUse : mu* +# 978| v6_3(void) = ExitFunction : + +# 979| Block 7 +# 979| r7_0(glval) = VariableAddress[b] : +# 979| r7_1(glval) = VariableAddress[x] : +# 979| r7_2(int) = Load : r7_1, mu0_1 +# 979| r7_3(glval) = VariableAddress[y] : +# 979| r7_4(int) = Load : r7_3, mu0_1 +# 979| r7_5(bool) = CompareLT : r7_2, r7_4 +# 979| mu7_6(bool) = Store : r7_0, r7_5 +# 979| r7_7(glval) = VariableAddress[b] : +# 979| r7_8(bool) = Load : r7_7, mu0_1 +# 979| v7_9(void) = ConditionalBranch : r7_8 +#-----| False -> Block 2 +#-----| True -> Block 1 diff --git a/cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected b/cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected index 0ef298fee3d..1c30402ee65 100644 --- a/cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected +++ b/cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected @@ -8,6 +8,8 @@ | IR: C | 1 | | IR: Call | 1 | | IR: CallAdd | 1 | +| IR: CallBadMemberFunction | 1 | +| IR: CallCopyConstructor | 1 | | IR: CallMethods | 1 | | IR: CallMin | 1 | | IR: CallNestedTemplateFunc | 1 | @@ -53,6 +55,7 @@ | IR: FunctionReferences | 1 | | IR: HierarchyConversions | 1 | | IR: IfStatements | 8 | +| IR: IfStmtWithDeclaration | 7 | | IR: InitArray | 1 | | IR: InitList | 1 | | IR: InitReference | 1 | @@ -73,6 +76,7 @@ | IR: OperatorNew | 1 | | IR: OperatorNewArray | 1 | | IR: Parameters | 1 | +| IR: Point | 1 | | IR: PointerCompare | 1 | | IR: PointerCrement | 1 | | IR: PointerOps | 1 | @@ -92,6 +96,7 @@ | IR: VarArgs | 1 | | IR: VirtualMemberFunction | 1 | | IR: WhileStatements | 4 | +| IR: WhileStmtWithDeclaration | 8 | | IR: designatedInit | 4 | | IR: min | 4 | | IR: operator= | 1 | diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected index af2385fb03d..8aa58507f26 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected @@ -1,3 +1,49 @@ +bad_asts.cpp: +# 14| Bad::CallBadMemberFunction() -> void +# 14| Block 0 +# 14| v0_0(void) = EnterFunction : +# 14| mu0_1(unknown) = UnmodeledDefinition : +# 15| r0_2(glval) = VariableAddress[s] : +# 15| mu0_3(S) = Uninitialized : r0_2 +# 15| r0_4(glval) = FieldAddress[x] : r0_2 +# 15| r0_5(int) = Constant[0] : +# 15| mu0_6(int) = Store : r0_4, r0_5 +# 16| r0_7(glval) = VariableAddress[s] : +# 16| r0_8(glval) = FunctionAddress[MemberFunction] : +# 16| r0_9(int) = Constant[1] : +# 16| r0_10(int) = Call : r0_8, this:r0_7, r0_9 +# 17| v0_11(void) = NoOp : +# 14| v0_12(void) = ReturnVoid : +# 14| v0_13(void) = UnmodeledUse : mu* +# 14| v0_14(void) = ExitFunction : + +# 22| Bad::Point::Point() -> void +# 22| Block 0 +# 22| v0_0(void) = EnterFunction : +# 22| mu0_1(unknown) = UnmodeledDefinition : +# 22| r0_2(glval) = InitializeThis : +# 23| v0_3(void) = NoOp : +# 22| v0_4(void) = ReturnVoid : +# 22| v0_5(void) = UnmodeledUse : mu* +# 22| v0_6(void) = ExitFunction : + +# 26| Bad::CallCopyConstructor(const Point &) -> void +# 26| Block 0 +# 26| v0_0(void) = EnterFunction : +# 26| mu0_1(unknown) = UnmodeledDefinition : +# 26| r0_2(glval) = VariableAddress[a] : +# 26| m0_3(Point &) = InitializeParameter[a] : r0_2 +# 27| r0_4(glval) = VariableAddress[b] : +# 27| r0_5(glval) = VariableAddress[a] : +# 27| r0_6(Point &) = Load : r0_5, m0_3 +# 27| r0_7(glval) = Convert : r0_6 +# 27| r0_8(Point) = Load : r0_7, mu0_1 +# 27| m0_9(Point) = Store : r0_4, r0_8 +# 28| v0_10(void) = NoOp : +# 26| v0_11(void) = ReturnVoid : +# 26| v0_12(void) = UnmodeledUse : mu* +# 26| v0_13(void) = ExitFunction : + ir.cpp: # 1| Constants() -> void # 1| Block 0 @@ -2152,40 +2198,43 @@ ir.cpp: # 503| r0_4(glval) = VariableAddress[f] : # 503| m0_5(float) = InitializeParameter[f] : r0_4 # 504| r0_6(glval) = VariableAddress[pt1] : -# 504| r0_7(glval) = FieldAddress[x] : r0_6 -# 504| r0_8(glval) = VariableAddress[x] : -# 504| r0_9(int) = Load : r0_8, m0_3 -# 504| m0_10(int) = Store : r0_7, r0_9 -# 504| r0_11(glval) = FieldAddress[y] : r0_6 -# 504| r0_12(glval) = VariableAddress[f] : -# 504| r0_13(float) = Load : r0_12, m0_5 -# 504| r0_14(int) = Convert : r0_13 -# 504| mu0_15(int) = Store : r0_11, r0_14 -# 505| r0_16(glval) = VariableAddress[pt2] : -# 505| r0_17(glval) = FieldAddress[x] : r0_16 -# 505| r0_18(glval) = VariableAddress[x] : -# 505| r0_19(int) = Load : r0_18, m0_3 -# 505| m0_20(int) = Store : r0_17, r0_19 -# 505| r0_21(glval) = FieldAddress[y] : r0_16 -# 505| r0_22(int) = Constant[0] : -# 505| mu0_23(int) = Store : r0_21, r0_22 -# 506| r0_24(glval) = VariableAddress[pt3] : -# 506| r0_25(glval) = FieldAddress[x] : r0_24 -# 506| r0_26(int) = Constant[0] : -# 506| m0_27(int) = Store : r0_25, r0_26 -# 506| r0_28(glval) = FieldAddress[y] : r0_24 +# 504| m0_7(Point) = Uninitialized : r0_6 +# 504| r0_8(glval) = FieldAddress[x] : r0_6 +# 504| r0_9(glval) = VariableAddress[x] : +# 504| r0_10(int) = Load : r0_9, m0_3 +# 504| m0_11(int) = Store : r0_8, r0_10 +# 504| r0_12(glval) = FieldAddress[y] : r0_6 +# 504| r0_13(glval) = VariableAddress[f] : +# 504| r0_14(float) = Load : r0_13, m0_5 +# 504| r0_15(int) = Convert : r0_14 +# 504| mu0_16(int) = Store : r0_12, r0_15 +# 505| r0_17(glval) = VariableAddress[pt2] : +# 505| m0_18(Point) = Uninitialized : r0_17 +# 505| r0_19(glval) = FieldAddress[x] : r0_17 +# 505| r0_20(glval) = VariableAddress[x] : +# 505| r0_21(int) = Load : r0_20, m0_3 +# 505| m0_22(int) = Store : r0_19, r0_21 +# 505| r0_23(glval) = FieldAddress[y] : r0_17 +# 505| r0_24(int) = Constant[0] : +# 505| mu0_25(int) = Store : r0_23, r0_24 +# 506| r0_26(glval) = VariableAddress[pt3] : +# 506| m0_27(Point) = Uninitialized : r0_26 +# 506| r0_28(glval) = FieldAddress[x] : r0_26 # 506| r0_29(int) = Constant[0] : -# 506| mu0_30(int) = Store : r0_28, r0_29 -# 508| r0_31(glval) = VariableAddress[x1] : -# 508| r0_32(int) = Constant[1] : -# 508| m0_33(int) = Store : r0_31, r0_32 -# 509| r0_34(glval) = VariableAddress[x2] : -# 509| r0_35(int) = Constant[0] : -# 509| m0_36(int) = Store : r0_34, r0_35 -# 510| v0_37(void) = NoOp : -# 503| v0_38(void) = ReturnVoid : -# 503| v0_39(void) = UnmodeledUse : mu* -# 503| v0_40(void) = ExitFunction : +# 506| m0_30(int) = Store : r0_28, r0_29 +# 506| r0_31(glval) = FieldAddress[y] : r0_26 +# 506| r0_32(int) = Constant[0] : +# 506| mu0_33(int) = Store : r0_31, r0_32 +# 508| r0_34(glval) = VariableAddress[x1] : +# 508| r0_35(int) = Constant[1] : +# 508| m0_36(int) = Store : r0_34, r0_35 +# 509| r0_37(glval) = VariableAddress[x2] : +# 509| r0_38(int) = Constant[0] : +# 509| m0_39(int) = Store : r0_37, r0_38 +# 510| v0_40(void) = NoOp : +# 503| v0_41(void) = ReturnVoid : +# 503| v0_42(void) = UnmodeledUse : mu* +# 503| v0_43(void) = ExitFunction : # 512| NestedInitList(int, float) -> void # 512| Block 0 @@ -2196,68 +2245,72 @@ ir.cpp: # 512| r0_4(glval) = VariableAddress[f] : # 512| m0_5(float) = InitializeParameter[f] : r0_4 # 513| r0_6(glval) = VariableAddress[r1] : -# 513| r0_7(glval) = FieldAddress[topLeft] : r0_6 -# 513| r0_8(Point) = Constant[0] : -# 513| m0_9(Point) = Store : r0_7, r0_8 -# 513| r0_10(glval) = FieldAddress[bottomRight] : r0_6 -# 513| r0_11(Point) = Constant[0] : -# 513| mu0_12(Point) = Store : r0_10, r0_11 -# 514| r0_13(glval) = VariableAddress[r2] : -# 514| r0_14(glval) = FieldAddress[topLeft] : r0_13 -# 514| r0_15(glval) = FieldAddress[x] : r0_14 -# 514| r0_16(glval) = VariableAddress[x] : -# 514| r0_17(int) = Load : r0_16, m0_3 -# 514| m0_18(int) = Store : r0_15, r0_17 -# 514| r0_19(glval) = FieldAddress[y] : r0_14 -# 514| r0_20(glval) = VariableAddress[f] : -# 514| r0_21(float) = Load : r0_20, m0_5 -# 514| r0_22(int) = Convert : r0_21 -# 514| mu0_23(int) = Store : r0_19, r0_22 -# 514| r0_24(glval) = FieldAddress[bottomRight] : r0_13 -# 514| r0_25(Point) = Constant[0] : -# 514| mu0_26(Point) = Store : r0_24, r0_25 -# 515| r0_27(glval) = VariableAddress[r3] : -# 515| r0_28(glval) = FieldAddress[topLeft] : r0_27 -# 515| r0_29(glval) = FieldAddress[x] : r0_28 -# 515| r0_30(glval) = VariableAddress[x] : -# 515| r0_31(int) = Load : r0_30, m0_3 -# 515| m0_32(int) = Store : r0_29, r0_31 -# 515| r0_33(glval) = FieldAddress[y] : r0_28 -# 515| r0_34(glval) = VariableAddress[f] : -# 515| r0_35(float) = Load : r0_34, m0_5 -# 515| r0_36(int) = Convert : r0_35 -# 515| mu0_37(int) = Store : r0_33, r0_36 -# 515| r0_38(glval) = FieldAddress[bottomRight] : r0_27 -# 515| r0_39(glval) = FieldAddress[x] : r0_38 -# 515| r0_40(glval) = VariableAddress[x] : -# 515| r0_41(int) = Load : r0_40, m0_3 -# 515| mu0_42(int) = Store : r0_39, r0_41 -# 515| r0_43(glval) = FieldAddress[y] : r0_38 -# 515| r0_44(glval) = VariableAddress[f] : -# 515| r0_45(float) = Load : r0_44, m0_5 -# 515| r0_46(int) = Convert : r0_45 -# 515| mu0_47(int) = Store : r0_43, r0_46 -# 516| r0_48(glval) = VariableAddress[r4] : -# 516| r0_49(glval) = FieldAddress[topLeft] : r0_48 -# 516| r0_50(glval) = FieldAddress[x] : r0_49 -# 516| r0_51(glval) = VariableAddress[x] : -# 516| r0_52(int) = Load : r0_51, m0_3 -# 516| m0_53(int) = Store : r0_50, r0_52 -# 516| r0_54(glval) = FieldAddress[y] : r0_49 -# 516| r0_55(int) = Constant[0] : -# 516| mu0_56(int) = Store : r0_54, r0_55 -# 516| r0_57(glval) = FieldAddress[bottomRight] : r0_48 -# 516| r0_58(glval) = FieldAddress[x] : r0_57 -# 516| r0_59(glval) = VariableAddress[x] : -# 516| r0_60(int) = Load : r0_59, m0_3 -# 516| mu0_61(int) = Store : r0_58, r0_60 -# 516| r0_62(glval) = FieldAddress[y] : r0_57 -# 516| r0_63(int) = Constant[0] : -# 516| mu0_64(int) = Store : r0_62, r0_63 -# 517| v0_65(void) = NoOp : -# 512| v0_66(void) = ReturnVoid : -# 512| v0_67(void) = UnmodeledUse : mu* -# 512| v0_68(void) = ExitFunction : +# 513| m0_7(Rect) = Uninitialized : r0_6 +# 513| r0_8(glval) = FieldAddress[topLeft] : r0_6 +# 513| r0_9(Point) = Constant[0] : +# 513| m0_10(Point) = Store : r0_8, r0_9 +# 513| r0_11(glval) = FieldAddress[bottomRight] : r0_6 +# 513| r0_12(Point) = Constant[0] : +# 513| mu0_13(Point) = Store : r0_11, r0_12 +# 514| r0_14(glval) = VariableAddress[r2] : +# 514| m0_15(Rect) = Uninitialized : r0_14 +# 514| r0_16(glval) = FieldAddress[topLeft] : r0_14 +# 514| r0_17(glval) = FieldAddress[x] : r0_16 +# 514| r0_18(glval) = VariableAddress[x] : +# 514| r0_19(int) = Load : r0_18, m0_3 +# 514| m0_20(int) = Store : r0_17, r0_19 +# 514| r0_21(glval) = FieldAddress[y] : r0_16 +# 514| r0_22(glval) = VariableAddress[f] : +# 514| r0_23(float) = Load : r0_22, m0_5 +# 514| r0_24(int) = Convert : r0_23 +# 514| mu0_25(int) = Store : r0_21, r0_24 +# 514| r0_26(glval) = FieldAddress[bottomRight] : r0_14 +# 514| r0_27(Point) = Constant[0] : +# 514| mu0_28(Point) = Store : r0_26, r0_27 +# 515| r0_29(glval) = VariableAddress[r3] : +# 515| m0_30(Rect) = Uninitialized : r0_29 +# 515| r0_31(glval) = FieldAddress[topLeft] : r0_29 +# 515| r0_32(glval) = FieldAddress[x] : r0_31 +# 515| r0_33(glval) = VariableAddress[x] : +# 515| r0_34(int) = Load : r0_33, m0_3 +# 515| m0_35(int) = Store : r0_32, r0_34 +# 515| r0_36(glval) = FieldAddress[y] : r0_31 +# 515| r0_37(glval) = VariableAddress[f] : +# 515| r0_38(float) = Load : r0_37, m0_5 +# 515| r0_39(int) = Convert : r0_38 +# 515| mu0_40(int) = Store : r0_36, r0_39 +# 515| r0_41(glval) = FieldAddress[bottomRight] : r0_29 +# 515| r0_42(glval) = FieldAddress[x] : r0_41 +# 515| r0_43(glval) = VariableAddress[x] : +# 515| r0_44(int) = Load : r0_43, m0_3 +# 515| mu0_45(int) = Store : r0_42, r0_44 +# 515| r0_46(glval) = FieldAddress[y] : r0_41 +# 515| r0_47(glval) = VariableAddress[f] : +# 515| r0_48(float) = Load : r0_47, m0_5 +# 515| r0_49(int) = Convert : r0_48 +# 515| mu0_50(int) = Store : r0_46, r0_49 +# 516| r0_51(glval) = VariableAddress[r4] : +# 516| m0_52(Rect) = Uninitialized : r0_51 +# 516| r0_53(glval) = FieldAddress[topLeft] : r0_51 +# 516| r0_54(glval) = FieldAddress[x] : r0_53 +# 516| r0_55(glval) = VariableAddress[x] : +# 516| r0_56(int) = Load : r0_55, m0_3 +# 516| m0_57(int) = Store : r0_54, r0_56 +# 516| r0_58(glval) = FieldAddress[y] : r0_53 +# 516| r0_59(int) = Constant[0] : +# 516| mu0_60(int) = Store : r0_58, r0_59 +# 516| r0_61(glval) = FieldAddress[bottomRight] : r0_51 +# 516| r0_62(glval) = FieldAddress[x] : r0_61 +# 516| r0_63(glval) = VariableAddress[x] : +# 516| r0_64(int) = Load : r0_63, m0_3 +# 516| mu0_65(int) = Store : r0_62, r0_64 +# 516| r0_66(glval) = FieldAddress[y] : r0_61 +# 516| r0_67(int) = Constant[0] : +# 516| mu0_68(int) = Store : r0_66, r0_67 +# 517| v0_69(void) = NoOp : +# 512| v0_70(void) = ReturnVoid : +# 512| v0_71(void) = UnmodeledUse : mu* +# 512| v0_72(void) = ExitFunction : # 519| ArrayInit(int, float) -> void # 519| Block 0 @@ -2268,40 +2321,43 @@ ir.cpp: # 519| r0_4(glval) = VariableAddress[f] : # 519| m0_5(float) = InitializeParameter[f] : r0_4 # 520| r0_6(glval) = VariableAddress[a1] : -# 520| r0_7(int) = Constant[0] : -# 520| r0_8(glval) = PointerAdd : r0_6, r0_7 -# 520| r0_9(unknown[12]) = Constant[0] : -# 520| mu0_10(unknown[12]) = Store : r0_8, r0_9 -# 521| r0_11(glval) = VariableAddress[a2] : -# 521| r0_12(int) = Constant[0] : -# 521| r0_13(glval) = PointerAdd : r0_11, r0_12 -# 521| r0_14(glval) = VariableAddress[x] : -# 521| r0_15(int) = Load : r0_14, m0_3 -# 521| mu0_16(int) = Store : r0_13, r0_15 -# 521| r0_17(int) = Constant[1] : -# 521| r0_18(glval) = PointerAdd : r0_11, r0_17 -# 521| r0_19(glval) = VariableAddress[f] : -# 521| r0_20(float) = Load : r0_19, m0_5 -# 521| r0_21(int) = Convert : r0_20 -# 521| mu0_22(int) = Store : r0_18, r0_21 -# 521| r0_23(int) = Constant[2] : -# 521| r0_24(glval) = PointerAdd : r0_11, r0_23 -# 521| r0_25(int) = Constant[0] : -# 521| mu0_26(int) = Store : r0_24, r0_25 -# 522| r0_27(glval) = VariableAddress[a3] : -# 522| r0_28(int) = Constant[0] : -# 522| r0_29(glval) = PointerAdd : r0_27, r0_28 -# 522| r0_30(glval) = VariableAddress[x] : -# 522| r0_31(int) = Load : r0_30, m0_3 -# 522| mu0_32(int) = Store : r0_29, r0_31 -# 522| r0_33(int) = Constant[1] : -# 522| r0_34(glval) = PointerAdd : r0_27, r0_33 -# 522| r0_35(unknown[8]) = Constant[0] : -# 522| mu0_36(unknown[8]) = Store : r0_34, r0_35 -# 523| v0_37(void) = NoOp : -# 519| v0_38(void) = ReturnVoid : -# 519| v0_39(void) = UnmodeledUse : mu* -# 519| v0_40(void) = ExitFunction : +# 520| mu0_7(int[3]) = Uninitialized : r0_6 +# 520| r0_8(int) = Constant[0] : +# 520| r0_9(glval) = PointerAdd : r0_6, r0_8 +# 520| r0_10(unknown[12]) = Constant[0] : +# 520| mu0_11(unknown[12]) = Store : r0_9, r0_10 +# 521| r0_12(glval) = VariableAddress[a2] : +# 521| mu0_13(int[3]) = Uninitialized : r0_12 +# 521| r0_14(int) = Constant[0] : +# 521| r0_15(glval) = PointerAdd : r0_12, r0_14 +# 521| r0_16(glval) = VariableAddress[x] : +# 521| r0_17(int) = Load : r0_16, m0_3 +# 521| mu0_18(int) = Store : r0_15, r0_17 +# 521| r0_19(int) = Constant[1] : +# 521| r0_20(glval) = PointerAdd : r0_12, r0_19 +# 521| r0_21(glval) = VariableAddress[f] : +# 521| r0_22(float) = Load : r0_21, m0_5 +# 521| r0_23(int) = Convert : r0_22 +# 521| mu0_24(int) = Store : r0_20, r0_23 +# 521| r0_25(int) = Constant[2] : +# 521| r0_26(glval) = PointerAdd : r0_12, r0_25 +# 521| r0_27(int) = Constant[0] : +# 521| mu0_28(int) = Store : r0_26, r0_27 +# 522| r0_29(glval) = VariableAddress[a3] : +# 522| mu0_30(int[3]) = Uninitialized : r0_29 +# 522| r0_31(int) = Constant[0] : +# 522| r0_32(glval) = PointerAdd : r0_29, r0_31 +# 522| r0_33(glval) = VariableAddress[x] : +# 522| r0_34(int) = Load : r0_33, m0_3 +# 522| mu0_35(int) = Store : r0_32, r0_34 +# 522| r0_36(int) = Constant[1] : +# 522| r0_37(glval) = PointerAdd : r0_29, r0_36 +# 522| r0_38(unknown[8]) = Constant[0] : +# 522| mu0_39(unknown[8]) = Store : r0_37, r0_38 +# 523| v0_40(void) = NoOp : +# 519| v0_41(void) = ReturnVoid : +# 519| v0_42(void) = UnmodeledUse : mu* +# 519| v0_43(void) = ExitFunction : # 530| UnionInit(int, float) -> void # 530| Block 0 @@ -2312,15 +2368,16 @@ ir.cpp: # 530| r0_4(glval) = VariableAddress[f] : # 530| m0_5(float) = InitializeParameter[f] : r0_4 # 531| r0_6(glval) = VariableAddress[u1] : -# 531| r0_7(glval) = FieldAddress[d] : r0_6 -# 531| r0_8(glval) = VariableAddress[f] : -# 531| r0_9(float) = Load : r0_8, m0_5 -# 531| r0_10(double) = Convert : r0_9 -# 531| m0_11(double) = Store : r0_7, r0_10 -# 533| v0_12(void) = NoOp : -# 530| v0_13(void) = ReturnVoid : -# 530| v0_14(void) = UnmodeledUse : mu* -# 530| v0_15(void) = ExitFunction : +# 531| m0_7(U) = Uninitialized : r0_6 +# 531| r0_8(glval) = FieldAddress[d] : r0_6 +# 531| r0_9(glval) = VariableAddress[f] : +# 531| r0_10(float) = Load : r0_9, m0_5 +# 531| r0_11(double) = Convert : r0_10 +# 531| m0_12(double) = Store : r0_8, r0_11 +# 533| v0_13(void) = NoOp : +# 530| v0_14(void) = ReturnVoid : +# 530| v0_15(void) = UnmodeledUse : mu* +# 530| v0_16(void) = ExitFunction : # 535| EarlyReturn(int, int) -> void # 535| Block 0 @@ -2479,41 +2536,45 @@ ir.cpp: # 575| r0_18(glval) = VariableAddress[b] : # 575| m0_19(char[2]) = Uninitialized : r0_18 # 576| r0_20(glval) = VariableAddress[c] : -# 576| r0_21(int) = Constant[0] : -# 576| r0_22(glval) = PointerAdd : r0_20, r0_21 -# 576| r0_23(unknown[2]) = Constant[0] : -# 576| mu0_24(unknown[2]) = Store : r0_22, r0_23 -# 577| r0_25(glval) = VariableAddress[d] : -# 577| r0_26(int) = Constant[0] : -# 577| r0_27(glval) = PointerAdd : r0_25, r0_26 -# 577| r0_28(char) = Constant[0] : -# 577| mu0_29(char) = Store : r0_27, r0_28 -# 577| r0_30(int) = Constant[1] : -# 577| r0_31(glval) = PointerAdd : r0_25, r0_30 -# 577| r0_32(char) = Constant[0] : -# 577| mu0_33(char) = Store : r0_31, r0_32 -# 578| r0_34(glval) = VariableAddress[e] : -# 578| r0_35(int) = Constant[0] : -# 578| r0_36(glval) = PointerAdd : r0_34, r0_35 -# 578| r0_37(char) = Constant[0] : -# 578| mu0_38(char) = Store : r0_36, r0_37 -# 578| r0_39(int) = Constant[1] : -# 578| r0_40(glval) = PointerAdd : r0_34, r0_39 -# 578| r0_41(char) = Constant[1] : -# 578| mu0_42(char) = Store : r0_40, r0_41 -# 579| r0_43(glval) = VariableAddress[f] : -# 579| r0_44(int) = Constant[0] : -# 579| r0_45(glval) = PointerAdd : r0_43, r0_44 -# 579| r0_46(char) = Constant[0] : -# 579| mu0_47(char) = Store : r0_45, r0_46 -# 579| r0_48(int) = Constant[1] : -# 579| r0_49(glval) = PointerAdd : r0_43, r0_48 -# 579| r0_50(unknown[2]) = Constant[0] : -# 579| mu0_51(unknown[2]) = Store : r0_49, r0_50 -# 580| v0_52(void) = NoOp : -# 571| v0_53(void) = ReturnVoid : -# 571| v0_54(void) = UnmodeledUse : mu* -# 571| v0_55(void) = ExitFunction : +# 576| mu0_21(char[2]) = Uninitialized : r0_20 +# 576| r0_22(int) = Constant[0] : +# 576| r0_23(glval) = PointerAdd : r0_20, r0_22 +# 576| r0_24(unknown[2]) = Constant[0] : +# 576| mu0_25(unknown[2]) = Store : r0_23, r0_24 +# 577| r0_26(glval) = VariableAddress[d] : +# 577| mu0_27(char[2]) = Uninitialized : r0_26 +# 577| r0_28(int) = Constant[0] : +# 577| r0_29(glval) = PointerAdd : r0_26, r0_28 +# 577| r0_30(char) = Constant[0] : +# 577| mu0_31(char) = Store : r0_29, r0_30 +# 577| r0_32(int) = Constant[1] : +# 577| r0_33(glval) = PointerAdd : r0_26, r0_32 +# 577| r0_34(char) = Constant[0] : +# 577| mu0_35(char) = Store : r0_33, r0_34 +# 578| r0_36(glval) = VariableAddress[e] : +# 578| mu0_37(char[2]) = Uninitialized : r0_36 +# 578| r0_38(int) = Constant[0] : +# 578| r0_39(glval) = PointerAdd : r0_36, r0_38 +# 578| r0_40(char) = Constant[0] : +# 578| mu0_41(char) = Store : r0_39, r0_40 +# 578| r0_42(int) = Constant[1] : +# 578| r0_43(glval) = PointerAdd : r0_36, r0_42 +# 578| r0_44(char) = Constant[1] : +# 578| mu0_45(char) = Store : r0_43, r0_44 +# 579| r0_46(glval) = VariableAddress[f] : +# 579| mu0_47(char[3]) = Uninitialized : r0_46 +# 579| r0_48(int) = Constant[0] : +# 579| r0_49(glval) = PointerAdd : r0_46, r0_48 +# 579| r0_50(char) = Constant[0] : +# 579| mu0_51(char) = Store : r0_49, r0_50 +# 579| r0_52(int) = Constant[1] : +# 579| r0_53(glval) = PointerAdd : r0_46, r0_52 +# 579| r0_54(unknown[2]) = Constant[0] : +# 579| mu0_55(unknown[2]) = Store : r0_53, r0_54 +# 580| v0_56(void) = NoOp : +# 571| v0_57(void) = ReturnVoid : +# 571| v0_58(void) = UnmodeledUse : mu* +# 571| v0_59(void) = ExitFunction : # 584| VarArgs() -> void # 584| Block 0 @@ -3912,10 +3973,11 @@ ir.cpp: # 961| v0_0(void) = EnterFunction : # 961| mu0_1(unknown) = UnmodeledDefinition : # 962| r0_2(glval) = VariableAddress[a1] : -# 962| r0_3(int) = Constant[0] : -# 962| r0_4(glval) = PointerAdd : r0_2, r0_3 -# 962| r0_5(unknown[8]) = Constant[0] : -# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5 +# 962| mu0_3(int[1000]) = Uninitialized : r0_2 +# 962| r0_4(int) = Constant[0] : +# 962| r0_5(glval) = PointerAdd : r0_2, r0_4 +# 962| r0_6(unknown[8]) = Constant[0] : +# 962| mu0_7(unknown[8]) = Store : r0_5, r0_6 #-----| Goto -> Block 2 # 962| Block 1 @@ -3952,3 +4014,147 @@ ir.cpp: # 962| r3_6(unknown[3588]) = Constant[0] : # 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6 #-----| Goto -> Block 2 + +# 966| IfStmtWithDeclaration(int, int) -> void +# 966| Block 0 +# 966| v0_0(void) = EnterFunction : +# 966| mu0_1(unknown) = UnmodeledDefinition : +# 966| r0_2(glval) = VariableAddress[x] : +# 966| mu0_3(int) = InitializeParameter[x] : r0_2 +# 966| r0_4(glval) = VariableAddress[y] : +# 966| m0_5(int) = InitializeParameter[y] : r0_4 +# 967| r0_6(glval) = VariableAddress[b] : +# 967| r0_7(glval) = VariableAddress[x] : +# 967| r0_8(int) = Load : r0_7, mu0_1 +# 967| r0_9(glval) = VariableAddress[y] : +# 967| r0_10(int) = Load : r0_9, m0_5 +# 967| r0_11(bool) = CompareLT : r0_8, r0_10 +# 967| m0_12(bool) = Store : r0_6, r0_11 +# 967| r0_13(glval) = VariableAddress[b] : +# 967| r0_14(bool) = Load : r0_13, m0_12 +# 967| v0_15(void) = ConditionalBranch : r0_14 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 968| Block 1 +# 968| r1_0(int) = Constant[5] : +# 968| r1_1(glval) = VariableAddress[x] : +# 968| mu1_2(int) = Store : r1_1, r1_0 +#-----| Goto -> Block 6 + +# 970| Block 2 +# 970| r2_0(glval) = VariableAddress[z] : +# 970| r2_1(glval) = VariableAddress[x] : +# 970| r2_2(int) = Load : r2_1, mu0_1 +# 970| r2_3(glval) = VariableAddress[y] : +# 970| r2_4(int) = Load : r2_3, m0_5 +# 970| r2_5(int) = Add : r2_2, r2_4 +# 970| m2_6(int) = Store : r2_0, r2_5 +# 970| r2_7(glval) = VariableAddress[z] : +# 970| r2_8(int) = Load : r2_7, m2_6 +# 970| r2_9(int) = Constant[0] : +# 970| r2_10(bool) = CompareNE : r2_8, r2_9 +# 970| v2_11(void) = ConditionalBranch : r2_10 +#-----| False -> Block 4 +#-----| True -> Block 3 + +# 971| Block 3 +# 971| r3_0(int) = Constant[7] : +# 971| r3_1(glval) = VariableAddress[y] : +# 971| m3_2(int) = Store : r3_1, r3_0 +#-----| Goto -> Block 6 + +# 973| Block 4 +# 973| r4_0(glval) = VariableAddress[p] : +# 973| r4_1(glval) = VariableAddress[x] : +# 973| m4_2(int *) = Store : r4_0, r4_1 +# 973| r4_3(glval) = VariableAddress[p] : +# 973| r4_4(int *) = Load : r4_3, m4_2 +# 973| r4_5(int *) = Constant[0] : +# 973| r4_6(bool) = CompareNE : r4_4, r4_5 +# 973| v4_7(void) = ConditionalBranch : r4_6 +#-----| False -> Block 6 +#-----| True -> Block 5 + +# 974| Block 5 +# 974| r5_0(int) = Constant[2] : +# 974| r5_1(glval) = VariableAddress[p] : +# 974| r5_2(int *) = Load : r5_1, m4_2 +# 974| mu5_3(int) = Store : r5_2, r5_0 +#-----| Goto -> Block 6 + +# 976| Block 6 +# 976| v6_0(void) = NoOp : +# 966| v6_1(void) = ReturnVoid : +# 966| v6_2(void) = UnmodeledUse : mu* +# 966| v6_3(void) = ExitFunction : + +# 978| WhileStmtWithDeclaration(int, int) -> void +# 978| Block 0 +# 978| v0_0(void) = EnterFunction : +# 978| mu0_1(unknown) = UnmodeledDefinition : +# 978| r0_2(glval) = VariableAddress[x] : +# 978| mu0_3(int) = InitializeParameter[x] : r0_2 +# 978| r0_4(glval) = VariableAddress[y] : +# 978| m0_5(int) = InitializeParameter[y] : r0_4 +#-----| Goto -> Block 7 + +# 979| Block 1 +# 979| v1_0(void) = NoOp : +#-----| Goto -> Block 7 + +# 981| Block 2 +# 981| r2_0(glval) = VariableAddress[z] : +# 981| r2_1(glval) = VariableAddress[x] : +# 981| r2_2(int) = Load : r2_1, mu0_1 +# 981| r2_3(glval) = VariableAddress[y] : +# 981| r2_4(int) = Load : r2_3, m0_5 +# 981| r2_5(int) = Add : r2_2, r2_4 +# 981| m2_6(int) = Store : r2_0, r2_5 +# 981| r2_7(glval) = VariableAddress[z] : +# 981| r2_8(int) = Load : r2_7, m2_6 +# 981| r2_9(int) = Constant[0] : +# 981| r2_10(bool) = CompareNE : r2_8, r2_9 +# 981| v2_11(void) = ConditionalBranch : r2_10 +#-----| False -> Block 4 +#-----| True -> Block 3 + +# 981| Block 3 +# 981| v3_0(void) = NoOp : +#-----| Goto -> Block 2 + +# 983| Block 4 +# 983| r4_0(glval) = VariableAddress[p] : +# 983| r4_1(glval) = VariableAddress[x] : +# 983| m4_2(int *) = Store : r4_0, r4_1 +# 983| r4_3(glval) = VariableAddress[p] : +# 983| r4_4(int *) = Load : r4_3, m4_2 +# 983| r4_5(int *) = Constant[0] : +# 983| r4_6(bool) = CompareNE : r4_4, r4_5 +# 983| v4_7(void) = ConditionalBranch : r4_6 +#-----| False -> Block 6 +#-----| True -> Block 5 + +# 983| Block 5 +# 983| v5_0(void) = NoOp : +#-----| Goto -> Block 4 + +# 985| Block 6 +# 985| v6_0(void) = NoOp : +# 978| v6_1(void) = ReturnVoid : +# 978| v6_2(void) = UnmodeledUse : mu* +# 978| v6_3(void) = ExitFunction : + +# 979| Block 7 +# 979| r7_0(glval) = VariableAddress[b] : +# 979| r7_1(glval) = VariableAddress[x] : +# 979| r7_2(int) = Load : r7_1, mu0_1 +# 979| r7_3(glval) = VariableAddress[y] : +# 979| r7_4(int) = Load : r7_3, m0_5 +# 979| r7_5(bool) = CompareLT : r7_2, r7_4 +# 979| m7_6(bool) = Store : r7_0, r7_5 +# 979| r7_7(glval) = VariableAddress[b] : +# 979| r7_8(bool) = Load : r7_7, m7_6 +# 979| v7_9(void) = ConditionalBranch : r7_8 +#-----| False -> Block 2 +#-----| True -> Block 1 diff --git a/cpp/ql/test/library-tests/opts/main.cpp b/cpp/ql/test/library-tests/opts/main.cpp index 2f78971c3fc..881cd001ad3 100644 --- a/cpp/ql/test/library-tests/opts/main.cpp +++ b/cpp/ql/test/library-tests/opts/main.cpp @@ -1,8 +1,8 @@ char *Xstrdup(const char *string); -void abort(); +void abort(void); struct FILE; -char *fgets(char *str, int num, FILE *stream); +char *fgets(char *s, int n, FILE *stream); int ignore_return_value(); #define IGNORE_RETURN_VALUE() ignore_return_value() void myIgnoreReturnValue(); diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/OffsetUseBeforeRangeCheck.expected b/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/OffsetUseBeforeRangeCheck.expected new file mode 100644 index 00000000000..7b74afa93ff --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/OffsetUseBeforeRangeCheck.expected @@ -0,0 +1,6 @@ +| test.cpp:11:10:11:18 | access to array | This use of offset 'i' should follow the $@. | test.cpp:11:32:11:45 | ... < ... | range check | +| test.cpp:15:7:15:15 | access to array | This use of offset 'i' should follow the $@. | test.cpp:15:29:15:42 | ... < ... | range check | +| test.cpp:27:7:27:15 | access to array | This use of offset 'i' should follow the $@. | test.cpp:27:39:27:52 | ... < ... | range check | +| test.cpp:39:8:39:16 | access to array | This use of offset 'i' should follow the $@. | test.cpp:39:30:39:47 | ... < ... | range check | +| test.cpp:44:7:44:15 | access to array | This use of offset 'i' should follow the $@. | test.cpp:44:22:44:35 | ... < ... | range check | +| test.cpp:47:7:47:15 | access to array | This use of offset 'i' should follow the $@. | test.cpp:47:33:47:46 | ... < ... | range check | diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/OffsetUseBeforeRangeCheck.qlref b/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/OffsetUseBeforeRangeCheck.qlref new file mode 100644 index 00000000000..d934901f174 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/OffsetUseBeforeRangeCheck.qlref @@ -0,0 +1 @@ +Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/test.cpp new file mode 100644 index 00000000000..0c7baf7b7ff --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck/test.cpp @@ -0,0 +1,50 @@ + +void test(char *buffer, int bufferSize) +{ + int i; + + // skip whitespace + i = 0; + while ((i < bufferSize) && (buffer[i] == ' ')) { i++; } // GOOD + + i = 0; + while ((buffer[i] == ' ') && (i < bufferSize)) { i++; } // BAD + + // check for 'x' + if ((i < bufferSize) && (buffer[i] == 'x')) {} // GOOD + if ((buffer[i] == 'x') && (i < bufferSize)) {} // BAD + + if ((bufferSize > i) && (buffer[i] == 'x')) {} // GOOD + if ((buffer[i] == 'x') && (bufferSize > i)) {} // BAD [NOT DETECTED] + + if ((i <= bufferSize - 1) && (buffer[i] == 'x')) {} // GOOD + if ((buffer[i] == 'x') && (i <= bufferSize - 1)) {} // BAD [NOT DETECTED] + + if ((bufferSize >= i + 1) && (buffer[i] == 'x')) {} // GOOD + if ((buffer[i] == 'x') && (bufferSize >= i + 1)) {} // BAD [NOT DETECTED] + + if ((i < bufferSize) && (true) && (buffer[i] == 'x')) {} // GOOD + if ((buffer[i] == 'x') && (true) && (i < bufferSize)) {} // BAD + + if ((i < bufferSize - 1) && (buffer[i + 1] == 'x')) {} // GOOD + if ((buffer[i + 1] == 'x') && (i < bufferSize - 1)) {} // BAD [NOT DETECTED] + + if ((i < bufferSize) && (buffer[i] == 'x') && (i < bufferSize - 1)) {} // GOOD + if ((i < bufferSize) && ((buffer[i] == 'x') && (i < bufferSize - 1))) {} // GOOD + if ((i < bufferSize + 1) && (buffer[i] == 'x') && (i < bufferSize)) {} // BAD [NOT DETECTED] + if ((i < bufferSize + 1) && ((buffer[i] == 'x') && (i < bufferSize))) {} // BAD [NOT DETECTED] + + // look for 'ab' + for (i = 0; i < bufferSize; i++) { + if ((buffer[i] == 'a') && (i < bufferSize - 1) && (buffer[i + 1] == 'b')) // GOOD [FALSE POSITIVE] + break; + } + + if ((i < bufferSize) && (buffer[i])) {} // GOOD + if ((buffer[i]) && (i < bufferSize)) {} // BAD + + if ((i < bufferSize) && (buffer[i] + 1 == 'x')) {} // GOOD + if ((buffer[i] + 1 == 'x') && (i < bufferSize)) {} // BAD + + if ((buffer != 0) && (i < bufferSize)) {} // GOOD +} diff --git a/cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryNeverFreed.expected b/cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryNeverFreed.expected index 105bed90060..900925d8927 100644 --- a/cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryNeverFreed.expected +++ b/cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryNeverFreed.expected @@ -8,3 +8,5 @@ | test.cpp:42:18:42:23 | call to malloc | This memory is never freed | | test.cpp:73:18:73:23 | call to malloc | This memory is never freed | | test.cpp:89:18:89:23 | call to malloc | This memory is never freed | +| test.cpp:156:3:156:26 | new | This memory is never freed | +| test.cpp:157:3:157:26 | new[] | This memory is never freed | diff --git a/cpp/ql/test/query-tests/Critical/MemoryFreed/test.cpp b/cpp/ql/test/query-tests/Critical/MemoryFreed/test.cpp index 7d05263eb4f..63636166fc8 100644 --- a/cpp/ql/test/query-tests/Critical/MemoryFreed/test.cpp +++ b/cpp/ql/test/query-tests/Critical/MemoryFreed/test.cpp @@ -130,3 +130,29 @@ int main() return 0; } + +// --- placement new --- + +namespace std { + typedef unsigned long size_t; + struct nothrow_t {}; + extern const nothrow_t nothrow; +} + +void* operator new (std::size_t size, void* ptr) noexcept; +void* operator new[](std::size_t size, void* ptr) noexcept; +void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; + +int overloadedNew() { + char buf[sizeof(int)]; + + new(&buf[0]) int(5); // GOOD + int five = *(int*)buf; + + new(buf) int[1]; // GOOD + *(int*)buf = 4; + + new(std::nothrow) int(3); // BAD + new(std::nothrow) int[2]; // BAD +} diff --git a/cpp/ql/test/query-tests/Critical/OverflowStatic/OverflowStatic.expected b/cpp/ql/test/query-tests/Critical/OverflowStatic/OverflowStatic.expected index e5958e767e7..e6e2c51f7d9 100644 --- a/cpp/ql/test/query-tests/Critical/OverflowStatic/OverflowStatic.expected +++ b/cpp/ql/test/query-tests/Critical/OverflowStatic/OverflowStatic.expected @@ -6,3 +6,4 @@ | test.cpp:20:3:20:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer2' has 3 elements. | | test.cpp:24:27:24:27 | 4 | Potential buffer-overflow: 'buffer1' has size 3 not 4. | | test.cpp:26:27:26:27 | 4 | Potential buffer-overflow: 'buffer2' has size 3 not 4. | +| test.cpp:40:22:40:27 | amount | Potential buffer-overflow: 'buffer' has size 100 not 101. | diff --git a/cpp/ql/test/query-tests/Critical/OverflowStatic/test.cpp b/cpp/ql/test/query-tests/Critical/OverflowStatic/test.cpp index 2311693e7a8..be9e14bd841 100644 --- a/cpp/ql/test/query-tests/Critical/OverflowStatic/test.cpp +++ b/cpp/ql/test/query-tests/Critical/OverflowStatic/test.cpp @@ -25,3 +25,24 @@ void f1(void) memcpy(buffer2, buffer1, 3); // GOOD memcpy(buffer2, buffer1, 4); // BAD } + +void f2(char *src) +{ + char buffer[100]; + char *ptr; + int amount; + + amount = 100; + memcpy(buffer, src, amount); // GOOD + amount = amount + 1; + memcpy(buffer, src, amount); // BAD [NOT DETECTED] + amount = 101; + memcpy(buffer, src, amount); // BAD + + ptr = buffer; + memcpy(ptr, src, 101); // BAD [NOT DETECTED] + ptr = &(buffer[0]); + memcpy(ptr, src, 101); // BAD [NOT DETECTED] + ptr = &(buffer[1]); + memcpy(ptr, src, 100); // BAD [NOT DETECTED] +} diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/LimitedScopeFile.expected b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/LimitedScopeFile.expected new file mode 100644 index 00000000000..2bdd09e89df --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/LimitedScopeFile.expected @@ -0,0 +1 @@ +| file1.c:3:5:3:14 | globalInt1 | The global variable globalInt1 is not accessed outside of file1.c and could be made static. | diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/LimitedScopeFile.qlref b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/LimitedScopeFile.qlref new file mode 100644 index 00000000000..5e38f12f938 --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/LimitedScopeFile.qlref @@ -0,0 +1 @@ +JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file1.c b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file1.c new file mode 100644 index 00000000000..96e8dc7ce86 --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file1.c @@ -0,0 +1,25 @@ +// file1.c + +int globalInt1; // BAD [only accessed in this file] +int globalInt2; // GOOD [accessed in file1.c and file2.c] +int globalInt3; // GOOD [referenced in file1.h] +int globalInt4; // GOOD [only accessed in one function, should be function scope instead] +int globalInt5; // GOOD [not accessed] + +static int staticInt1; // GOOD [static] + +void file1Func1() +{ + globalInt1++; + globalInt2++; + globalInt3++; + globalInt4++; + staticInt1++; +} + +void file1Func2() +{ + globalInt1++; + globalInt3++; + staticInt1++; +} diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file1.h b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file1.h new file mode 100644 index 00000000000..f446408efcf --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file1.h @@ -0,0 +1,3 @@ +// file1.h + +extern int globalInt3; diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file2.c b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file2.c new file mode 100644 index 00000000000..6da3ce01615 --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFile/file2.c @@ -0,0 +1,10 @@ +// file2.c + +#include "file1.h" + +extern int globalInt2; + +void file2Func() +{ + globalInt2++; +} diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/LimitedScopeFunction.expected b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/LimitedScopeFunction.expected new file mode 100644 index 00000000000..d5bffb07061 --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/LimitedScopeFunction.expected @@ -0,0 +1,3 @@ +| test.c:8:5:8:14 | globalInt4 | The variable globalInt4 is only accessed in $@ and should be scoped accordingly. | test.c:19:6:19:10 | func1 | func1 | +| test.c:9:5:9:14 | globalInt5 | The variable globalInt5 is only accessed in $@ and should be scoped accordingly. | test.c:19:6:19:10 | func1 | func1 | +| test.c:10:5:10:14 | globalInt6 | The variable globalInt6 is only accessed in $@ and should be scoped accordingly. | test.c:19:6:19:10 | func1 | func1 | diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/LimitedScopeFunction.qlref b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/LimitedScopeFunction.qlref new file mode 100644 index 00000000000..c5e632ca9b6 --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/LimitedScopeFunction.qlref @@ -0,0 +1 @@ +JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/test.c b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/test.c new file mode 100644 index 00000000000..a2089446ca7 --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/test.c @@ -0,0 +1,44 @@ +// test.c + +#include "test.h" + +int globalInt1; // GOOD [used in func1, func2] +int globalInt2; // GOOD [used in func1, func2] +int globalInt3; // GOOD [used in func1, func2] +int globalInt4; // BAD [only used in func1] +int globalInt5; // BAD [only used in func1] +int globalInt6; // BAD [only used in func1] +int globalInt7; // GOOD [not used, should be reported by another query] +int globalInt8; // GOOD [used at file level] +int *addrGlobalInt8 = &globalInt8; // GOOD [used in func1, func2] +int globalInt9; // GOOD [used at file level and in func1] +int *addrGlobalInt9 = &globalInt9; // GOOD [used in func1, func2] + +int externInt; // GOOD [extern'd so could be part of an interface] + +void func1() +{ + int *ptr3 = &globalInt3; + int *ptr6 = &globalInt6; + int i8 = *addrGlobalInt8; + + globalInt1 = globalInt2; + globalInt4 = globalInt5; + externInt = globalInt9; +} + +void func2() +{ + int *ptr1 = &globalInt3; + int i8 = *addrGlobalInt8; + + globalInt1 = globalInt2; +} + +void func3() +{ + static int staticInt; // GOOD [declared in local scope] + int i; + + i = staticInt; +} diff --git a/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/test.h b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/test.h new file mode 100644 index 00000000000..3aa12e4d9a7 --- /dev/null +++ b/cpp/ql/test/query-tests/JPL_C/LOC-3/Rule 13/LimitedScopeFunction/test.h @@ -0,0 +1,3 @@ +// test.h + +extern int externInt; \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/PointlessSelfComparison.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/PointlessSelfComparison.expected index 016706c2338..2318c286c60 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/PointlessSelfComparison.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/PointlessSelfComparison.expected @@ -3,3 +3,4 @@ | test.cpp:83:10:83:15 | ... == ... | Self comparison. | | test.cpp:90:10:90:15 | ... == ... | Self comparison. | | test.cpp:118:7:118:32 | ... != ... | Self comparison. | +| test.cpp:151:11:151:16 | ... == ... | Self comparison. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp index 25ccbad42fe..4669b709bc4 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp @@ -123,3 +123,30 @@ int isSmallEnough(unsigned long long x) { // get compiled away on others. return x == (size_t)x && x == (u64)x; // GOOD } + +#define markRange(str, x, y) \ + if ((x) == (y)) { \ + str[x] = '^'; \ + } else { \ + int i; \ + str[x] = '<'; \ + for (i = x + 1; i < y; i++) { \ + str[i] = '-'; \ + } \ + str[y] = '>'; \ + } + +void useMarkRange(int offs) { + char buffer[100]; + + markRange(buffer, 10, 20); + markRange(buffer, 30, 30); + markRange(buffer, offs, offs + 10); + markRange(buffer, offs, offs); // GOOD (comparison is in the macro) +} + +#define MY_MACRO(x) (x) + +void myMacroTest(int x) { + MY_MACRO(x == x); // BAD +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString/ReturnCstrOfLocalStdString.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString/ReturnCstrOfLocalStdString.expected index 32869c5353b..df2724bc3c6 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString/ReturnCstrOfLocalStdString.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString/ReturnCstrOfLocalStdString.expected @@ -1,3 +1,3 @@ -| test.cpp:22:3:22:26 | return ... | Return value may contain a dangling pointer to $@. | test.cpp:21:24:21:37 | call to string | this local std::string | -| test.cpp:30:3:30:44 | return ... | Return value may contain a dangling pointer to $@. | test.cpp:30:10:30:35 | call to string | this local std::string | -| test.cpp:43:3:43:42 | return ... | Return value may contain a dangling pointer to $@. | test.cpp:42:22:42:35 | call to string | this local std::string | +| test.cpp:24:3:24:26 | return ... | Return value may contain a dangling pointer to $@. | test.cpp:23:24:23:37 | call to basic_string | this local std::string | +| test.cpp:32:3:32:44 | return ... | Return value may contain a dangling pointer to $@. | test.cpp:32:10:32:35 | call to basic_string | this local std::string | +| test.cpp:45:3:45:42 | return ... | Return value may contain a dangling pointer to $@. | test.cpp:44:22:44:35 | call to basic_string | this local std::string | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString/test.cpp index b9858ab5594..c27cb77b1d8 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString/test.cpp @@ -1,20 +1,22 @@ -extern "C" { - char *strdup(const char *s); - void free (void* ptr); -} namespace std { - // We are not allowed to include in the test file, - // so this is an approximation of the std::string class. - class string { - char* str_; + template struct char_traits; + template class allocator { public: - string(const char* str) : str_(strdup(str)) {} - ~string() { free(str_); } - - const char* c_str() const noexcept { return str_; } + allocator() throw(); }; + + template, class Allocator = allocator > + class basic_string { + public: + explicit basic_string(const Allocator& a = Allocator()); + basic_string(const charT* s, const Allocator& a = Allocator()); + + const charT* c_str() const; + }; + + typedef basic_string string; } const char* bad000() { diff --git a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.c b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.c index 79f9e0ffaa3..63ce8288fe4 100644 --- a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.c +++ b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.c @@ -84,3 +84,13 @@ int f12(int x) // ... } } + +void f13() +{ + f13_func(); // implicitly declared here +} + +void f13_func(int x) +{ + if (x < 10) return; // GOOD +} diff --git a/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/AV Rule 164.expected b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/AV Rule 164.expected new file mode 100644 index 00000000000..3033e746d69 --- /dev/null +++ b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/AV Rule 164.expected @@ -0,0 +1,8 @@ +| test.c:3:2:3:9 | ... >> ... | AV Rule 164: The right-hand operand (here a value is -1) of this shift shall lie between 0 and 7. | +| test.c:6:2:6:8 | ... >> ... | AV Rule 164: The right-hand operand (here a value is 8) of this shift shall lie between 0 and 7. | +| test.c:8:2:8:9 | ... << ... | AV Rule 164: The right-hand operand (here a value is -1) of this shift shall lie between 0 and 7. | +| test.c:11:2:11:8 | ... << ... | AV Rule 164: The right-hand operand (here a value is 8) of this shift shall lie between 0 and 7. | +| test.c:18:2:18:9 | ... >> ... | AV Rule 164: The right-hand operand (here a value is -1) of this shift shall lie between 0 and 7. | +| test.c:21:2:21:8 | ... >> ... | AV Rule 164: The right-hand operand (here a value is 8) of this shift shall lie between 0 and 7. | +| test.c:23:2:23:25 | ... >> ... | AV Rule 164: The right-hand operand (here a value is -1) of this shift shall lie between 0 and 7. | +| test.c:26:2:26:24 | ... >> ... | AV Rule 164: The right-hand operand (here a value is 8) of this shift shall lie between 0 and 7. | diff --git a/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/AV Rule 164.qlref b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/AV Rule 164.qlref new file mode 100644 index 00000000000..d6afaadc595 --- /dev/null +++ b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/AV Rule 164.qlref @@ -0,0 +1 @@ +jsf/4.21 Operators/AV Rule 164.ql diff --git a/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/test.c b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/test.c new file mode 100644 index 00000000000..99cc6bd7db7 --- /dev/null +++ b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 164/test.c @@ -0,0 +1,28 @@ + +void f(unsigned char uc, signed char sc, int i) { + uc >> -1; // BAD + uc >> 0; + uc >> 7; + uc >> 8; // BAD + + uc << -1; // BAD + uc << 0; + uc << 7; + uc << 8; // BAD + + uc >>= -1; // BAD [NOT DETECTED] + uc >>= 0; // BAD [NOT DETECTED] + uc >>= 7; + uc >>= 8; // BAD [NOT DETECTED] + + sc >> -1; // BAD + sc >> 0; + sc >> 7; + sc >> 8; // BAD + + ((unsigned char)i) >> -1; // BAD + ((unsigned char)i) >> 0; + ((unsigned char)i) >> 7; + ((unsigned char)i) >> 8; // BAD +} + diff --git a/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/AV Rule 165.expected b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/AV Rule 165.expected new file mode 100644 index 00000000000..5a6e6a66eef --- /dev/null +++ b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/AV Rule 165.expected @@ -0,0 +1,9 @@ +| test.c:6:6:6:8 | - ... | The unary minus operator should not be applied to an unsigned expression. | +| test.c:9:7:9:9 | - ... | The unary minus operator should not be applied to an unsigned expression. | +| test.c:12:7:12:9 | - ... | The unary minus operator should not be applied to an unsigned expression. | +| test.c:16:6:16:21 | - ... | The unary minus operator should not be applied to an unsigned expression. | +| test.c:19:7:19:23 | - ... | The unary minus operator should not be applied to an unsigned expression. | +| test.c:22:8:22:11 | - ... | The unary minus operator should not be applied to an unsigned expression. | +| test.c:23:8:23:11 | - ... | The unary minus operator should not be applied to an unsigned expression. | +| test.c:24:6:24:7 | - ... | The unary minus operator should not be applied to an unsigned expression. | +| test.c:25:7:25:9 | - ... | The unary minus operator should not be applied to an unsigned expression. | diff --git a/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/AV Rule 165.qlref b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/AV Rule 165.qlref new file mode 100644 index 00000000000..a6ee879dfe9 --- /dev/null +++ b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/AV Rule 165.qlref @@ -0,0 +1 @@ +jsf/4.21 Operators/AV Rule 165.ql diff --git a/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/test.c b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/test.c new file mode 100644 index 00000000000..26d53e5a0c3 --- /dev/null +++ b/cpp/ql/test/query-tests/jsf/4.21 Operators/AV Rule 165/test.c @@ -0,0 +1,27 @@ + +typedef unsigned int TUI; + +void f(int i, unsigned int ui, signed int si, TUI tui, volatile unsigned int vui, unsigned u, unsigned short us) { + i = -i; + i = -ui; // BAD + i = -si; + ui = -i; + ui = -ui; // BAD + ui = -si; + si = -i; + si = -ui; // BAD + si = -si; + + i = -(int)i; + i = -(unsigned int)i; // BAD + i = -(signed int)i; + ui = -(int)ui; + ui = -(unsigned int)ui; // BAD + ui = -(signed int)ui; + + tui = -tui; // BAD + vui = -vui; // BAD + u = -u; // BAD + us = -us; // BAD + ui = -(5U); // BAD [NOT DETECTED] +} diff --git a/csharp/extractor/.gitignore b/csharp/.gitignore similarity index 100% rename from csharp/extractor/.gitignore rename to csharp/.gitignore diff --git a/csharp/extractor/CSharpExtractor.sln b/csharp/CSharp.sln similarity index 78% rename from csharp/extractor/CSharpExtractor.sln rename to csharp/CSharp.sln index 9f0d615ed38..78d853a5bbe 100644 --- a/csharp/extractor/CSharpExtractor.sln +++ b/csharp/CSharp.sln @@ -3,27 +3,27 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2036 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Util", "Semmle.Util\Semmle.Util.csproj", "{CDD7AD69-0FD8-40F0-A9DA-F1077A2A85D6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Util", "extractor\Semmle.Util\Semmle.Util.csproj", "{CDD7AD69-0FD8-40F0-A9DA-F1077A2A85D6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction", "Semmle.Extraction\Semmle.Extraction.csproj", "{81EAAD75-4BE1-44E4-91DF-20778216DB64}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction", "extractor\Semmle.Extraction\Semmle.Extraction.csproj", "{81EAAD75-4BE1-44E4-91DF-20778216DB64}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp", "Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj", "{C4D62DA0-B64B-440B-86DC-AB52318CB8BF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp", "extractor\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj", "{C4D62DA0-B64B-440B-86DC-AB52318CB8BF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL", "Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj", "{399A1579-68F0-40F4-9A23-F241BA697F9C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL", "extractor\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj", "{399A1579-68F0-40F4-9A23-F241BA697F9C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Autobuild", "Semmle.Autobuild\Semmle.Autobuild.csproj", "{5131EF00-0BA9-4436-A3B0-C5CDAB4B194C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Autobuild", "autobuilder\Semmle.Autobuild\Semmle.Autobuild.csproj", "{5131EF00-0BA9-4436-A3B0-C5CDAB4B194C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Standalone", "Semmle.Extraction.CSharp.Standalone\Semmle.Extraction.CSharp.Standalone.csproj", "{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Standalone", "extractor\Semmle.Extraction.CSharp.Standalone\Semmle.Extraction.CSharp.Standalone.csproj", "{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL.Driver", "Semmle.Extraction.CIL.Driver\Semmle.Extraction.CIL.Driver.csproj", "{EFA400B3-C1CE-446F-A4E2-8B44E61EF47C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL.Driver", "extractor\Semmle.Extraction.CIL.Driver\Semmle.Extraction.CIL.Driver.csproj", "{EFA400B3-C1CE-446F-A4E2-8B44E61EF47C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Driver", "Semmle.Extraction.CSharp.Driver\Semmle.Extraction.CSharp.Driver.csproj", "{C36453BF-0C82-448A-B15D-26947503A2D3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Driver", "extractor\Semmle.Extraction.CSharp.Driver\Semmle.Extraction.CSharp.Driver.csproj", "{C36453BF-0C82-448A-B15D-26947503A2D3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.Tests", "Semmle.Extraction.Tests\Semmle.Extraction.Tests.csproj", "{CD8D3F90-AD2E-4BB5-8E82-B94AA293864A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.Tests", "extractor\Semmle.Extraction.Tests\Semmle.Extraction.Tests.csproj", "{CD8D3F90-AD2E-4BB5-8E82-B94AA293864A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Util.Tests", "Semmle.Util.Tests\Semmle.Util.Tests.csproj", "{55A620F0-23F6-440D-A5BA-0567613B3C0F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Util.Tests", "extractor\Semmle.Util.Tests\Semmle.Util.Tests.csproj", "{55A620F0-23F6-440D-A5BA-0567613B3C0F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Autobuild.Tests", "Semmle.Autobuild.Tests\Semmle.Autobuild.Tests.csproj", "{CE267461-D762-4F53-A275-685A0A4EC48D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Autobuild.Tests", "autobuilder\Semmle.Autobuild.Tests\Semmle.Autobuild.Tests.csproj", "{CE267461-D762-4F53-A275-685A0A4EC48D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/csharp/extractor/Semmle.Autobuild.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs similarity index 80% rename from csharp/extractor/Semmle.Autobuild.Tests/BuildScripts.cs rename to csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs index 21235dd102b..4cd50926dba 100644 --- a/csharp/extractor/Semmle.Autobuild.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System; using System.Linq; using Microsoft.Build.Construction; +using System.Xml; namespace Semmle.Extraction.Tests { @@ -129,12 +130,22 @@ namespace Semmle.Extraction.Tests string IBuildActions.PathCombine(params string[] parts) { - return string.Join('\\', parts); + return string.Join('\\', parts.Where(p => !string.IsNullOrWhiteSpace(p))); } + string IBuildActions.GetFullPath(string path) => path; + void IBuildActions.WriteAllText(string filename, string contents) { } + + public IDictionary LoadXml = new Dictionary(); + XmlDocument IBuildActions.LoadXml(string filename) + { + if (LoadXml.TryGetValue(filename, out var xml)) + return xml; + throw new ArgumentException("Missing LoadXml " + filename); + } } /// @@ -142,23 +153,21 @@ namespace Semmle.Extraction.Tests /// class TestSolution : ISolution { - public IEnumerable Projects => throw new NotImplementedException(); - public IEnumerable Configurations => throw new NotImplementedException(); public string DefaultConfigurationName => "Release"; public string DefaultPlatformName => "x86"; - public string Path { get; set; } - - public int ProjectCount => throw new NotImplementedException(); + public string FullPath { get; set; } public Version ToolsVersion => new Version("14.0"); + public IEnumerable IncludedProjects => throw new NotImplementedException(); + public TestSolution(string path) { - Path = path; + FullPath = path; } } @@ -318,11 +327,11 @@ namespace Semmle.Extraction.Tests } Autobuilder CreateAutoBuilder(string lgtmLanguage, bool isWindows, - string buildless=null, string solution=null, string buildCommand=null, string ignoreErrors=null, - string msBuildArguments=null, string msBuildPlatform=null, string msBuildConfiguration=null, string msBuildTarget=null, - string dotnetArguments=null, string dotnetVersion=null, string vsToolsVersion=null, - string nugetRestore=null, string allSolutions=null, - string cwd=@"C:\Project") + string buildless = null, string solution = null, string buildCommand = null, string ignoreErrors = null, + string msBuildArguments = null, string msBuildPlatform = null, string msBuildConfiguration = null, string msBuildTarget = null, + string dotnetArguments = null, string dotnetVersion = null, string vsToolsVersion = null, + string nugetRestore = null, string allSolutions = null, + string cwd = @"C:\Project") { Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa"; Actions.GetEnvironmentVariable["SEMMLE_JAVA_HOME"] = @"C:\odasa\tools\java"; @@ -354,16 +363,26 @@ namespace Semmle.Extraction.Tests public void TestDefaultCSharpAutoBuilder() { Actions.RunProcess["cmd.exe /C dotnet --info"] = 0; - Actions.RunProcess["cmd.exe /C dotnet clean"] = 0; - Actions.RunProcess["cmd.exe /C dotnet restore"] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; + Actions.RunProcess["cmd.exe /C dotnet clean test.csproj"] = 0; + Actions.RunProcess["cmd.exe /C dotnet restore test.csproj"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; + Actions.FileExists["test.csproj"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; - Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\nbar.cs"; + Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\nbar.cs\ntest.csproj"; Actions.EnumerateDirectories[@"C:\Project"] = ""; + var xml = new XmlDocument(); + xml.LoadXml(@" + + Exe + netcoreapp2.1 + + +"); + Actions.LoadXml["test.csproj"] = xml; var autobuilder = CreateAutoBuilder("csharp", true); TestAutobuilderScript(autobuilder, 0, 6); @@ -373,16 +392,26 @@ namespace Semmle.Extraction.Tests public void TestLinuxCSharpAutoBuilder() { Actions.RunProcess["dotnet --info"] = 0; - Actions.RunProcess["dotnet clean"] = 0; - Actions.RunProcess["dotnet restore"] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; + Actions.RunProcess["dotnet clean test.csproj"] = 0; + Actions.RunProcess["dotnet restore test.csproj"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; + Actions.FileExists["test.csproj"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; - Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.cs"; + Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.cs\ntest.csproj"; Actions.EnumerateDirectories[@"C:\Project"] = ""; + var xml = new XmlDocument(); + xml.LoadXml(@" + + Exe + netcoreapp2.1 + + +"); + Actions.LoadXml["test.csproj"] = xml; var autobuilder = CreateAutoBuilder("csharp", false); TestAutobuilderScript(autobuilder, 0, 6); @@ -391,10 +420,6 @@ namespace Semmle.Extraction.Tests [Fact] public void TestLinuxCSharpAutoBuilderExtractorFailed() { - Actions.RunProcess["dotnet --info"] = 0; - Actions.RunProcess["dotnet clean"] = 0; - Actions.RunProcess["dotnet restore"] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; Actions.FileExists["csharp.log"] = false; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -402,7 +427,7 @@ namespace Semmle.Extraction.Tests Actions.EnumerateDirectories[@"C:\Project"] = ""; var autobuilder = CreateAutoBuilder("csharp", false); - TestAutobuilderScript(autobuilder, 1, 4); + TestAutobuilderScript(autobuilder, 1, 0); } @@ -438,7 +463,7 @@ namespace Semmle.Extraction.Tests var autobuilder = CreateAutoBuilder("cpp", true); var solution = new TestSolution(@"C:\Project\test.sln"); - autobuilder.SolutionsToBuild.Add(solution); + autobuilder.ProjectsOrSolutionsToBuild.Add(solution); TestAutobuilderScript(autobuilder, 0, 2); } @@ -495,7 +520,7 @@ namespace Semmle.Extraction.Tests Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln"; Actions.EnumerateDirectories[@"C:\Project"] = ""; - var autobuilder = CreateAutoBuilder("csharp", false, buildless:"true"); + var autobuilder = CreateAutoBuilder("csharp", false, buildless: "true"); TestAutobuilderScript(autobuilder, 0, 3); } @@ -550,7 +575,7 @@ namespace Semmle.Extraction.Tests Assert.Equal(commandsRun, EndCallbackReturn.Count); var action = Actions.RunProcess.GetEnumerator(); - for(int cmd=0; cmd + + Exe + netcoreapp2.1 + - var autobuilder = CreateAutoBuilder("csharp", false, dotnetArguments:"--no-restore"); // nugetRestore=false does not work for now. +"); + Actions.LoadXml["test.csproj"] = xml; + + var autobuilder = CreateAutoBuilder("csharp", false, dotnetArguments: "--no-restore"); // nugetRestore=false does not work for now. TestAutobuilderScript(autobuilder, 0, 6); } @@ -818,19 +848,29 @@ namespace Semmle.Extraction.Tests Actions.RunProcess[@"chmod u+x dotnet-install.sh"] = 0; Actions.RunProcess[@"./dotnet-install.sh --channel release --version 2.1.3 --install-dir C:\Project\.dotnet"] = 0; Actions.RunProcess[@"C:\Project\.dotnet\dotnet --info"] = 0; - Actions.RunProcess[@"C:\Project\.dotnet\dotnet clean"] = 0; - Actions.RunProcess[@"C:\Project\.dotnet\dotnet restore"] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; + Actions.RunProcess[@"C:\Project\.dotnet\dotnet clean test.csproj"] = 0; + Actions.RunProcess[@"C:\Project\.dotnet\dotnet restore test.csproj"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; + Actions.FileExists["test.csproj"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; Actions.GetEnvironmentVariable["PATH"] = "/bin:/usr/bin"; - Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.cs"; + Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.cs\ntest.csproj"; Actions.EnumerateDirectories[@"C:\Project"] = ""; + var xml = new XmlDocument(); + xml.LoadXml(@" + + Exe + netcoreapp2.1 + - var autobuilder = CreateAutoBuilder("csharp", false, dotnetVersion:"2.1.3"); +"); + Actions.LoadXml["test.csproj"] = xml; + + var autobuilder = CreateAutoBuilder("csharp", false, dotnetVersion: "2.1.3"); TestAutobuilderScript(autobuilder, 0, 10); } @@ -843,17 +883,27 @@ namespace Semmle.Extraction.Tests Actions.RunProcess[@"chmod u+x dotnet-install.sh"] = 0; Actions.RunProcess[@"./dotnet-install.sh --channel release --version 2.1.3 --install-dir C:\Project\.dotnet"] = 0; Actions.RunProcess[@"C:\Project\.dotnet\dotnet --info"] = 0; - Actions.RunProcess[@"C:\Project\.dotnet\dotnet clean"] = 0; - Actions.RunProcess[@"C:\Project\.dotnet\dotnet restore"] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; + Actions.RunProcess[@"C:\Project\.dotnet\dotnet clean test.csproj"] = 0; + Actions.RunProcess[@"C:\Project\.dotnet\dotnet restore test.csproj"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; + Actions.FileExists["test.csproj"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; Actions.GetEnvironmentVariable["PATH"] = "/bin:/usr/bin"; - Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\nbar.cs"; + Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\nbar.cs\ntest.csproj"; Actions.EnumerateDirectories[@"C:\Project"] = ""; + var xml = new XmlDocument(); + xml.LoadXml(@" + + Exe + netcoreapp2.1 + + +"); + Actions.LoadXml["test.csproj"] = xml; var autobuilder = CreateAutoBuilder("csharp", false, dotnetVersion: "2.1.3"); TestAutobuilderScript(autobuilder, 0, 10); @@ -866,20 +916,131 @@ namespace Semmle.Extraction.Tests Actions.RunProcessOut["cmd.exe /C dotnet --list-sdks"] = "2.1.3 [C:\\Program Files\\dotnet\\sdks]\n2.1.4 [C:\\Program Files\\dotnet\\sdks]"; Actions.RunProcess[@"cmd.exe /C powershell -NoProfile -ExecutionPolicy unrestricted -file C:\Project\install-dotnet.ps1 -Version 2.1.3 -InstallDir C:\Project\.dotnet"] = 0; Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet --info"] = 0; - Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean"] = 0; - Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore"] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean test.csproj"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore test.csproj"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; + Actions.FileExists["test.csproj"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; Actions.GetEnvironmentVariable["PATH"] = "/bin:/usr/bin"; - Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.cs"; + Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.cs\ntest.csproj"; Actions.EnumerateDirectories[@"C:\Project"] = ""; + var xml = new XmlDocument(); + xml.LoadXml(@" + + Exe + netcoreapp2.1 + + +"); + Actions.LoadXml["test.csproj"] = xml; var autobuilder = CreateAutoBuilder("csharp", true, dotnetVersion: "2.1.3"); TestAutobuilderScript(autobuilder, 0, 8); } + + [Fact] + public void TestDirsProjWindows() + { + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\csharp\nuget\nuget.exe restore dirs.proj"] = 1; + Actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && C:\\odasa\\tools\\odasa index --auto msbuild dirs.proj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; + Actions.FileExists["csharp.log"] = true; + Actions.FileExists[@"a\test.csproj"] = true; + Actions.FileExists["dirs.proj"] = true; + Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false; + Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false; + Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"] = true; + Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"] = false; + Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"] = true; + + Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; + Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; + Actions.EnumerateFiles[@"C:\Project"] = "a\\test.cs\na\\test.csproj\ndirs.proj"; + Actions.EnumerateDirectories[@"C:\Project"] = ""; + + var csproj = new XmlDocument(); + csproj.LoadXml(@" + + + + + "); + Actions.LoadXml["a\\test.csproj"] = csproj; + + var dirsproj = new XmlDocument(); + dirsproj.LoadXml(@" + + + +"); + Actions.LoadXml["dirs.proj"] = dirsproj; + + var autobuilder = CreateAutoBuilder("csharp", true, msBuildArguments: "/P:Fu=Bar", msBuildTarget: "Windows", msBuildPlatform: "x86", msBuildConfiguration: "Debug", + vsToolsVersion: "12", allSolutions: "true"); + TestAutobuilderScript(autobuilder, 0, 4); + } + + [Fact] + public void TestDirsProjLinux() + { + Actions.RunProcess[@"mono C:\odasa\tools\csharp\nuget\nuget.exe restore dirs.proj"] = 1; + Actions.RunProcess[@"C:\odasa\tools\odasa index --auto msbuild dirs.proj /p:UseSharedCompilation=false /t:rebuild /p:MvcBuildViews=true"] = 0; + Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; + Actions.FileExists["csharp.log"] = true; + Actions.FileExists["a/test.csproj"] = true; + Actions.FileExists["dirs.proj"] = true; + Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; + Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; + Actions.EnumerateFiles[@"C:\Project"] = "a/test.cs\na/test.csproj\ndirs.proj"; + Actions.EnumerateDirectories[@"C:\Project"] = ""; + + var csproj = new XmlDocument(); + csproj.LoadXml(@" + + + + + "); + Actions.LoadXml["a/test.csproj"] = csproj; + + var dirsproj = new XmlDocument(); + dirsproj.LoadXml(@" + + + +"); + Actions.LoadXml["dirs.proj"] = dirsproj; + + var autobuilder = CreateAutoBuilder("csharp", false); + TestAutobuilderScript(autobuilder, 0, 4); + } + + [Fact] + public void TestCyclicDirsProj() + { + Actions.FileExists["dirs.proj"] = true; + Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; + Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; + Actions.FileExists["csharp.log"] = false; + Actions.EnumerateFiles[@"C:\Project"] = "dirs.proj"; + Actions.EnumerateDirectories[@"C:\Project"] = ""; + + var dirsproj1 = new XmlDocument(); + dirsproj1.LoadXml(@" + + + +"); + Actions.LoadXml["dirs.proj"] = dirsproj1; + + var autobuilder = CreateAutoBuilder("csharp", false); + TestAutobuilderScript(autobuilder, 1, 0); + } } } diff --git a/csharp/extractor/Semmle.Autobuild.Tests/Properties/AssemblyInfo.cs b/csharp/autobuilder/Semmle.Autobuild.Tests/Properties/AssemblyInfo.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild.Tests/Properties/AssemblyInfo.cs rename to csharp/autobuilder/Semmle.Autobuild.Tests/Properties/AssemblyInfo.cs diff --git a/csharp/extractor/Semmle.Autobuild.Tests/Semmle.Autobuild.Tests.csproj b/csharp/autobuilder/Semmle.Autobuild.Tests/Semmle.Autobuild.Tests.csproj similarity index 100% rename from csharp/extractor/Semmle.Autobuild.Tests/Semmle.Autobuild.Tests.csproj rename to csharp/autobuilder/Semmle.Autobuild.Tests/Semmle.Autobuild.Tests.csproj diff --git a/csharp/extractor/Semmle.Autobuild/AspBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/AspBuildRule.cs rename to csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs diff --git a/csharp/extractor/Semmle.Autobuild/AutobuildOptions.cs b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/AutobuildOptions.cs rename to csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs diff --git a/csharp/extractor/Semmle.Autobuild/Autobuilder.cs b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs similarity index 75% rename from csharp/extractor/Semmle.Autobuild/Autobuilder.cs rename to csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs index 3edcb802ffe..02e3b672511 100644 --- a/csharp/extractor/Semmle.Autobuild/Autobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs @@ -29,26 +29,32 @@ namespace Semmle.Autobuild public class Autobuilder { /// - /// Full file paths of files found in the project directory. + /// Full file paths of files found in the project directory, as well as + /// their distance from the project root folder. The list is sorted + /// by distance in ascending order. /// - public IEnumerable Paths => pathsLazy.Value; - readonly Lazy> pathsLazy; + public IEnumerable<(string, int)> Paths => pathsLazy.Value; + readonly Lazy> pathsLazy; /// - /// Gets a list of paths matching a set of extensions - /// (including the "."). + /// Gets a list of paths matching a set of extensions (including the "."), + /// as well as their distance from the project root folder. + /// The list is sorted by distance in ascending order. /// /// The extensions to find. /// The files matching the extension. - public IEnumerable GetExtensions(params string[] extensions) => - Paths.Where(p => extensions.Contains(Path.GetExtension(p))); + public IEnumerable<(string, int)> GetExtensions(params string[] extensions) => + Paths.Where(p => extensions.Contains(Path.GetExtension(p.Item1))); /// - /// Gets all paths matching a particular filename. + /// Gets all paths matching a particular filename, as well as + /// their distance from the project root folder. The list is sorted + /// by distance in ascending order. /// /// The filename to find. /// Possibly empty sequence of paths with the given filename. - public IEnumerable GetFilename(string name) => Paths.Where(p => Path.GetFileName(p) == name); + public IEnumerable<(string, int)> GetFilename(string name) => + Paths.Where(p => Path.GetFileName(p.Item1) == name); /// /// Holds if a given path, relative to the root of the source directory @@ -59,30 +65,30 @@ namespace Semmle.Autobuild public bool HasRelativePath(string path) => HasPath(Actions.PathCombine(RootDirectory, path)); /// - /// List of solution files to build. + /// List of project/solution files to build. /// - public IList SolutionsToBuild => solutionsToBuildLazy.Value; - readonly Lazy> solutionsToBuildLazy; + public IList ProjectsOrSolutionsToBuild => projectsOrSolutionsToBuildLazy.Value; + readonly Lazy> projectsOrSolutionsToBuildLazy; /// /// Holds if a given path was found. /// /// The path of the file. /// True iff the path was found. - public bool HasPath(string path) => Paths.Any(p => path == p); + public bool HasPath(string path) => Paths.Any(p => path == p.Item1); - void FindFiles(string dir, int depth, IList results) + void FindFiles(string dir, int depth, int maxDepth, IList<(string, int)> results) { foreach (var f in Actions.EnumerateFiles(dir)) { - results.Add(f); + results.Add((f, depth)); } - if (depth > 1) + if (depth < maxDepth) { foreach (var d in Actions.EnumerateDirectories(dir)) { - FindFiles(d, depth - 1, results); + FindFiles(d, depth + 1, maxDepth, results); } } } @@ -113,46 +119,66 @@ namespace Semmle.Autobuild Actions = actions; Options = options; - pathsLazy = new Lazy>(() => + pathsLazy = new Lazy>(() => { - var files = new List(); - FindFiles(options.RootDirectory, options.SearchDepth, files); - return files. - OrderBy(s => s.Count(c => c == Path.DirectorySeparatorChar)). - ThenBy(s => Path.GetFileName(s).Length). - ToArray(); + var files = new List<(string, int)>(); + FindFiles(options.RootDirectory, 0, options.SearchDepth, files); + return files.OrderBy(f => f.Item2).ToArray(); }); - solutionsToBuildLazy = new Lazy>(() => + projectsOrSolutionsToBuildLazy = new Lazy>(() => { + List ret; if (options.Solution.Any()) { - var ret = new List(); + ret = new List(); foreach (var solution in options.Solution) { if (actions.FileExists(solution)) ret.Add(new Solution(this, solution)); else - Log(Severity.Error, "The specified solution file {0} was not found", solution); + Log(Severity.Error, $"The specified solution file {solution} was not found"); } return ret; } - var solutions = GetExtensions(".sln"). - Select(s => new Solution(this, s)). - Where(s => s.ProjectCount > 0). - OrderByDescending(s => s.ProjectCount). - ThenBy(s => s.Path.Length). + IEnumerable FindFiles(string extension, Func create) + { + var matchingFiles = GetExtensions(extension). + Select(p => (ProjectOrSolution: create(p.Item1), DistanceFromRoot: p.Item2)). + Where(p => p.ProjectOrSolution.HasLanguage(this.Options.Language)). ToArray(); - foreach (var sln in solutions) - { - Log(Severity.Info, $"Found {sln.Path} with {sln.ProjectCount} {this.Options.Language} projects, version {sln.ToolsVersion}, config {string.Join(" ", sln.Configurations.Select(c => c.FullName))}"); + if (matchingFiles.Length == 0) + return null; + + if (options.AllSolutions) + return matchingFiles.Select(p => p.ProjectOrSolution); + + var firstIsClosest = matchingFiles.Length > 1 && matchingFiles[0].DistanceFromRoot < matchingFiles[1].DistanceFromRoot; + if (matchingFiles.Length == 1 || firstIsClosest) + return matchingFiles.Select(p => p.ProjectOrSolution).Take(1); + + var candidates = matchingFiles. + Where(f => f.DistanceFromRoot == matchingFiles[0].DistanceFromRoot). + Select(f => f.ProjectOrSolution); + Log(Severity.Info, $"Found multiple '{extension}' files, giving up: {string.Join(", ", candidates)}."); + return new IProjectOrSolution[0]; } - return new List(options.AllSolutions ? - solutions : - solutions.Take(1)); + // First look for `.proj` files + ret = FindFiles(".proj", f => new Project(this, f))?.ToList(); + if (ret != null) + return ret; + + // Then look for `.sln` files + ret = FindFiles(".sln", f => new Solution(this, f))?.ToList(); + if (ret != null) + return ret; + + // Finally look for language specific project files, e.g. `.csproj` files + ret = FindFiles(this.Options.Language.ProjectExtension, f => new Project(this, f))?.ToList(); + return ret ?? new List(); }); SemmleDist = Actions.GetEnvironmentVariable("SEMMLE_DIST"); diff --git a/csharp/extractor/Semmle.Autobuild/BuildActions.cs b/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs similarity index 92% rename from csharp/extractor/Semmle.Autobuild/BuildActions.cs rename to csharp/autobuilder/Semmle.Autobuild/BuildActions.cs index 906d6701c1a..433598c5c16 100644 --- a/csharp/extractor/Semmle.Autobuild/BuildActions.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Xml; namespace Semmle.Autobuild { @@ -96,12 +97,22 @@ namespace Semmle.Autobuild /// The combined path. string PathCombine(params string[] parts); + /// + /// Gets the full path for , Path.GetFullPath(). + /// + string GetFullPath(string path); + /// /// Writes contents to file, File.WriteAllText(). /// /// The filename. /// The text. void WriteAllText(string filename, string contents); + + /// + /// Loads the XML document from . + /// + XmlDocument LoadXml(string filename); } /// @@ -167,10 +178,15 @@ namespace Semmle.Autobuild void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents); - private SystemBuildActions() + XmlDocument IBuildActions.LoadXml(string filename) { + var ret = new XmlDocument(); + ret.Load(filename); + return ret; } + string IBuildActions.GetFullPath(string path) => Path.GetFullPath(path); + public static readonly IBuildActions Instance = new SystemBuildActions(); } } diff --git a/csharp/extractor/Semmle.Autobuild/BuildCommandAutoRule.cs b/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs similarity index 91% rename from csharp/extractor/Semmle.Autobuild/BuildCommandAutoRule.cs rename to csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs index 627651eaefe..9ec8a3e16eb 100644 --- a/csharp/extractor/Semmle.Autobuild/BuildCommandAutoRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Semmle.Util; using Semmle.Util.Logging; namespace Semmle.Autobuild @@ -32,7 +31,7 @@ namespace Semmle.Autobuild var extensions = builder.Actions.IsWindows() ? winExtensions : linuxExtensions; var scripts = buildScripts.SelectMany(s => extensions.Select(e => s + e)); - var scriptPath = builder.Paths.Where(p => scripts.Any(p.ToLower().EndsWith)).OrderBy(p => p.Length).FirstOrDefault(); + var scriptPath = builder.Paths.Where(p => scripts.Any(p.Item1.ToLower().EndsWith)).OrderBy(p => p.Item2).Select(p => p.Item1).FirstOrDefault(); if (scriptPath == null) return BuildScript.Failure; @@ -41,12 +40,12 @@ namespace Semmle.Autobuild chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}"); var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script); - var path = Path.GetDirectoryName(scriptPath); + var dir = Path.GetDirectoryName(scriptPath); // A specific .NET Core version may be required return chmodScript & DotNetRule.WithDotNet(builder, dotNet => { - var command = new CommandBuilder(builder.Actions, path, dotNet?.Environment); + var command = new CommandBuilder(builder.Actions, dir, dotNet?.Environment); // A specific Visual Studio version may be required var vsTools = MsBuildRule.GetVcVarsBatFile(builder); diff --git a/csharp/extractor/Semmle.Autobuild/BuildCommandRule.cs b/csharp/autobuilder/Semmle.Autobuild/BuildCommandRule.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/BuildCommandRule.cs rename to csharp/autobuilder/Semmle.Autobuild/BuildCommandRule.cs diff --git a/csharp/extractor/Semmle.Autobuild/BuildScript.cs b/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs similarity index 99% rename from csharp/extractor/Semmle.Autobuild/BuildScript.cs rename to csharp/autobuilder/Semmle.Autobuild/BuildScript.cs index d36e98a0db5..c268ae98030 100644 --- a/csharp/extractor/Semmle.Autobuild/BuildScript.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; -using Semmle.Util; namespace Semmle.Autobuild { diff --git a/csharp/extractor/Semmle.Autobuild/BuildTools.cs b/csharp/autobuilder/Semmle.Autobuild/BuildTools.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/BuildTools.cs rename to csharp/autobuilder/Semmle.Autobuild/BuildTools.cs diff --git a/csharp/extractor/Semmle.Autobuild/CommandBuilder.cs b/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/CommandBuilder.cs rename to csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs diff --git a/csharp/extractor/Semmle.Autobuild/DotNetRule.cs b/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs similarity index 88% rename from csharp/extractor/Semmle.Autobuild/DotNetRule.cs rename to csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs index a862a4f1a1b..c9622d2cf26 100644 --- a/csharp/extractor/Semmle.Autobuild/DotNetRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs @@ -4,6 +4,7 @@ using System.Linq; using Newtonsoft.Json.Linq; using System.Collections.Generic; using System.IO; +using Semmle.Util; namespace Semmle.Autobuild { @@ -15,46 +16,36 @@ namespace Semmle.Autobuild { public BuildScript Analyse(Autobuilder builder) { - builder.Log(Severity.Info, "Attempting to build using .NET Core"); + if (!builder.ProjectsOrSolutionsToBuild.Any()) + return BuildScript.Failure; - var projects = builder.SolutionsToBuild.Any() - ? builder.SolutionsToBuild.SelectMany(s => s.Projects).ToArray() - : builder.GetExtensions(Language.CSharp.ProjectExtension).Select(p => new Project(builder, p)).ToArray(); - - var notDotNetProject = projects.FirstOrDefault(p => !p.DotNetProject); + var notDotNetProject = builder.ProjectsOrSolutionsToBuild. + SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects)). + OfType(). + FirstOrDefault(p => !p.DotNetProject); if (notDotNetProject != null) { builder.Log(Severity.Info, "Not using .NET Core because of incompatible project {0}", notDotNetProject); return BuildScript.Failure; } - if (!builder.SolutionsToBuild.Any()) - // Attempt dotnet build in root folder - return WithDotNet(builder, dotNet => - { - var info = GetInfoCommand(builder.Actions, dotNet); - var clean = GetCleanCommand(builder.Actions, dotNet).Script; - var restore = GetRestoreCommand(builder.Actions, dotNet).Script; - var build = GetBuildCommand(builder, dotNet).Script; - return info & clean & BuildScript.Try(restore) & build; - }); + builder.Log(Severity.Info, "Attempting to build using .NET Core"); - // Attempt dotnet build on each solution return WithDotNet(builder, dotNet => { var ret = GetInfoCommand(builder.Actions, dotNet); - foreach (var solution in builder.SolutionsToBuild) + foreach (var projectOrSolution in builder.ProjectsOrSolutionsToBuild) { var cleanCommand = GetCleanCommand(builder.Actions, dotNet); - cleanCommand.QuoteArgument(solution.Path); + cleanCommand.QuoteArgument(projectOrSolution.FullPath); var clean = cleanCommand.Script; var restoreCommand = GetRestoreCommand(builder.Actions, dotNet); - restoreCommand.QuoteArgument(solution.Path); + restoreCommand.QuoteArgument(projectOrSolution.FullPath); var restore = restoreCommand.Script; var buildCommand = GetBuildCommand(builder, dotNet); - buildCommand.QuoteArgument(solution.Path); + buildCommand.QuoteArgument(projectOrSolution.FullPath); var build = buildCommand.Script; ret &= clean & BuildScript.Try(restore) & build; @@ -110,7 +101,7 @@ namespace Semmle.Autobuild // See https://docs.microsoft.com/en-us/dotnet/core/tools/global-json var installScript = BuildScript.Success; var validGlobalJson = false; - foreach (var path in builder.Paths.Where(p => p.EndsWith("global.json", StringComparison.Ordinal))) + foreach (var path in builder.Paths.Select(p => p.Item1).Where(p => p.EndsWith("global.json", StringComparison.Ordinal))) { string version; try diff --git a/csharp/extractor/Semmle.Autobuild/Language.cs b/csharp/autobuilder/Semmle.Autobuild/Language.cs similarity index 78% rename from csharp/extractor/Semmle.Autobuild/Language.cs rename to csharp/autobuilder/Semmle.Autobuild/Language.cs index 6f8d73b2a47..5049506be57 100644 --- a/csharp/extractor/Semmle.Autobuild/Language.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Language.cs @@ -8,9 +8,6 @@ public bool ProjectFileHasThisLanguage(string path) => System.IO.Path.GetExtension(path) == ProjectExtension; - public static bool IsProjectFileForAnySupportedLanguage(string path) => - Cpp.ProjectFileHasThisLanguage(path) || CSharp.ProjectFileHasThisLanguage(path); - public readonly string ProjectExtension; private Language(string extension) diff --git a/csharp/extractor/Semmle.Autobuild/MsBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs similarity index 69% rename from csharp/extractor/Semmle.Autobuild/MsBuildRule.cs rename to csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs index cb7eae2c23b..2b46d8d526e 100644 --- a/csharp/extractor/Semmle.Autobuild/MsBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs @@ -1,5 +1,4 @@ using Semmle.Util.Logging; -using System.IO; using System.Linq; namespace Semmle.Autobuild @@ -16,19 +15,19 @@ namespace Semmle.Autobuild public BuildScript Analyse(Autobuilder builder) { - builder.Log(Severity.Info, "Attempting to build using MSBuild"); - - if (!builder.SolutionsToBuild.Any()) - { - builder.Log(Severity.Info, "Could not find a suitable solution file to build"); + if (!builder.ProjectsOrSolutionsToBuild.Any()) return BuildScript.Failure; - } + + builder.Log(Severity.Info, "Attempting to build using MSBuild"); var vsTools = GetVcVarsBatFile(builder); - if (vsTools == null && builder.SolutionsToBuild.Any()) + if (vsTools == null && builder.ProjectsOrSolutionsToBuild.Any()) { - vsTools = BuildTools.FindCompatibleVcVars(builder.Actions, builder.SolutionsToBuild.First()); + var firstSolution = builder.ProjectsOrSolutionsToBuild.OfType().FirstOrDefault(); + vsTools = firstSolution != null + ? BuildTools.FindCompatibleVcVars(builder.Actions, firstSolution) + : BuildTools.VcVarsAllBatFiles(builder.Actions).OrderByDescending(b => b.ToolsVersion).FirstOrDefault(); } if (vsTools == null && builder.Actions.IsWindows()) @@ -40,36 +39,42 @@ namespace Semmle.Autobuild var ret = BuildScript.Success; - foreach (var solution in builder.SolutionsToBuild) + foreach (var projectOrSolution in builder.ProjectsOrSolutionsToBuild) { if (builder.Options.NugetRestore) { var nugetCommand = new CommandBuilder(builder.Actions). RunCommand(nuget). Argument("restore"). - QuoteArgument(solution.Path); + QuoteArgument(projectOrSolution.FullPath); ret &= BuildScript.Try(nugetCommand.Script); } var command = new CommandBuilder(builder.Actions); if (vsTools != null) - { command.CallBatFile(vsTools.Path); - } command.IndexCommand(builder.Odasa, MsBuild); - command.QuoteArgument(solution.Path); + command.QuoteArgument(projectOrSolution.FullPath); command.Argument("/p:UseSharedCompilation=false"); - string target = builder.Options.MsBuildTarget != null ? builder.Options.MsBuildTarget : "rebuild"; - string platform = builder.Options.MsBuildPlatform != null ? builder.Options.MsBuildPlatform : solution.DefaultPlatformName; - string configuration = builder.Options.MsBuildConfiguration != null ? builder.Options.MsBuildConfiguration : solution.DefaultConfigurationName; + string target = builder.Options.MsBuildTarget != null + ? builder.Options.MsBuildTarget + : "rebuild"; + string platform = builder.Options.MsBuildPlatform != null + ? builder.Options.MsBuildPlatform + : projectOrSolution is ISolution s1 ? s1.DefaultPlatformName : null; + string configuration = builder.Options.MsBuildConfiguration != null + ? builder.Options.MsBuildConfiguration + : projectOrSolution is ISolution s2 ? s2.DefaultConfigurationName : null; command.Argument("/t:" + target); - command.Argument(string.Format("/p:Platform=\"{0}\"", platform)); - command.Argument(string.Format("/p:Configuration=\"{0}\"", configuration)); + if (platform != null) + command.Argument(string.Format("/p:Platform=\"{0}\"", platform)); + if (configuration != null) + command.Argument(string.Format("/p:Configuration=\"{0}\"", configuration)); command.Argument("/p:MvcBuildViews=true"); command.Argument(builder.Options.MsBuildArguments); diff --git a/csharp/extractor/Semmle.Autobuild/Program.cs b/csharp/autobuilder/Semmle.Autobuild/Program.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/Program.cs rename to csharp/autobuilder/Semmle.Autobuild/Program.cs diff --git a/csharp/autobuilder/Semmle.Autobuild/Project.cs b/csharp/autobuilder/Semmle.Autobuild/Project.cs new file mode 100644 index 00000000000..87088d1edfb --- /dev/null +++ b/csharp/autobuilder/Semmle.Autobuild/Project.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using Semmle.Util.Logging; + +namespace Semmle.Autobuild +{ + /// + /// Representation of a .proj file, a .csproj file (C#), or a .vcxproj file (C++). + /// C# project files come in 2 flavours, .Net core and msbuild, but they + /// have the same file extension. + /// + public class Project : ProjectOrSolution + { + /// + /// Holds if this project is for .Net core. + /// + public bool DotNetProject { get; private set; } + + public bool ValidToolsVersion { get; private set; } + + public Version ToolsVersion { get; private set; } + + readonly Lazy> includedProjectsLazy; + public override IEnumerable IncludedProjects => includedProjectsLazy.Value; + + public Project(Autobuilder builder, string path) : base(builder, path) + { + ToolsVersion = new Version(); + includedProjectsLazy = new Lazy>(() => new List()); + + if (!builder.Actions.FileExists(FullPath)) + return; + + XmlDocument projFile; + try + { + projFile = builder.Actions.LoadXml(FullPath); + } + catch (XmlException) + { + builder.Log(Severity.Info, $"Skipping project file {path} as it is not a valid XML document."); + return; + } + + var root = projFile.DocumentElement; + + if (root.Name == "Project") + { + if (root.HasAttribute("Sdk")) + { + DotNetProject = true; + return; + } + + var toolsVersion = root.GetAttribute("ToolsVersion"); + if (!string.IsNullOrEmpty(toolsVersion)) + { + try + { + ToolsVersion = new Version(toolsVersion); + ValidToolsVersion = true; + } + catch // Generic catch clause - Version constructor throws about 5 different exceptions. + { + builder.Log(Severity.Warning, "Project {0} has invalid tools version {1}", path, toolsVersion); + } + } + + includedProjectsLazy = new Lazy>(() => + { + var ret = new List(); + // The documentation on `.proj` files is very limited, but it appears that both + // `` and `` is valid + var mgr = new XmlNamespaceManager(projFile.NameTable); + mgr.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003"); + var projectFileIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFile/@Include", mgr).OfType(); + var projectFilesIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFiles/@Include", mgr).OfType(); + foreach (var include in projectFileIncludes.Concat(projectFilesIncludes)) + { + var includePath = builder.Actions.IsWindows() ? include.Value : include.Value.Replace("\\", "/"); + ret.Add(new Project(builder, builder.Actions.PathCombine(Path.GetDirectoryName(this.FullPath), includePath))); + } + return ret; + }); + } + } + } +} diff --git a/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs b/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs new file mode 100644 index 00000000000..53025345b69 --- /dev/null +++ b/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Semmle.Autobuild +{ + /// + /// A file that can be the target in an invocation of `msbuild` or `dotnet build`. + /// Either a solution file or a project file (`.proj`, `.csproj`, or `.vcxproj`). + /// + public interface IProjectOrSolution + { + /// + /// Gets the full path of this file. + /// + string FullPath { get; } + + /// + /// Gets a list of other projects directly included by this file. + /// + IEnumerable IncludedProjects { get; } + } + + public abstract class ProjectOrSolution : IProjectOrSolution + { + public string FullPath { get; private set; } + + protected ProjectOrSolution(Autobuilder builder, string path) + { + FullPath = builder.Actions.GetFullPath(path); + } + + public abstract IEnumerable IncludedProjects { get; } + + public override string ToString() => FullPath; + } + + public static class IProjectOrSolutionExtensions + { + /// + /// Holds if this file includes a project with code from language . + /// + public static bool HasLanguage(this IProjectOrSolution p, Language l) + { + bool HasLanguage(IProjectOrSolution p0, HashSet seen) + { + if (seen.Contains(p0.FullPath)) + return false; + seen.Add(p0.FullPath); // guard against cyclic includes + return l.ProjectFileHasThisLanguage(p0.FullPath) || p0.IncludedProjects.Any(p1 => HasLanguage(p1, seen)); + } + return HasLanguage(p, new HashSet()); + } + } +} diff --git a/csharp/extractor/Semmle.Autobuild/Properties/AssemblyInfo.cs b/csharp/autobuilder/Semmle.Autobuild/Properties/AssemblyInfo.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/Properties/AssemblyInfo.cs rename to csharp/autobuilder/Semmle.Autobuild/Properties/AssemblyInfo.cs diff --git a/csharp/extractor/Semmle.Autobuild/Semmle.Autobuild.csproj b/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj similarity index 77% rename from csharp/extractor/Semmle.Autobuild/Semmle.Autobuild.csproj rename to csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj index 8a9d272169c..2d7eb6bfb6a 100644 --- a/csharp/extractor/Semmle.Autobuild/Semmle.Autobuild.csproj +++ b/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj @@ -20,8 +20,8 @@ - - + + diff --git a/csharp/extractor/Semmle.Autobuild/Solution.cs b/csharp/autobuilder/Semmle.Autobuild/Solution.cs similarity index 62% rename from csharp/extractor/Semmle.Autobuild/Solution.cs rename to csharp/autobuilder/Semmle.Autobuild/Solution.cs index 66bbff777ac..312e7deeb54 100644 --- a/csharp/extractor/Semmle.Autobuild/Solution.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Solution.cs @@ -10,15 +10,8 @@ namespace Semmle.Autobuild /// /// A solution file, extension .sln. /// - public interface ISolution + public interface ISolution : IProjectOrSolution { - /// - /// List of C# or C++ projects contained in the solution. - /// (There could be other project types as well - these are ignored.) - /// - - IEnumerable Projects { get; } - /// /// Solution configurations. /// @@ -34,16 +27,6 @@ namespace Semmle.Autobuild /// string DefaultPlatformName { get; } - /// - /// The path of the solution file. - /// - string Path { get; } - - /// - /// The number of C# or C++ projects. - /// - int ProjectCount { get; } - /// /// Gets the "best" tools version for this solution. /// If there are several versions, because the project files @@ -56,11 +39,12 @@ namespace Semmle.Autobuild /// /// A solution file on the filesystem, read using Microsoft.Build. /// - class Solution : ISolution + class Solution : ProjectOrSolution, ISolution { readonly SolutionFile solution; - public IEnumerable Projects { get; private set; } + readonly IEnumerable includedProjects; + public override IEnumerable IncludedProjects => includedProjects; public IEnumerable Configurations => solution == null ? Enumerable.Empty() : solution.SolutionConfigurations; @@ -71,18 +55,16 @@ namespace Semmle.Autobuild public string DefaultPlatformName => solution == null ? "" : solution.GetDefaultPlatformName(); - public Solution(Autobuilder builder, string path) + public Solution(Autobuilder builder, string path) : base(builder, path) { - Path = System.IO.Path.GetFullPath(path); try { - solution = SolutionFile.Parse(Path); + solution = SolutionFile.Parse(FullPath); - Projects = + includedProjects = solution.ProjectsInOrder. Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat). - Select(p => System.IO.Path.GetFullPath(FileUtils.ConvertToNative(p.AbsolutePath))). - Where(p => builder.Options.Language.ProjectFileHasThisLanguage(p)). + Select(p => builder.Actions.GetFullPath(FileUtils.ConvertToNative(p.AbsolutePath))). Select(p => new Project(builder, p)). ToArray(); } @@ -90,17 +72,11 @@ namespace Semmle.Autobuild { // We allow specifying projects as solutions in lgtm.yml, so model // that scenario as a solution with just that one project - Projects = Language.IsProjectFileForAnySupportedLanguage(Path) - ? new[] { new Project(builder, Path) } - : new Project[0]; + includedProjects = new[] { new Project(builder, path) }; } } - public string Path { get; private set; } - - public int ProjectCount => Projects.Count(); - - IEnumerable ToolsVersions => Projects.Where(p => p.ValidToolsVersion).Select(p => p.ToolsVersion); + IEnumerable ToolsVersions => includedProjects.Where(p => p.ValidToolsVersion).Select(p => p.ToolsVersion); public Version ToolsVersion => ToolsVersions.Any() ? ToolsVersions.Max() : new Version(); } diff --git a/csharp/extractor/Semmle.Autobuild/StandaloneBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/StandaloneBuildRule.cs rename to csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs diff --git a/csharp/extractor/Semmle.Autobuild/XmlBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs similarity index 100% rename from csharp/extractor/Semmle.Autobuild/XmlBuildRule.cs rename to csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs diff --git a/csharp/extractor/Semmle.Autobuild/Project.cs b/csharp/extractor/Semmle.Autobuild/Project.cs deleted file mode 100644 index e0a1ee8386d..00000000000 --- a/csharp/extractor/Semmle.Autobuild/Project.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.IO; -using System.Xml; -using Semmle.Util.Logging; - -namespace Semmle.Autobuild -{ - /// - /// Representation of a .csproj (C#) or .vcxproj (C++) file. - /// C# project files come in 2 flavours, .Net core and msbuild, but they - /// have the same file extension. - /// - public class Project - { - /// - /// Holds if this project is for .Net core. - /// - public bool DotNetProject { get; private set; } - - public bool ValidToolsVersion { get; private set; } - - public Version ToolsVersion { get; private set; } - - readonly string filename; - - public Project(Autobuilder builder, string filename) - { - this.filename = filename; - ToolsVersion = new Version(); - - if (!File.Exists(filename)) - return; - - var projFile = new XmlDocument(); - projFile.Load(filename); - var root = projFile.DocumentElement; - - if (root.Name == "Project") - { - if (root.HasAttribute("Sdk")) - { - DotNetProject = true; - } - else - { - var toolsVersion = root.GetAttribute("ToolsVersion"); - if (string.IsNullOrEmpty(toolsVersion)) - { - builder.Log(Severity.Warning, "Project {0} is missing a tools version", filename); - } - else - { - try - { - ToolsVersion = new Version(toolsVersion); - ValidToolsVersion = true; - } - catch // Generic catch clause - Version constructor throws about 5 different exceptions. - { - builder.Log(Severity.Warning, "Project {0} has invalid tools version {1}", filename, toolsVersion); - } - } - } - } - } - - public override string ToString() => filename; - } -} diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.qhelp b/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.qhelp index faf3e92865c..2b31cb13e54 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.qhelp +++ b/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.qhelp @@ -8,7 +8,7 @@ This makes the controls easier to find in Intellisense and also makes the purpos -

Give controls an appropriate prefix to indicate their type (e.g. txt for text boxes or rad for +

Give controls an appropriate prefix to indicate their type (for example, txt for text boxes or rad for radio buttons).

diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.ql b/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.ql index c45e91e117b..4c0814f6ae8 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.ql @@ -1,7 +1,7 @@ /** * @name ASP.NET control name prefixes - * @description This query checks that certain prefixes are used for naming fields for - * ASP.NET Web / HTML controls. + * @description Including standard prefixes in the field names of + * ASP.NET Web / HTML controls makes code easier to understand. * @kind problem * @problem.severity recommendation * @precision medium diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.qhelp b/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.qhelp index f16003b96ff..e5fc96bbaba 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.qhelp +++ b/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.qhelp @@ -3,11 +3,12 @@ "qhelp.dtd"> -

This rule identifies Windows form controls that have a default name such as textBox1 -.

+

This query identifies Windows form controls that have a default name such as textBox1 +. Replacing the default names with names that describe their purpose makes it much easier for other +developers to understand your code.

-

Give controls meaningful names that relate to their purpose.

+

Give controls meaningful names that indicate their purpose.

diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql b/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql index c97f271d6d3..28a238febba 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql @@ -1,6 +1,7 @@ /** * @name Windows controls with generated names - * @description Finds fields, corresponding to windows-forms controls, with generated names (such as "label1" or "PictureBox4"). + * @description Replacing the generated names in windows forms with meaningful names + makes it easier for other developers to understand the code. * @kind problem * @problem.severity recommendation * @precision medium diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.qhelp b/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.qhelp index 4ba33ffdf09..41e1ac06449 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.qhelp +++ b/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.qhelp @@ -3,7 +3,7 @@ "qhelp.dtd"> -

Source code with lots of short variable names is likely to be hard to read.

+

Source code with lots of short variable names is likely to be difficult to read.

diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql b/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql index e7660b72825..90b31d1886e 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql @@ -1,6 +1,6 @@ /** * @name Variable name is too short - * @description Variables should have meaningful names so that code is comprehensible. This query finds variable names that are too short. + * @description Using meaningful names for variables makes code easier to understand. * @kind problem * @problem.severity recommendation * @precision low diff --git a/csharp/ql/src/Security Features/CWE-022/TaintedPath.ql b/csharp/ql/src/Security Features/CWE-022/TaintedPath.ql index 76b940631a2..d08cc2ca564 100644 --- a/csharp/ql/src/Security Features/CWE-022/TaintedPath.ql +++ b/csharp/ql/src/Security Features/CWE-022/TaintedPath.ql @@ -1,7 +1,7 @@ /** * @name Uncontrolled data used in path expression * @description Accessing paths influenced by users can allow an attacker to access unexpected resources. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/path-injection @@ -14,7 +14,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.TaintedPath::TaintedPath +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in a path.", source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in a path.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-022/ZipSlip.ql b/csharp/ql/src/Security Features/CWE-022/ZipSlip.ql index 37969f0b6eb..fc687c1d6b2 100644 --- a/csharp/ql/src/Security Features/CWE-022/ZipSlip.ql +++ b/csharp/ql/src/Security Features/CWE-022/ZipSlip.ql @@ -3,7 +3,7 @@ * @description Extracting files from a malicious zip archive without validating that the * destination file path is within the destination directory can cause files outside * the destination directory to be overwritten. - * @kind problem + * @kind path-problem * @id cs/zipslip * @problem.severity error * @precision high @@ -13,7 +13,9 @@ import csharp import semmle.code.csharp.security.dataflow.ZipSlip::ZipSlip +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration zipTaintTracking, DataFlow::Node source, DataFlow::Node sink -where zipTaintTracking.hasFlow(source, sink) -select sink, "Unsanitized zip archive $@, which may contain '..', is used in a file system operation.", source, "item path" +from TaintTrackingConfiguration zipTaintTracking, DataFlow::PathNode source, DataFlow::PathNode sink +where zipTaintTracking.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Unsanitized zip archive $@, which may contain '..', is used in a file system operation.", source.getNode(), "item path" diff --git a/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql b/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql index 17dec56988f..337d191eae1 100644 --- a/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql +++ b/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql @@ -2,7 +2,7 @@ * @name Uncontrolled command line * @description Using externally controlled strings in a command line may allow a malicious * user to change the meaning of the command. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/command-line-injection @@ -14,7 +14,9 @@ import csharp import semmle.code.csharp.security.dataflow.CommandInjection::CommandInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in a command.", source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in a command.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql b/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql index acd883e106c..be51a9e347e 100644 --- a/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql +++ b/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql @@ -2,7 +2,7 @@ * @name Uncontrolled command line from stored user input * @description Using externally controlled strings in a command line may allow a malicious * user to change the meaning of the command. - * @kind problem + * @kind path-problem * @problem.severity error * @precision medium * @id cs/stored-command-line-injection @@ -15,6 +15,7 @@ import csharp import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.security.dataflow.CommandInjection::CommandInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { override predicate isSource(DataFlow::Node source) { @@ -22,6 +23,7 @@ class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { } } -from StoredTaintTrackingConfiguration c, StoredFlowSource source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in a command.", source, "Stored user-provided value" +from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in a command.", source.getNode(), "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-079/StoredXSS.ql b/csharp/ql/src/Security Features/CWE-079/StoredXSS.ql index 91fe8b2616c..80f16f35d4a 100644 --- a/csharp/ql/src/Security Features/CWE-079/StoredXSS.ql +++ b/csharp/ql/src/Security Features/CWE-079/StoredXSS.ql @@ -2,7 +2,7 @@ * @name Stored cross-site scripting * @description Writing input from the database directly to a web page indicates a cross-site * scripting vulnerability if the data was originally user-provided. - * @kind problem + * @kind path-problem * @problem.severity error * @precision medium * @id cs/web/stored-xss @@ -13,6 +13,7 @@ import csharp import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.security.dataflow.XSS::XSS +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { override predicate isSource(DataFlow::Node source) { @@ -20,10 +21,11 @@ class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { } } -from StoredTaintTrackingConfiguration c, StoredFlowSource source, Sink sink, string explanation -where c.hasFlow(source, sink) +from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink, string explanation +where c.hasFlowPath(source, sink) and - if exists(sink.explanation()) - then explanation = ": " + sink.explanation() + "." + if exists(sink.getNode().(Sink).explanation()) + then explanation = ": " + sink.getNode().(Sink).explanation() + "." else explanation = "." -select sink, "$@ flows to here and is written to HTML or javascript" + explanation, source, "Stored user-provided value" +select sink.getNode(), source, sink, + "$@ flows to here and is written to HTML or JavaScript" + explanation, source.getNode(), "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-089/SecondOrderSqlInjection.ql b/csharp/ql/src/Security Features/CWE-089/SecondOrderSqlInjection.ql index b7fb79ccf37..3e533dfd993 100644 --- a/csharp/ql/src/Security Features/CWE-089/SecondOrderSqlInjection.ql +++ b/csharp/ql/src/Security Features/CWE-089/SecondOrderSqlInjection.ql @@ -2,7 +2,7 @@ * @name SQL query built from stored user-controlled sources * @description Building a SQL query from stored user-controlled sources is vulnerable to insertion * of malicious SQL code by the user. - * @kind problem + * @kind path-problem * @problem.severity error * @precision medium * @id cs/second-order-sql-injection @@ -13,6 +13,7 @@ import csharp import semmle.code.csharp.security.dataflow.SqlInjection import semmle.code.csharp.security.dataflow.flowsources.Stored +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends SqlInjection::TaintTrackingConfiguration { override predicate isSource(DataFlow::Node source) { @@ -20,6 +21,7 @@ class StoredTaintTrackingConfiguration extends SqlInjection::TaintTrackingConfig } } -from StoredTaintTrackingConfiguration c, DataFlow::Node source, DataFlow::Node sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in an SQL query.", source, "Stored user-provided value" +from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in an SQL query.", source.getNode(), "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-089/SqlInjection.ql b/csharp/ql/src/Security Features/CWE-089/SqlInjection.ql index b3973132808..f06eab7ef37 100644 --- a/csharp/ql/src/Security Features/CWE-089/SqlInjection.ql +++ b/csharp/ql/src/Security Features/CWE-089/SqlInjection.ql @@ -2,7 +2,7 @@ * @name SQL query built from user-controlled sources * @description Building a SQL query from user-controlled sources is vulnerable to insertion of * malicious SQL code by the user. -* @kind problem +* @kind path-problem * @problem.severity error * @precision high * @id cs/sql-injection @@ -12,7 +12,9 @@ import csharp import semmle.code.csharp.security.dataflow.SqlInjection::SqlInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, RemoteFlowSource source, Sink sink -where c.hasFlow(source, sink) -select sink, "Query might include code from $@.", source, ("this " + source.getSourceType()) +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Query might include code from $@.", source, ("this " + source.getNode().(RemoteFlowSource).getSourceType()) diff --git a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql index b5688b7ac41..669e82e1d7e 100644 --- a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql +++ b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql @@ -2,7 +2,7 @@ * @name LDAP query built from user-controlled sources * @description Building an LDAP query from user-controlled sources is vulnerable to insertion of * malicious LDAP code by the user. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/ldap-injection @@ -11,7 +11,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.LDAPInjection::LDAPInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in an LDAP query.", source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in an LDAP query.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-090/StoredLDAPInjection.ql b/csharp/ql/src/Security Features/CWE-090/StoredLDAPInjection.ql index 0cea7f63113..846ad8735ac 100644 --- a/csharp/ql/src/Security Features/CWE-090/StoredLDAPInjection.ql +++ b/csharp/ql/src/Security Features/CWE-090/StoredLDAPInjection.ql @@ -2,7 +2,7 @@ * @name LDAP query built from stored user-controlled sources * @description Building an LDAP query from stored user-controlled sources is vulnerable to * insertion of malicious LDAP code by the user. - * @kind problem + * @kind path-problem * @problem.severity error * @precision medium * @id cs/stored-ldap-injection @@ -12,6 +12,7 @@ import csharp import semmle.code.csharp.security.dataflow.LDAPInjection::LDAPInjection import semmle.code.csharp.security.dataflow.flowsources.Stored +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { override predicate isSource(DataFlow::Node source) { @@ -19,6 +20,7 @@ class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { } } -from StoredTaintTrackingConfiguration c, StoredFlowSource source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in an LDAP query.", source, "Stored user-provided value" +from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in an LDAP query.", source.getNode(), "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql b/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql index d97498f0f12..de26ec087e1 100644 --- a/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql +++ b/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql @@ -2,7 +2,7 @@ * @name Improper control of generation of code * @description Treating externally controlled strings as code can allow an attacker to execute * malicious code. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/code-injection @@ -13,7 +13,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.CodeInjection::CodeInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is compiled as code.", source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is compiled as code.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql b/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql index 9853f0c0098..50b3bc2c45f 100644 --- a/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql +++ b/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql @@ -2,7 +2,7 @@ * @name Resource injection * @description Building a resource descriptor from untrusted user input is vulnerable to a * malicious user providing an unintended resource. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/resource-injection @@ -11,7 +11,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.ResourceInjection::ResourceInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in a resource descriptor.", source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in a resource descriptor.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql b/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql index ae4228a5c3a..e2c051f260e 100644 --- a/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql +++ b/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql @@ -2,7 +2,7 @@ * @name Missing XML validation * @description User input should not be processed as XML without validating it against a known * schema. - * @kind problem + * @kind path-problem * @problem.severity recommendation * @precision high * @id cs/xml/missing-validation @@ -11,7 +11,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.MissingXMLValidation::MissingXMLValidation +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is processed as XML without validation because " + sink.getReason(), source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is processed as XML without validation because " + sink.getNode().(Sink).getReason(), source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-117/LogForging.ql b/csharp/ql/src/Security Features/CWE-117/LogForging.ql index 32068cf59e2..010a46f0650 100644 --- a/csharp/ql/src/Security Features/CWE-117/LogForging.ql +++ b/csharp/ql/src/Security Features/CWE-117/LogForging.ql @@ -2,7 +2,7 @@ * @name Log entries created from user input * @description Building log entries from user-controlled sources is vulnerable to * insertion of forged log entries by a malicious user. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/log-forging @@ -11,7 +11,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.LogForging::LogForging +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to log entry.", source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to log entry.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql b/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql index 3c2e9350a2d..13377c0e39d 100644 --- a/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql +++ b/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql @@ -1,7 +1,7 @@ /** * @name Information exposure through transmitted data * @description Transmitting sensitive information to the user is a potential security risk. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/sensitive-data-transmission @@ -15,6 +15,7 @@ import semmle.code.csharp.security.dataflow.XSS import semmle.code.csharp.security.dataflow.Email import semmle.code.csharp.frameworks.system.data.Common import semmle.code.csharp.frameworks.System +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class TaintTrackingConfiguration extends TaintTracking::Configuration { TaintTrackingConfiguration() { @@ -49,6 +50,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { } } -from TaintTrackingConfiguration configuration, DataFlow::Node source, DataFlow::Node sink -where configuration.hasFlow(source, sink) -select sink, "Sensitive information from $@ flows to here, and is transmitted to the user.", source, source.toString() +from TaintTrackingConfiguration configuration, DataFlow::PathNode source, DataFlow::PathNode sink +where configuration.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Sensitive information from $@ flows to here, and is transmitted to the user.", source.getNode(), source.toString() diff --git a/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql b/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql index b895b50321b..92e0a2c2905 100644 --- a/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql +++ b/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql @@ -3,7 +3,7 @@ * @description Leaking information about an exception, such as messages and stack traces, to an * external user can expose implementation details that are useful to an attacker for * developing a subsequent exploit. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/information-exposure-through-exception @@ -15,6 +15,7 @@ import csharp import semmle.code.csharp.frameworks.System import semmle.code.csharp.security.dataflow.XSS +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph /** * A taint-tracking configuration for reasoning about stack traces that flow to web page outputs. @@ -56,6 +57,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { } } -from TaintTrackingConfiguration c, DataFlow::Node source, DataFlow::Node sink -where c.hasFlow(source, sink) -select sink, "Exception information from $@ flows to here, and is exposed to the user.", source, source.toString() +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Exception information from $@ flows to here, and is exposed to the user.", source.getNode(), source.toString() diff --git a/csharp/ql/src/Security Features/CWE-312/CleartextStorage.ql b/csharp/ql/src/Security Features/CWE-312/CleartextStorage.ql index e44ad181727..86a40318b83 100644 --- a/csharp/ql/src/Security Features/CWE-312/CleartextStorage.ql +++ b/csharp/ql/src/Security Features/CWE-312/CleartextStorage.ql @@ -2,7 +2,7 @@ * @name Clear text storage of sensitive information * @description Sensitive information stored without encryption or hashing can expose it to an * attacker. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/cleartext-storage-of-sensitive-information @@ -13,7 +13,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.CleartextStorage::CleartextStorage +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "Sensitive data returned by $@ is stored here.", source, source.toString() +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Sensitive data returned by $@ is stored here.", source.getNode(), source.toString() diff --git a/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql b/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql index 412af8e43f7..3a4293fddac 100644 --- a/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql +++ b/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql @@ -2,7 +2,7 @@ * @name Do not add certificates to the system root store. * @description Application- or user-specific certificates placed in the system root store could * weaken security for other processing running on the same system. - * @kind problem + * @kind path-problem * @id cs/adding-cert-to-root-store * @problem.severity error * @tags security @@ -10,6 +10,7 @@ */ import csharp import semmle.code.csharp.dataflow.DataFlow::DataFlow +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class AddCertToRootStoreConfig extends DataFlow::Configuration { AddCertToRootStoreConfig() { this = "Adding Certificate To Root Store" } @@ -30,7 +31,8 @@ class AddCertToRootStoreConfig extends DataFlow::Configuration { } } -from Expr oc, Expr mc, AddCertToRootStoreConfig config -where config.hasFlow(DataFlow::exprNode(oc), DataFlow::exprNode(mc)) -select mc, "Certificate added to the root certificate store." +from DataFlow::PathNode oc, DataFlow::PathNode mc, AddCertToRootStoreConfig config +where config.hasFlowPath(oc, mc) +select mc.getNode(), oc, mc, + "Certificate added to the root certificate store." diff --git a/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql b/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql index 5b8dad5f931..9f952f4db50 100644 --- a/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql +++ b/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql @@ -2,7 +2,7 @@ * @name Exposure of private information * @description If private information is written to an external location, it may be accessible by * unauthorized persons. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/exposure-of-sensitive-information @@ -11,7 +11,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.ExposureOfPrivateInformation::ExposureOfPrivateInformation +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "Private data returned by $@ is written to an external location.", source, source.toString() +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Private data returned by $@ is written to an external location.", source.getNode(), source.getNode().toString() diff --git a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql index b2a148e10a6..e951bba312d 100644 --- a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql +++ b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql @@ -2,7 +2,7 @@ * @name URL redirection from remote source * @description URL redirection based on unvalidated user input * may cause redirection to malicious web sites. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/web/unvalidated-url-redirection @@ -11,7 +11,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.UrlRedirect::UrlRedirect +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "Untrusted URL redirection due to $@.", source, "user-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Untrusted URL redirection due to $@.", source.getNode(), "user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql b/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql index 09f8fa924be..6458534cbf4 100644 --- a/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql +++ b/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql @@ -1,7 +1,7 @@ /** * @name Untrusted XML is read insecurely * @description Untrusted XML is read with an insecure resolver and DTD processing enabled. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/xml/insecure-dtd-handling @@ -12,7 +12,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.XMLEntityInjection::XMLEntityInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is loaded insecurely as XML (" + sink.getReason() +").", source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is loaded insecurely as XML (" + sink.getNode().(Sink).getReason() +").", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-643/StoredXPathInjection.ql b/csharp/ql/src/Security Features/CWE-643/StoredXPathInjection.ql index 2dd94bd1fb3..3734533d9f0 100644 --- a/csharp/ql/src/Security Features/CWE-643/StoredXPathInjection.ql +++ b/csharp/ql/src/Security Features/CWE-643/StoredXPathInjection.ql @@ -2,7 +2,7 @@ * @name Stored XPath injection * @description Building an XPath expression from stored data which may have been provided by the * user is vulnerable to insertion of malicious code by the user. - * @kind problem + * @kind path-problem * @problem.severity error * @precision medium * @id cs/xml/stored-xpath-injection @@ -12,6 +12,7 @@ import csharp import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.security.dataflow.XPathInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends XPathInjection::TaintTrackingConfiguration { override @@ -20,6 +21,7 @@ class StoredTaintTrackingConfiguration extends XPathInjection::TaintTrackingConf } } -from StoredTaintTrackingConfiguration c, DataFlow::Node source, DataFlow::Node sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in an XPath expression.", source, "Stored user-provided value" +from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in an XPath expression.", source.getNode(), "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql b/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql index 4206884d76c..e5eba0b9db4 100644 --- a/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql +++ b/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql @@ -2,7 +2,7 @@ * @name XPath injection * @description Building an XPath expression from user-controlled sources is vulnerable to insertion of * malicious code by the user. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/xml/xpath-injection @@ -11,7 +11,9 @@ */ import csharp import semmle.code.csharp.security.dataflow.XPathInjection::XPathInjection +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) -select sink, "$@ flows to here and is used in an XPath expression.", source, "User-provided value" +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "$@ flows to here and is used in an XPath expression.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-730/ReDoS.ql b/csharp/ql/src/Security Features/CWE-730/ReDoS.ql index 9e75c1aa1bb..f1dbe5a068e 100644 --- a/csharp/ql/src/Security Features/CWE-730/ReDoS.ql +++ b/csharp/ql/src/Security Features/CWE-730/ReDoS.ql @@ -2,7 +2,7 @@ * @name Denial of Service from comparison of user input against expensive regex * @description User input should not be matched against a regular expression that could require * exponential time on certain input. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/redos @@ -13,9 +13,17 @@ import csharp import semmle.code.csharp.security.dataflow.ReDoS::ReDoS import semmle.code.csharp.frameworks.system.text.RegularExpressions +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, DataFlow::Node sink -where c.hasFlow(source, sink) +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where + c.hasFlowPath(source, sink) and // No global timeout set - and not exists(RegexGlobalTimeout r) -select sink, "$@ flows to regular expression operation with dangerous regex.", source, "User-provided value" + not exists(RegexGlobalTimeout r) and + ( + sink.getNode() instanceof Sink + or + sink.getNode() instanceof ExponentialRegexSink + ) +select sink.getNode(), source, sink, + "$@ flows to regular expression operation with dangerous regex.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql b/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql index 4e3bacc8b60..2582acc7ebe 100644 --- a/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql +++ b/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql @@ -3,7 +3,7 @@ * @description User input should not be used in regular expressions without first being escaped, * otherwise a malicious user may be able to provide a regex that could require * exponential time on certain inputs. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/regex-injection @@ -14,9 +14,11 @@ import csharp import semmle.code.csharp.security.dataflow.RegexInjection::RegexInjection import semmle.code.csharp.frameworks.system.text.RegularExpressions +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink -where c.hasFlow(source, sink) +from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) // No global timeout set and not exists(RegexGlobalTimeout r) -select sink, "$@ flows to the construction of a regular expression.", source, "User-provided value" +select sink.getNode(), source, sink, + "$@ flows to the construction of a regular expression.", source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql b/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql index a2376bdbd23..481268366cb 100644 --- a/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql +++ b/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql @@ -1,7 +1,7 @@ /** * @name Hard-coded connection string with credentials * @description Credentials are hard-coded in a connection string in the source code of the application. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/hardcoded-connection-string-credentials @@ -13,6 +13,7 @@ import csharp import semmle.code.csharp.frameworks.system.Data import semmle.code.csharp.security.dataflow.HardcodedCredentials +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph /** * A string literal containing a username or password field. @@ -47,6 +48,8 @@ class ConnectionStringTaintTrackingConfiguration extends TaintTracking::Configur } } -from ConnectionStringTaintTrackingConfiguration c, DataFlow::Node source, DataFlow::Node sink -where c.hasFlow(source, sink) -select source, "'ConnectionString' property includes hard-coded credentials set in $@.", any(Call call | call.getAnArgument() = sink.asExpr()) as call, call.toString() +from ConnectionStringTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +where c.hasFlowPath(source, sink) +select source.getNode(), source, sink, + "'ConnectionString' property includes hard-coded credentials set in $@.", + any(Call call | call.getAnArgument() = sink.getNode().asExpr()) as call, call.toString() diff --git a/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql b/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql index 05f24d0810e..11d4307d05e 100644 --- a/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql +++ b/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql @@ -1,7 +1,7 @@ /** * @name Hard-coded credentials * @description Credentials are hard coded in the source code of the application. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/hardcoded-credentials @@ -11,13 +11,21 @@ * external/cwe/cwe-798 */ import csharp -private import semmle.code.csharp.security.dataflow.HardcodedCredentials::HardcodedCredentials +import semmle.code.csharp.security.dataflow.HardcodedCredentials::HardcodedCredentials +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink, string value -where c.hasFlow(source, sink) +from TaintTrackingConfiguration c, Source source, Sink sink, DataFlow::PathNode sourcePath, DataFlow::PathNode sinkPath, + string value +where + source = sourcePath.getNode() and + sink = sinkPath.getNode() and + c.hasFlow(source, sink) and // Print the source value if it's available - and if exists(source.asExpr().getValue()) then + if exists(source.asExpr().getValue()) then value = "The hard-coded value \"" + source.asExpr().getValue() + "\"" else value = "This hard-coded value" -select source, value + " flows to " + sink.getSinkDescription() + ".", sink, sink.getSinkName(), sink.getSupplementaryElement(), sink.getSupplementaryElement().toString() +select source, sourcePath, sinkPath, + value + " flows to " + sink.getSinkDescription() + ".", + sink, sink.getSinkName(), sink.getSupplementaryElement(), + sink.getSupplementaryElement().toString() diff --git a/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql b/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql index e2399be992b..cf16ee88306 100644 --- a/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql +++ b/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql @@ -2,7 +2,7 @@ * @name User-controlled bypass of sensitive method * @description User-controlled bypassing of sensitive methods may allow attackers to avoid * passing through authentication systems. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cs/user-controlled-bypass @@ -13,8 +13,10 @@ */ import csharp import semmle.code.csharp.security.dataflow.ConditionalBypass::UserControlledBypassOfSensitiveMethod +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from Configuration config, Source source, Sink sink -where config.hasFlow(source, sink) -select sink.getSensitiveMethodCall(), "Sensitive method may not be executed depending on $@, which flows from $@.", - sink, "this condition", source, "user input" +from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode().(Sink).getSensitiveMethodCall(), source, sink, + "Sensitive method may not be executed depending on $@, which flows from $@.", + sink.getNode(), "this condition", source.getNode(), "user input" diff --git a/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql b/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql index d429bb0c0d2..133f1f3b3b2 100644 --- a/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql +++ b/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql @@ -2,7 +2,7 @@ * @name Inappropriate encoding * @description Using an inappropriate encoding may give unintended results and may * pose a security risk. -* @kind problem +* @kind path-problem * @problem.severity error * @precision low * @id cs/inappropriate-encoding @@ -20,6 +20,7 @@ import semmle.code.csharp.security.dataflow.SqlInjection import semmle.code.csharp.security.dataflow.XSS import semmle.code.csharp.security.dataflow.UrlRedirect import semmle.code.csharp.security.Sanitizers +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph /** * A configuration for specifying expressions that must be @@ -43,8 +44,8 @@ abstract class RequiresEncodingConfiguration extends TaintTracking::Configuratio * `sink`, where `sink` is an expression of kind `kind` that is required * to be encoded. */ - predicate hasWrongEncoding(Expr encodedValue, Expr sink, string kind) { - hasFlow(exprNode(encodedValue), exprNode(sink)) and + predicate hasWrongEncoding(PathNode encodedValue, PathNode sink, string kind) { + hasFlowPath(encodedValue, sink) and kind = this.getKind() } @@ -153,6 +154,7 @@ module EncodingConfigurations { } } -from RequiresEncodingConfiguration c, Expr encodedValue, Expr sink, string kind +from RequiresEncodingConfiguration c, PathNode encodedValue, PathNode sink, string kind where c.hasWrongEncoding(encodedValue, sink, kind) -select sink, "This " + kind + " may include data from a $@.", encodedValue, "possibly inappropriately encoded value" +select sink.getNode(), encodedValue, sink, + "This " + kind + " may include data from a $@.", encodedValue.getNode(), "possibly inappropriately encoded value" diff --git a/csharp/ql/src/Security Features/InsecureRandomness.ql b/csharp/ql/src/Security Features/InsecureRandomness.ql index b03b49f2264..37dd0f1d481 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.ql +++ b/csharp/ql/src/Security Features/InsecureRandomness.ql @@ -3,7 +3,7 @@ * @description Using a cryptographically weak pseudo-random number generator to generate a * security sensitive value may allow an attacker to predict what sensitive value will * be generated. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision high * @id cs/insecure-randomness @@ -12,6 +12,7 @@ */ import csharp import semmle.code.csharp.frameworks.Test +import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph module Random { import semmle.code.csharp.dataflow.flowsources.Remote @@ -103,6 +104,7 @@ module Random { } } -from Random::TaintTrackingConfiguration randomTracking, Random::Source source, Random::Sink sink -where randomTracking.hasFlow(source, sink) -select sink, "Cryptographically insecure random number is generated at $@ and used here in a security context.", source, source.toString() +from Random::TaintTrackingConfiguration randomTracking, DataFlow::PathNode source, DataFlow::PathNode sink +where randomTracking.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Cryptographically insecure random number is generated at $@ and used here in a security context.", source.getNode(), source.getNode().toString() diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll index aa7bf06f2a2..14d12af5219 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll @@ -2516,8 +2516,12 @@ module ControlFlow { result = strictcount(getAnElement()) } + predicate immediatelyDominates(PreBasicBlock bb) { + bbIDominates(this, bb) + } + predicate strictlyDominates(PreBasicBlock bb) { - bbIDominates+(this, bb) + this.immediatelyDominates+(bb) } predicate dominates(PreBasicBlock bb) { @@ -2565,7 +2569,8 @@ module ControlFlow { /** * Provides an SSA implementation based on "pre-basic-blocks", restricted - * to local scope variables. + * to local scope variables and fields/properties that behave like local + * scope variables. * * The logic is duplicated from the implementation in `SSA.qll`, and * being an internal class, all predicate documentation has been removed. @@ -2574,17 +2579,40 @@ module ControlFlow { private import PreBasicBlocks private import AssignableDefinitions - class SimpleLocalScopeVariable extends LocalScopeVariable { - SimpleLocalScopeVariable() { - not exists(AssignableDefinition def1, AssignableDefinition def2 | - def1.getTarget() = this and - def2.getTarget() = this and - def1.getEnclosingCallable() != def2.getEnclosingCallable() + /** + * A simple assignable. Either a local scope variable or a field/property + * that behaves like a local scope variable. + */ + class SimpleAssignable extends Assignable { + private Callable c; + + SimpleAssignable() { + ( + this instanceof LocalScopeVariable + or + this instanceof Field + or + this = any(TrivialProperty tp | not tp.isOverridableOrImplementable()) + ) and + forall(AssignableDefinition def | + def.getTarget() = this | + c = def.getEnclosingCallable() + or + def.getEnclosingCallable() instanceof Constructor + ) and + exists(AssignableAccess aa | + aa.getTarget() = this | + c = aa.getEnclosingCallable() + ) and + forall(QualifiableExpr qe | + qe.(AssignableAccess).getTarget() = this | + qe.targetIsThisInstance() ) } - } - private newtype SsaRefKind = SsaRead() or SsaDef() + /** Gets a callable in which this simple assignable can be analyzed. */ + Callable getACallable() { result = c } + } class Definition extends TPreSsaDef { string toString() { @@ -2593,22 +2621,29 @@ module ControlFlow { result = def.toString() ) or - exists(SimpleLocalScopeVariable v | - this = TPhiPreSsaDef(_, v) | - result = "phi(" + v.toString() + ")" + exists(SimpleAssignable a | + this = TImplicitEntryPreSsaDef(_, _, a) | + result = "implicit(" + a + ")" + ) + or + exists(SimpleAssignable a | + this = TPhiPreSsaDef(_, a) | + result = "phi(" + a.toString() + ")" ) } - SimpleLocalScopeVariable getVariable() { + SimpleAssignable getAssignable() { this = TExplicitPreSsaDef(_, _, _, result) or + this = TImplicitEntryPreSsaDef(_, _, result) + or this = TPhiPreSsaDef(_, result) } - LocalScopeVariableRead getARead() { + AssignableRead getARead() { firstReadSameVar(this, result) or - exists(LocalScopeVariableRead read | + exists(AssignableRead read | firstReadSameVar(this, read) | adjacentReadPairSameVar+(read, result) ) @@ -2620,142 +2655,271 @@ module ControlFlow { result = def.getLocation() ) or + exists(Callable c | + this = TImplicitEntryPreSsaDef(c, _, _) | + result = c.getLocation() + ) + or exists(PreBasicBlock bb | this = TPhiPreSsaDef(bb, _) | result = bb.getLocation() ) } + PreBasicBlock getBasicBlock() { + this = TExplicitPreSsaDef(result, _, _, _) + or + this = TImplicitEntryPreSsaDef(_, result, _) + or + this = TPhiPreSsaDef(result, _) + } + + Callable getCallable() { + result = this.getBasicBlock().getEnclosingCallable() + } + AssignableDefinition getDefinition() { this = TExplicitPreSsaDef(_, _, result, _) } + + Definition getAPhiInput() { + exists(PreBasicBlock bb, PreBasicBlock phiPred, SimpleAssignable a | + this = TPhiPreSsaDef(bb, a) | + bb.getAPredecessor() = phiPred and + ssaDefReachesEndOfBlock(phiPred, result, a) + ) + } } - predicate assignableDefAt(PreBasicBlocks::PreBasicBlock bb, int i, AssignableDefinition def, SimpleLocalScopeVariable v) { + predicate implicitEntryDef(Callable c, PreBasicBlock bb, SimpleAssignable a) { + not a instanceof LocalScopeVariable and + c = a.getACallable() and + bb = succEntry(c) + } + + private predicate assignableDefAt(PreBasicBlocks::PreBasicBlock bb, int i, AssignableDefinition def, SimpleAssignable a) { bb.getElement(i) = def.getExpr() and - v = def.getTarget() and + a = def.getTarget() and // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def | second.getAssignment() = first.getAssignment() and second.getEvaluationOrder() > first.getEvaluationOrder() and - second.getTarget() = v + second.getTarget() = a ) or - def.(ImplicitParameterDefinition).getParameter() = v and + def.(ImplicitParameterDefinition).getParameter() = a and exists(Callable c | - v = c.getAParameter() | + a = c.getAParameter() | bb = succEntry(c) and i = -1 ) } - predicate defAt(PreBasicBlock bb, int i, Definition def, SimpleLocalScopeVariable v) { - def = TExplicitPreSsaDef(bb, i, _, v) - or - def = TPhiPreSsaDef(bb, v) and i = -1 - } - - private predicate readAt(PreBasicBlock bb, int i, LocalScopeVariableRead read, SimpleLocalScopeVariable v) { + private predicate readAt(PreBasicBlock bb, int i, AssignableRead read, SimpleAssignable a) { read = bb.getElement(i) and - read.getTarget() = v + read.getTarget() = a } - private predicate ssaRef(PreBasicBlock bb, int i, SimpleLocalScopeVariable v, SsaRefKind k) { - readAt(bb, i, _, v) and + pragma[noinline] + private predicate exitBlock(PreBasicBlock bb, Callable c) { + exists(succExit(bb.getLastElement(), _)) and + c = bb.getEnclosingCallable() + } + + private predicate outRefExitRead(PreBasicBlock bb, int i, LocalScopeVariable v) { + exitBlock(bb, v.getCallable()) and + i = bb.length() + 1 and + (v.isRef() or v.(Parameter).isOut()) + } + + private newtype RefKind = + Read() + or + Write(boolean certain) { certain = true or certain = false } + + private predicate ref(PreBasicBlock bb, int i, SimpleAssignable a, RefKind k) { + (readAt(bb, i, _, a) or outRefExitRead(bb, i, a)) and + k = Read() + or + exists(AssignableDefinition def, boolean certain | + assignableDefAt(bb, i, def, a) | + if def.getTargetAccess().isRefArgument() then certain = false else certain = true and + k = Write(certain) + ) + } + + private int refRank(PreBasicBlock bb, int i, SimpleAssignable a, RefKind k) { + i = rank[result](int j | ref(bb, j, a, _)) and + ref(bb, i, a, k) + } + + private int maxRefRank(PreBasicBlock bb, SimpleAssignable a) { + result = refRank(bb, _, a, _) and + not result + 1 = refRank(bb, _, a, _) + } + + private int firstReadOrCertainWrite(PreBasicBlock bb, SimpleAssignable a) { + result = min(int r, RefKind k | + r = refRank(bb, _, a, k) and + k != Write(false) + | + r + ) + } + + predicate liveAtEntry(PreBasicBlock bb, SimpleAssignable a) { + refRank(bb, _, a, Read()) = firstReadOrCertainWrite(bb, a) + or + not exists(firstReadOrCertainWrite(bb, a)) and + liveAtExit(bb, a) + } + + private predicate liveAtExit(PreBasicBlock bb, SimpleAssignable a) { + liveAtEntry(bb.getASuccessor(), a) + } + + predicate assignableDefAtLive(PreBasicBlocks::PreBasicBlock bb, int i, AssignableDefinition def, SimpleAssignable a) { + assignableDefAt(bb, i, def, a) and + exists(int rnk | + rnk = refRank(bb, i, a, Write(_)) | + rnk + 1 = refRank(bb, _, a, Read()) + or + rnk = maxRefRank(bb, a) and + liveAtExit(bb, a) + ) + } + + predicate defAt(PreBasicBlock bb, int i, Definition def, SimpleAssignable a) { + def = TExplicitPreSsaDef(bb, i, _, a) + or + def = TImplicitEntryPreSsaDef(_, bb, a) and i = -1 + or + def = TPhiPreSsaDef(bb, a) and i = -1 + } + + private newtype SsaRefKind = SsaRead() or SsaDef() + + private predicate ssaRef(PreBasicBlock bb, int i, SimpleAssignable a, SsaRefKind k) { + readAt(bb, i, _, a) and k = SsaRead() or - defAt(bb, i, _, v) and + defAt(bb, i, _, a) and k = SsaDef() } - private int ssaRefRank(PreBasicBlock bb, int i, SimpleLocalScopeVariable v, SsaRefKind k) { - i = rank[result](int j | ssaRef(bb, j, v, _)) and - ssaRef(bb, i, v, k) + private int ssaRefRank(PreBasicBlock bb, int i, SimpleAssignable a, SsaRefKind k) { + i = rank[result](int j | ssaRef(bb, j, a, _)) and + ssaRef(bb, i, a, k) } - private predicate defReachesRank(PreBasicBlock bb, Definition def, SimpleLocalScopeVariable v, int rnk) { + private predicate defReachesRank(PreBasicBlock bb, Definition def, SimpleAssignable a, int rnk) { exists(int i | - rnk = ssaRefRank(bb, i, v, SsaDef()) and - defAt(bb, i, def, v) + rnk = ssaRefRank(bb, i, a, SsaDef()) and + defAt(bb, i, def, a) ) or - defReachesRank(bb, def, v, rnk - 1) and - rnk = ssaRefRank(bb, _, v, SsaRead()) + defReachesRank(bb, def, a, rnk - 1) and + rnk = ssaRefRank(bb, _, a, SsaRead()) } - private predicate reachesEndOf(Definition def, SimpleLocalScopeVariable v, PreBasicBlock bb) { - exists(int rnk | - defReachesRank(bb, def, v, rnk) and - rnk = max(ssaRefRank(bb, _, v, _)) + private int maxSsaRefRank(PreBasicBlock bb, SimpleAssignable a) { + result = ssaRefRank(bb, _, a, _) and + not result + 1 = ssaRefRank(bb, _, a, _) + } + + private predicate reachesEndOf(Definition def, SimpleAssignable a, PreBasicBlock bb) { + exists(int last | + last = maxSsaRefRank(bb, a) | + defReachesRank(bb, def, a, last) ) or exists(PreBasicBlock mid | - reachesEndOf(def, v, mid) and - not exists(ssaRefRank(mid, _, v, SsaDef())) and + reachesEndOf(def, a, mid) and + not exists(ssaRefRank(mid, _, a, SsaDef())) and bb = mid.getASuccessor() ) } - private predicate varOccursInBlock(SimpleLocalScopeVariable v, PreBasicBlock bb) { - exists(ssaRefRank(bb, _, v, _)) + private predicate varOccursInBlock(SimpleAssignable a, PreBasicBlock bb) { + exists(ssaRefRank(bb, _, a, _)) } pragma [nomagic] - private predicate blockPrecedesVar(SimpleLocalScopeVariable v, PreBasicBlock bb) { - varOccursInBlock(v, bb.getASuccessor*()) + private predicate blockPrecedesVar(SimpleAssignable a, PreBasicBlock bb) { + varOccursInBlock(a, bb.getASuccessor*()) } - private predicate varBlockReaches(SimpleLocalScopeVariable v, PreBasicBlock bb1, PreBasicBlock bb2) { - varOccursInBlock(v, bb1) and + private predicate varBlockReaches(SimpleAssignable a, PreBasicBlock bb1, PreBasicBlock bb2) { + varOccursInBlock(a, bb1) and bb2 = bb1.getASuccessor() and - blockPrecedesVar(v, bb2) + blockPrecedesVar(a, bb2) or - varBlockReachesRec(v, bb1, bb2) and - blockPrecedesVar(v, bb2) + varBlockReachesRec(a, bb1, bb2) and + blockPrecedesVar(a, bb2) } pragma [nomagic] - private predicate varBlockReachesRec(SimpleLocalScopeVariable v, PreBasicBlock bb1, PreBasicBlock bb2) { + private predicate varBlockReachesRec(SimpleAssignable a, PreBasicBlock bb1, PreBasicBlock bb2) { exists(PreBasicBlock mid | - varBlockReaches(v, bb1, mid) | + varBlockReaches(a, bb1, mid) | bb2 = mid.getASuccessor() and - not varOccursInBlock(v, mid) + not varOccursInBlock(a, mid) ) } - private predicate varBlockStep(SimpleLocalScopeVariable v, PreBasicBlock bb1, PreBasicBlock bb2) { - varBlockReaches(v, bb1, bb2) and - varOccursInBlock(v, bb2) + private predicate varBlockStep(SimpleAssignable a, PreBasicBlock bb1, PreBasicBlock bb2) { + varBlockReaches(a, bb1, bb2) and + varOccursInBlock(a, bb2) } - private predicate adjacentVarRefs(SimpleLocalScopeVariable v, PreBasicBlock bb1, int i1, PreBasicBlock bb2, int i2) { + private predicate adjacentVarRefs(SimpleAssignable a, PreBasicBlock bb1, int i1, PreBasicBlock bb2, int i2) { exists(int rankix | bb1 = bb2 and - rankix = ssaRefRank(bb1, i1, v, _) and - rankix + 1 = ssaRefRank(bb2, i2, v, _) + rankix = ssaRefRank(bb1, i1, a, _) and + rankix + 1 = ssaRefRank(bb2, i2, a, _) ) or - ssaRefRank(bb1, i1, v, _) = max(ssaRefRank(bb1, _, v, _)) and - varBlockStep(v, bb1, bb2) and - ssaRefRank(bb2, i2, v, _) = 1 + ssaRefRank(bb1, i1, a, _) = maxSsaRefRank(bb1, a) and + varBlockStep(a, bb1, bb2) and + ssaRefRank(bb2, i2, a, _) = 1 } - predicate firstReadSameVar(Definition def, LocalScopeVariableRead read) { - exists(SimpleLocalScopeVariable v, PreBasicBlock b1, int i1, PreBasicBlock b2, int i2 | - adjacentVarRefs(v, b1, i1, b2, i2) and - defAt(b1, i1, def, v) and - readAt(b2, i2, read, v) + predicate firstReadSameVar(Definition def, AssignableRead read) { + exists(SimpleAssignable a, PreBasicBlock b1, int i1, PreBasicBlock b2, int i2 | + adjacentVarRefs(a, b1, i1, b2, i2) and + defAt(b1, i1, def, a) and + readAt(b2, i2, read, a) ) } - predicate adjacentReadPairSameVar(LocalScopeVariableRead read1, LocalScopeVariableRead read2) { - exists(SimpleLocalScopeVariable v, PreBasicBlock bb1, int i1, PreBasicBlock bb2, int i2 | - adjacentVarRefs(v, bb1, i1, bb2, i2) and - readAt(bb1, i1, read1, v) and - readAt(bb2, i2, read2, v) + predicate adjacentReadPairSameVar(AssignableRead read1, AssignableRead read2) { + exists(SimpleAssignable a, PreBasicBlock bb1, int i1, PreBasicBlock bb2, int i2 | + adjacentVarRefs(a, bb1, i1, bb2, i2) and + readAt(bb1, i1, read1, a) and + readAt(bb2, i2, read2, a) ) } + + pragma[noinline] + private predicate ssaDefReachesEndOfBlockRec(PreBasicBlock bb, Definition def, SimpleAssignable a) { + exists(PreBasicBlock idom | + ssaDefReachesEndOfBlock(idom, def, a) | + idom.immediatelyDominates(bb) + ) + } + + predicate ssaDefReachesEndOfBlock(PreBasicBlock bb, Definition def, SimpleAssignable a) { + exists(int last | + last = maxSsaRefRank(bb, a) | + defReachesRank(bb, def, a, last) and + liveAtExit(bb, a) + ) + or + ssaDefReachesEndOfBlockRec(bb, def, a) and + liveAtExit(bb, a) and + not ssaRef(bb, _, a, SsaDef()) + } } /** @@ -3312,6 +3476,12 @@ module ControlFlow { this.correlatesConditions(any(ConditionBlock cb | cb.getLastElement() = cfe), _, _) } + /** + * Holds if basic block `bb` can reach a condition correlated with a + * split of this kind. + */ + abstract predicate canReachCorrelatedCondition(PreBasicBlock bb); + /** Gets the callable that this Boolean split kind belongs to. */ abstract Callable getEnclosingCallable(); @@ -3356,11 +3526,11 @@ module ControlFlow { * and `cb` can be reached from `read` without passing through another * condition that reads the same SSA variable. */ - private predicate defConditionReachableFromRead(ConditionBlock cb, LocalScopeVariableRead read) { + private predicate defConditionReachableFromRead(ConditionBlock cb, AssignableRead read) { this.defCondition(cb) and read = cb.getLastElement() or - exists(LocalScopeVariableRead mid | + exists(AssignableRead mid | this.defConditionReachableFromRead(cb, mid) | adjacentReadPairSameVar(read, mid) and not this.defCondition(read) @@ -3373,7 +3543,7 @@ module ControlFlow { * another condition that reads the same SSA variable. */ private predicate firstDefCondition(ConditionBlock cb) { - exists(LocalScopeVariableRead read | + exists(AssignableRead read | this.defConditionReachableFromRead(cb, read) | firstReadSameVar(def, read) ) @@ -3381,7 +3551,7 @@ module ControlFlow { override predicate correlatesConditions(ConditionBlock cb1, ConditionBlock cb2, boolean inverted) { this.firstDefCondition(cb1) and - exists(LocalScopeVariableRead read1, LocalScopeVariableRead read2 | + exists(AssignableRead read1, AssignableRead read2 | read1 = cb1.getLastElement() and adjacentReadPairSameVar+(read1, read2) and read2 = cb2.getLastElement() and @@ -3389,12 +3559,23 @@ module ControlFlow { ) } + override predicate canReachCorrelatedCondition(PreBasicBlock bb) { + this.correlatesConditions(_, bb, _) and + not def.getBasicBlock() = bb + or + exists(PreBasicBlock mid | + this.canReachCorrelatedCondition(mid) | + bb = mid.getAPredecessor() and + not def.getBasicBlock() = bb + ) + } + override Callable getEnclosingCallable() { - result = def.getVariable().getCallable() + result = def.getCallable() } override string toString() { - result = def.getVariable().toString() + result = def.getAssignable().toString() } override Location getLocation() { @@ -3472,7 +3653,7 @@ module ControlFlow { override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) { succ = succ(pred, c) and this.getSubKind().startsSplit(pred) and - c = any(BooleanCompletion bc | bc.getOuterValue() = this.getBranch()) + c = any(BooleanCompletion bc | bc.getInnerValue() = this.getBranch()) } private ConditionBlock getACorrelatedCondition(boolean inverted) { @@ -3498,26 +3679,13 @@ module ControlFlow { ) } - /** - * Holds if basic block `bb` can reach a condition correlated with the value - * recorded in this split. - */ - private predicate canReachCorrelatedCondition(PreBasicBlock bb) { - bb = this.getACorrelatedCondition(_) - or - exists(PreBasicBlock mid | - this.canReachCorrelatedCondition(mid) | - bb = mid.getAPredecessor() - ) - } - override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) { exists(PreBasicBlock bb | this.appliesToBlock(bb, c) | pred = bb.getLastElement() and succ = succ(pred, c) and // Exit this split if we can no longer reach a correlated condition - not this.canReachCorrelatedCondition(succ) + not this.getSubKind().canReachCorrelatedCondition(succ) ) } @@ -3538,7 +3706,7 @@ module ControlFlow { pred = bb.getLastElement() implies // We must still be able to reach a correlated condition to stay in this split - this.canReachCorrelatedCondition(succ) and + this.getSubKind().canReachCorrelatedCondition(succ) and c = c0 ) ) @@ -3843,18 +4011,29 @@ module ControlFlow { private cached module Cached { private import semmle.code.csharp.controlflow.Guards as Guards + pragma[noinline] + private predicate phiNodeMaybeLive(PreBasicBlocks::PreBasicBlock bb, PreSsa::SimpleAssignable a) { + exists(PreBasicBlocks::PreBasicBlock def | + PreSsa::defAt(def, _, _, a) | + def.inDominanceFrontier(bb) + ) + } + cached newtype TPreSsaDef = - TExplicitPreSsaDef(PreBasicBlocks::PreBasicBlock bb, int i, AssignableDefinition def, LocalScopeVariable v) { + TExplicitPreSsaDef(PreBasicBlocks::PreBasicBlock bb, int i, AssignableDefinition def, PreSsa::SimpleAssignable a) { Guards::Internal::CachedWithCFG::forceCachingInSameStage() and - PreSsa::assignableDefAt(bb, i, def, v) + PreSsa::assignableDefAtLive(bb, i, def, a) } or - TPhiPreSsaDef(PreBasicBlocks::PreBasicBlock bb, LocalScopeVariable v) { - exists(PreBasicBlocks::PreBasicBlock def | - def.inDominanceFrontier(bb) | - PreSsa::defAt(def, _, _, v) - ) + TImplicitEntryPreSsaDef(Callable c, PreBasicBlocks::PreBasicBlock bb, Assignable a) { + PreSsa::implicitEntryDef(c, bb, a) and + PreSsa::liveAtEntry(bb, a) + } + or + TPhiPreSsaDef(PreBasicBlocks::PreBasicBlock bb, PreSsa::SimpleAssignable a) { + phiNodeMaybeLive(bb, a) and + PreSsa::liveAtEntry(bb, a) } cached diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/DataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/DataFlow.qll index 6843d67087b..dfd7885899c 100755 --- a/csharp/ql/src/semmle/code/csharp/dataflow/DataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/DataFlow.qll @@ -130,6 +130,9 @@ module DataFlow { module PathGraph { /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } + + /** Holds if `node` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode node) { any() } } /** diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index 09f1fa9f073..ae2f0654f45 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -283,6 +283,11 @@ module Ssa { ref(bb, i, v, k) } + private int maxRefRank(BasicBlock bb, SourceVariable v) { + result = refRank(bb, _, v, _) and + not result + 1 = refRank(bb, _, v, _) + } + /** * Gets the (1-based) rank of the first reference to `v` inside basic block `bb` * that is either a read or a certain write. @@ -319,59 +324,28 @@ module Ssa { } /** - * Same as `variableWrite()`, but extended to include implicit call definitions - * for fields and properties. + * Holds if source variable `v` is likely to be live at any node inside basic + * block `bb`. This is an overestimate. */ - private predicate variableWriteExt(BasicBlock bb, int i, SourceVariable v, boolean certain) { - variableWrite(bb, i, v, certain) + predicate possiblyLiveAtAllNodes(BasicBlock bb, SourceVariable v) { + liveAtExit(bb, v, _) or - variableWriteExt(bb, i, v.(QualifiedFieldOrPropSourceVariable).getQualifier(), certain) - or - exists(Call c | - bb.getNode(i) = c.getAControlFlowNode() | - updatesNamedFieldOrProp(c, v, _) and - certain = false - ) - } - - /** - * Same as `ref()`, but extended to include implicit call definitions - * for fields and properties. - */ - private predicate refExt(BasicBlock bb, int i, SourceVariable v, RefKind k) { - exists(ReadKind rk | - variableRead(bb, i, v, _, rk) | - k = Read(rk) - ) - or - exists(boolean certain | - variableWriteExt(bb, i, v, certain) | - k = Write(certain) - ) - } - - /** - * Same as `refRank()`, but extended to include implicit call definitions - * for fields and properties. - */ - private int refRankExt(BasicBlock bb, int i, SourceVariable v, RefKind k) { - i = rank[result](int j | refExt(bb, j, v, _)) and - refExt(bb, i, v, k) + ref(bb, _, v, Read(_)) } /** * Holds if variable `v` is live in basic block `bb` at index `i`. - * The rank of `i` is `rnk` as defined by `refRankExt()`. + * The rank of `i` is `rnk` as defined by `refRank()`. */ - private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk, ReadKind rk) { - rnk = refRankExt(bb, i, v, _) and + predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk, ReadKind rk) { + rnk = refRank(bb, i, v, _) and ( - rnk = max(refRankExt(bb, _, v, _)) and + rnk = maxRefRank(bb, v) and liveAtExit(bb, v, rk) or ref(bb, i, v, Read(rk)) or - exists(int j | liveAtRank(bb, j, v, rnk + 1, rk) | not refExt(bb, j, v, Write(true))) + exists(int j | liveAtRank(bb, j, v, rnk + 1, rk) | not ref(bb, j, v, Write(true))) ) } @@ -382,7 +356,7 @@ module Ssa { */ predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v, ReadKind rk) { exists (int rnk | - rnk = refRankExt(bb, i, v, Write(_)) | + rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk, rk) ) } @@ -672,6 +646,11 @@ module Ssa { ssaRef(bb, i, v, k) } + private int maxSsaRefRank(BasicBlock bb, SourceVariable v) { + result = ssaRefRank(bb, _, v, _) and + not result + 1 = ssaRefRank(bb, _, v, _) + } + /** * Holds if the non-trivial SSA definition `def` reaches rank index `rankix` * in its own basic block `bb`. @@ -765,7 +744,7 @@ module Ssa { rankix + 1 = ssaRefRank(bb2, i2, v, _) ) or - ssaRefRank(bb1, i1, v, _) = max(ssaRefRank(bb1, _, v, _)) and + ssaRefRank(bb1, i1, v, _) = maxSsaRefRank(bb1, v) and varBlockStep(v, bb1, bb2) and ssaRefRank(bb2, i2, v, _) = 1 } @@ -823,7 +802,7 @@ module Ssa { rnk + 1 = ssaRefRank(bb, _, v, SsaDef()) or // No next reference to `v` inside `bb` - rnk = max(ssaRefRank(bb, _, v, _)) and + rnk = maxSsaRefRank(bb, v) and ( // Read reaches end of enclosing callable not varBlockReaches(v, bb, _) @@ -837,6 +816,21 @@ module Ssa { ) } + pragma[noinline] + private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, TrackedDefinition def, TrackedVar v) { + exists(BasicBlock idom | + ssaDefReachesEndOfBlock(idom, def, v) | + /* The construction of SSA form ensures that each read of a variable is + * dominated by its definition. An SSA definition therefore reaches a + * control flow node if it is the _closest_ SSA definition that dominates + * the node. If two definitions dominate a node then one must dominate the + * other, so therefore the definition of _closest_ is given by the dominator + * tree. Thus, reaching definitions can be calculated in terms of dominance. + */ + idom = bb.getImmediateDominator() + ) + } + /** * Holds if the non-trivial SSA definition of `v` at `def` reaches the end of a * basic block `bb`, at which point it is still live, without crossing another @@ -844,26 +838,15 @@ module Ssa { */ cached predicate ssaDefReachesEndOfBlock(BasicBlock bb, TrackedDefinition def, TrackedVar v) { - liveAtExit(bb, v, _) and - ( - exists(int last | - last = max(ssaRefRank(bb, _, v, _)) | - ssaDefReachesRank(bb, def, last, v) - ) - or - exists(BasicBlock idom | - /* The construction of SSA form ensures that each read of a variable is - * dominated by its definition. An SSA definition therefore reaches a - * control flow node if it is the _closest_ SSA definition that dominates - * the node. If two definitions dominate a node then one must dominate the - * other, so therefore the definition of _closest_ is given by the dominator - * tree. Thus, reaching definitions can be calculated in terms of dominance. - */ - idom = bb.getImmediateDominator() and - ssaDefReachesEndOfBlock(idom, def, v) and - not exists(ssaRefRank(bb, _, v, SsaDef())) - ) + exists(int last | + last = maxSsaRefRank(bb, v) | + ssaDefReachesRank(bb, def, last, v) and + liveAtExit(bb, v, _) ) + or + ssaDefReachesEndOfBlockRec(bb, def, v) and + liveAtExit(bb, v, _) and + not ssaRef(bb, _, v, SsaDef()) } /** @@ -1222,74 +1205,31 @@ module Ssa { setsOtherFieldOrProp(c, fp) and c = setter } + pragma[noinline] + predicate callAt(BasicBlock bb, int i, Call call) { + bb.getNode(i) = call.getAControlFlowNode() and + getARuntimeTarget(call).hasBody() + } + /** * Holds if `call` occurs in basic block `bb` at index `i`, `fp` has - * an update somewhere, and `fp` is accessed somewhere inside the callable - * to which `bb` belongs. + * an update somewhere, and `fp` is likely to be live in `bb` at index + * `i`. */ private predicate updateCandidate(BasicBlock bb, int i, TrackedFieldOrProp fp, Call call) { - bb.getNode(i) = call.getAControlFlowNode() and - call.getEnclosingCallable() = fp.getEnclosingCallable() and - relevantDefinition(_, fp.getAssignable(), _) - } - - /** - * Same as `ref()`, but extended to include implicit call definitions - * for fields and properties. - */ - private predicate refExt(BasicBlock bb, int i, TrackedFieldOrProp fp) { - ref(bb, i, fp, _) - or - updateCandidate(bb, i, fp, _) and + possiblyLiveAtAllNodes(bb, fp) and + callAt(bb, i, call) and + relevantDefinition(_, fp.getAssignable(), _) and not ref(bb, i, fp, _) } - /** - * Same as `refRank()`, but extended to include implicit call definitions - * for fields and properties, and restricted to basic blocks that have - * a potential implicit call definition. - */ - private int refRankExt(BasicBlock bb, int i, TrackedFieldOrProp fp) { - updateCandidate(bb, _, fp, _) and - i = rank[result](int j | refExt(bb, j, fp)) and - refExt(bb, i, fp) - } - - /** - * Holds if field or property `fp` is live in basic block `bb` at index `i`. - * The rank of `i` is `rnk` as defined by `refRankExt()`. - */ - private predicate liveAtRank(BasicBlock bb, int i, TrackedFieldOrProp fp, int rnk) { - rnk = refRankExt(bb, i, fp) and - ( - rnk = max(refRankExt(bb, _, fp)) and - liveAtExit(bb, fp, _) - or - ref(bb, i, fp, Read(_)) - or - exists(int j | liveAtRank(bb, j, fp, rnk + 1) | not ref(bb, j, fp, Write(true))) - ) - } - - /** - * Holds if field or property `fp` is live after the potential update at call `c`. - */ - private predicate liveAfterUpdateCandidate(Call c, TrackedFieldOrProp fp) { - exists(BasicBlock bb, int i, int rnk | - updateCandidate(bb, i, fp, c) | - not ref(bb, i, fp, _) and - rnk = refRankExt(bb, i, fp) and - liveAtRank(bb, i, fp, rnk) - ) - } - /** * Holds if `c` is a relevant part of the call graph for * `updatesNamedFieldOrPropPart1` based on following edges in forward direction. */ private predicate pruneFromLeft(Callable c) { exists(Call call, TrackedFieldOrProp f | - liveAfterUpdateCandidate(call, f) and + updateCandidate(_, _, f, call) and c = getARuntimeTarget(call) and generalSetter(_, f.getAssignable(), _) ) @@ -1330,7 +1270,7 @@ module Ssa { pragma [noinline] private predicate updatesNamedFieldOrPropPart1Prefix0(Call call, TrackedFieldOrProp tfp, Callable c1, FieldOrProp fp) { - liveAfterUpdateCandidate(call, tfp) and + updateCandidate(_, _, tfp, call) and fp = tfp.getAssignable() and generalSetter(_, fp, _) and c1 = getARuntimeTarget(call) @@ -1353,7 +1293,7 @@ module Ssa { * may not alias with `this`. The actual update occurs in `setter`. */ pragma [noopt] - predicate updatesNamedFieldOrPropPart1(Call call, TrackedFieldOrProp tfp, Callable setter) { + private predicate updatesNamedFieldOrPropPart1(Call call, TrackedFieldOrProp tfp, Callable setter) { exists(Callable c1, Callable c2, FieldOrProp fp | updatesNamedFieldOrPropPart1Prefix(call, tfp, c1, setter, fp) and generalSetter(c2, fp, setter) | @@ -1365,10 +1305,79 @@ module Ssa { * Holds if `call` may change the value of `tfp` on `this`. The actual update occurs * in `setter`. */ - predicate updatesNamedFieldOrPropPart2(Call call, TrackedFieldOrProp tfp, Callable setter) { - liveAfterUpdateCandidate(call, tfp) and + private predicate updatesNamedFieldOrPropPart2(Call call, TrackedFieldOrProp tfp, Callable setter) { + updateCandidate(_, _, tfp, call) and setsOwnFieldOrPropTransitive(getARuntimeTarget(call), tfp.getAssignable(), setter) } + + private predicate updatesNamedFieldOrPropPossiblyLive(BasicBlock bb, int i, TrackedFieldOrProp fp, Call call, Callable setter) { + updateCandidate(bb, i, fp, call) and + ( + updatesNamedFieldOrPropPart1(call, fp, setter) + or + updatesNamedFieldOrPropPart2(call, fp, setter) + ) + } + + private int firstRefAfterCall(BasicBlock bb, int i, TrackedFieldOrProp fp) { + updatesNamedFieldOrPropPossiblyLive(bb, i, fp, _, _) and + result = min(int k | k > i and ref(bb, k, fp, _)) + } + + /** + * Holds if `call` may change the value of field or property `fp`. The actual + * update occurs in `setter`. + */ + cached + predicate updatesNamedFieldOrProp(Call c, TrackedFieldOrProp fp, Callable setter) { + forceCachingInSameStage() and + exists(BasicBlock bb, int i | + updatesNamedFieldOrPropPossiblyLive(bb, i, fp, c, setter) | + not exists(firstRefAfterCall(bb, i, fp)) and + liveAtExit(bb, fp, _) + or + exists(int j | + j = firstRefAfterCall(bb, i, fp) | + liveAtRank(bb, j, fp, _, _) and + not ref(bb, j, fp, Write(true)) + ) + ) + } + + /** + * Same as `variableWrite()`, but extended to include implicit call definitions + * for fields and properties. + */ + private predicate variableWriteExt(BasicBlock bb, int i, SourceVariable v) { + ref(bb, i, v, Write(_)) + or + variableWriteExt(bb, i, v.(QualifiedFieldOrPropSourceVariable).getQualifier()) + or + exists(Call c | callAt(bb, i, c) | updatesNamedFieldOrProp(c, v, _)) + } + + private int firstRefAfterQualifiedDef(BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable q) { + variableWriteExt(bb, i, q) and + result = min(int k | k > i and ref(bb, k, q, _)) + } + + /** + * Holds if qualified field or property `q` is live after the (certain or + * uncertain) write at index `i` inside basic block `bb`. + */ + predicate liveAfterWriteQualified(BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable q) { + variableWriteExt(bb, i, q) and + ( + not exists(firstRefAfterQualifiedDef(bb, i, q)) and + liveAtExit(bb, q, _) + or + exists(int j | + j = firstRefAfterQualifiedDef(bb, i, q) | + liveAtRank(bb, j, q, _, _) and + not ref(bb, j, q, Write(true)) + ) + ) + } } private import FieldOrPropsImpl @@ -1440,72 +1449,22 @@ module Ssa { /** * Holds if `call` occurs in basic block `bb` at index `i`, captured variable - * `v` has an update somewhere, and `v` is accessed somewhere inside the callable - * to which `bb` belongs. + * `v` has an update somewhere, and `v` is likely to be live in `bb` at index + * `i`. */ private predicate updateCandidate(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v, Call call) { - bb.getNode(i) = call.getAControlFlowNode() and - call.getEnclosingCallable() = v.getEnclosingCallable() and + possiblyLiveAtAllNodes(bb, v) and + callAt(bb, i, call) and relevantDefinition(_, v.getAssignable(), _) } - /** - * Same as `ref()`, but extended to include implicit call definitions - * for captured variables. - */ - private predicate refExt(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v) { - ref(bb, i, v, _) - or - updateCandidate(bb, i, v, _) and - not ref(bb, i, v, _) - } - - /** - * Same as `refRank()`, but extended to include implicit call definitions - * for captured variables, and restricted to basic blocks that have a - * potential implicit call definition. - */ - private int refRankExt(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v) { - updateCandidate(bb, _, v, _) and - i = rank[result](int j | refExt(bb, j, v)) and - refExt(bb, i, v) - } - - /** - * Holds if captured source variable `v` is live in basic block `bb` at index `i`. - * The rank of `i` is `rnk` as defined by `refRankExt()`. - */ - private predicate liveAtRank(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v, int rnk) { - rnk = refRankExt(bb, i, v) and - ( - rnk = max(refRankExt(bb, _, v)) and - liveAtExit(bb, v, _) - or - ref(bb, i, v, Read(_)) - or - exists(int j | liveAtRank(bb, j, v, rnk + 1) | not ref(bb, j, v, Write(true))) - ) - } - - /** - * Holds if captured source variable `v` is live after the potential update at call `c`. - */ - private predicate liveAfterUpdateCandidate(Call c, CapturedWrittenLocalScopeSourceVariable v) { - exists(BasicBlock bb, int i, int rnk | - updateCandidate(bb, i, v, c) | - not ref(bb, i, v, _) and - rnk = refRankExt(bb, i, v) and - liveAtRank(bb, i, v, rnk) - ) - } - /** * Holds if `c` is a relevant part of the call graph for * `updatesCapturedVariable` based on following edges in forward direction. */ private predicate pruneFromLeft(Callable c) { exists(Call call, CapturedWrittenLocalScopeSourceVariable v | - liveAfterUpdateCandidate(call, v) and + updateCandidate(_, _, v, call) and c = getARuntimeTarget(call) and relevantDefinition(_, v.getAssignable(), _) ) @@ -1551,7 +1510,7 @@ module Ssa { pragma [noinline] private predicate updatesCapturedVariablePrefix(Call call, CapturedWrittenLocalScopeSourceVariable v, PrunedCallable c, CapturedWrittenLocalScopeVariable captured) { - liveAfterUpdateCandidate(call, v) and + updateCandidate(_, _, v, call) and captured = v.getAssignable() and relevantDefinitionProj(_, captured) and c = getARuntimeTarget(call) @@ -1573,14 +1532,42 @@ module Ssa { ) } - // A non-cached helper predicate that is cached in a cached module further down, - // to make sure the predicate is evaluated in the same stage as other cached predicates - predicate updatesCapturedVariableNonCached(Call call, CapturedWrittenLocalScopeSourceVariable v, AssignableDefinition def) { + /** + * Holds if `call` may change the value of captured variable `v`. The actual + * update occurs in `def`. + */ + private predicate updatesCapturedVariablePossiblyLive(BasicBlock bb, int i, Call call, LocalScopeSourceVariable v, AssignableDefinition def) { + updateCandidate(bb, i, v, call) and exists(Callable writer | relevantDefinition(writer, v.getAssignable(), def) | updatesCapturedVariableWriter(call, v, writer) ) } + + private int firstRefAfter(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v) { + updatesCapturedVariablePossiblyLive(bb, i, _, v, _) and + result = min(int k | k > i and ref(bb, k, v, _)) + } + + /** + * Holds if `call` may change the value of captured variable `v`. The actual + * update occurs in `def`. + */ + cached + predicate updatesCapturedVariable(Call call, LocalScopeSourceVariable v, AssignableDefinition def) { + forceCachingInSameStage() and + exists(BasicBlock bb, int i | + updatesCapturedVariablePossiblyLive(bb, i, call, v, def) | + not exists(firstRefAfter(bb, i, v)) and + liveAtExit(bb, v, _) + or + exists(int j | + j = firstRefAfter(bb, i, v) | + liveAtRank(bb, j, v, _, _) and + not ref(bb, j, v, Write(true)) + ) + ) + } } private import CapturedVariableImpl @@ -1830,6 +1817,8 @@ module Ssa { private import CapturedVariableLivenessImpl private cached module SsaImpl { + cached predicate forceCachingInSameStage() { any() } + /** * A data type representing SSA definitions. * @@ -1905,7 +1894,7 @@ module Ssa { exists(BasicBlock bb, int i | qdef.getSourceVariable() = v.getQualifier() and qdef.definesAt(bb, i) and - liveAfterWrite(bb, i, v, _) and + liveAfterWriteQualified(bb, i, v) and // Eliminate corner case where a call definition can overlap with a // qualifier definition: if method `M` updates field `F`, then a call // to `M` is both an update of `x.M` and `x.M.M`, so the former call @@ -1921,14 +1910,18 @@ module Ssa { } or TPhiNode(TrackedVar v, ControlFlow::BasicBlocks::JoinBlock bb) { + phiNodeMaybeLive(bb, v) and liveAtEntry(bb, v, _) - and - exists(BasicBlock bb1, Definition def | - bb1.inDominanceFrontier(bb) and - definesAt(def, bb1, _, v) - ) } + pragma[noinline] + private predicate phiNodeMaybeLive(ControlFlow::BasicBlocks::JoinBlock bb, TrackedVar v) { + exists(Definition def, BasicBlock bb1 | + definesAt(def, bb1, _, v) | + bb1.inDominanceFrontier(bb) + ) + } + /** * Holds if the SSA definition `def` defines source variable `v` at index `i` * in basic block `bb`. Phi nodes and entry nodes (captured variables and @@ -1952,23 +1945,6 @@ module Ssa { def = TPhiNode(v, bb) and i = -1 } - /** - * Holds if `call` may change the value of field or property `fp`. The actual - * update occurs in `setter`. - */ - cached predicate updatesNamedFieldOrProp(Call call, TrackedFieldOrProp fp, Callable setter) { - updatesNamedFieldOrPropPart1(call, fp, setter) or - updatesNamedFieldOrPropPart2(call, fp, setter) - } - - /** - * Holds if `call` may change the value of captured variable `v`. The actual - * update occurs in `def`. - */ - cached predicate updatesCapturedVariable(Call call, LocalScopeSourceVariable v, AssignableDefinition def) { - updatesCapturedVariableNonCached(call, v, def) - } - cached predicate isCapturedVariableDefinitionFlowIn(ExplicitDefinition def, ImplicitEntryDefinition edef, Call c) { exists(BasicBlock bb, int i, LocalScopeSourceVariable v | definesAt(def, bb, i, v) | diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll index 9f005557d92..367358931b1 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll @@ -114,10 +114,9 @@ module BaseSsa { */ cached AssignableRead getARead(AssignableDefinition def, SimpleLocalScopeVariable v) { exists(BasicBlock bb, int i, int rnk | - result.getTarget() = v and result.getAControlFlowNode() = bb.getNode(i) and rnk = ssaRefRank(bb, i, v, SsaRead()) - | + | defReachesRank(bb, def, v, rnk) or reachesEndOf(def, v, bb.getAPredecessor()) and diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 3f98400488d..74e4497068d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -164,6 +164,13 @@ | Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | Conditions.cs:109:17:109:23 | ... = ... | 9 | | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | Conditions.cs:108:18:108:18 | [b (line 102): true] access to parameter b | 3 | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:102:12:102:13 | exit M8 | 3 | +| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:17:116:21 | Int32 i = ... | 10 | +| Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | exit M9 | 1 | +| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:38 | ... < ... | 4 | +| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | 2 | +| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:119:18:119:21 | access to local variable last | 13 | +| Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | 6 | +| Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:122:17:122:24 | ... = ... | 6 | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | exit M1 | 7 | | ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | exit M2 | 7 | | ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | exit M3 | 6 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlockDominance.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlockDominance.expected index 04c69bbb6c6..da73ec8b0bc 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlockDominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlockDominance.expected @@ -360,6 +360,27 @@ | post | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | | post | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | | post | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:16:110:16 | access to local variable x | +| post | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:113:10:113:11 | enter M9 | +| post | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | enter M9 | +| post | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | exit M9 | +| post | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:24:116:24 | access to local variable i | +| post | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:41:116:41 | access to local variable i | +| post | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:117:9:123:9 | {...} | +| post | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| post | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| post | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:113:10:113:11 | enter M9 | +| post | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:24 | access to local variable i | +| post | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | +| post | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | +| post | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| post | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| post | Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | +| post | Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | +| post | Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| post | Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| post | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:117:9:123:9 | {...} | +| post | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| post | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | | post | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | enter M1 | | post | ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | enter M2 | | post | ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | enter M3 | @@ -1705,6 +1726,27 @@ | pre | Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | | pre | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | | pre | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:16:110:16 | access to local variable x | +| pre | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:113:10:113:11 | enter M9 | +| pre | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:113:10:113:11 | exit M9 | +| pre | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:24:116:24 | access to local variable i | +| pre | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:41:116:41 | access to local variable i | +| pre | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:117:9:123:9 | {...} | +| pre | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| pre | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| pre | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | exit M9 | +| pre | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:113:10:113:11 | exit M9 | +| pre | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:24 | access to local variable i | +| pre | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | +| pre | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | +| pre | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| pre | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| pre | Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | +| pre | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:116:41:116:41 | access to local variable i | +| pre | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:117:9:123:9 | {...} | +| pre | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| pre | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| pre | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| pre | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | | pre | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | enter M1 | | pre | ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | enter M2 | | pre | ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | enter M3 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/BooleanNode.expected b/csharp/ql/test/library-tests/controlflow/graph/BooleanNode.expected index 84ce6e8c301..f8c6e8b0872 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BooleanNode.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BooleanNode.expected @@ -98,3 +98,11 @@ | inc (line 3): true | Conditions.cs:7:9:8:16 | [inc (line 3): true] if (...) ... | | inc (line 3): true | Conditions.cs:7:13:7:16 | [inc (line 3): true] !... | | inc (line 3): true | Conditions.cs:7:14:7:16 | [inc (line 3): true] access to parameter inc | +| last (line 118): false | Conditions.cs:120:17:120:17 | [last (line 118): false] access to local variable s | +| last (line 118): false | Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | +| last (line 118): false | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| last (line 118): false | Conditions.cs:120:21:120:22 | [last (line 118): false] "" | +| last (line 118): false | Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | +| last (line 118): false | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | +| last (line 118): true | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| last (line 118): true | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ConditionBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/ConditionBlock.expected index 6c29210d9a9..ad2b1fc3c4d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ConditionBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ConditionBlock.expected @@ -155,6 +155,13 @@ | Conditions.cs:105:13:105:13 | access to parameter b | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | true | | Conditions.cs:107:13:107:24 | [b (line 102): false] ... > ... | Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | true | | Conditions.cs:107:13:107:24 | [b (line 102): true] ... > ... | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | true | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | false | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:41:116:41 | access to local variable i | true | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:117:9:123:9 | {...} | true | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | true | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | true | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | false | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | true | | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | false | | ExitMethods.cs:55:13:55:13 | access to parameter b | ExitMethods.cs:56:19:56:33 | object creation of type Exception | true | | ExitMethods.cs:61:13:61:13 | access to parameter b | ExitMethods.cs:62:19:62:33 | object creation of type Exception | true | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ConditionalFlow.expected b/csharp/ql/test/library-tests/controlflow/graph/ConditionalFlow.expected index 3e5ddc8b28a..101b935f13a 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ConditionalFlow.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ConditionalFlow.expected @@ -187,10 +187,16 @@ | 108 | 18 | Conditions.cs:108:18:108:18 | [b (line 102): false] access to parameter b | false | 109 | 17 | Conditions.cs:109:17:109:24 | ...; | | 108 | 18 | Conditions.cs:108:18:108:18 | [b (line 102): true] access to parameter b | true | 110 | 16 | Conditions.cs:110:16:110:16 | access to local variable x | | 110 | 20 | cflow.cs:110:20:110:23 | true | true | 111 | 13 | cflow.cs:111:13:113:13 | {...} | +| 116 | 24 | Conditions.cs:116:24:116:38 | ... < ... | false | 113 | 10 | Conditions.cs:113:10:113:11 | exit M9 | +| 116 | 24 | Conditions.cs:116:24:116:38 | ... < ... | true | 117 | 9 | Conditions.cs:117:9:123:9 | {...} | | 117 | 25 | Switch.cs:117:25:117:32 | ... == ... | false | 118 | 13 | Switch.cs:118:13:118:33 | case ...: | | 117 | 25 | Switch.cs:117:25:117:32 | ... == ... | true | 117 | 43 | Switch.cs:117:43:117:43 | 1 | | 118 | 25 | Switch.cs:118:25:118:31 | ... == ... | false | 120 | 17 | Switch.cs:120:17:120:17 | 1 | | 118 | 25 | Switch.cs:118:25:118:31 | ... == ... | true | 118 | 42 | Switch.cs:118:42:118:42 | 2 | +| 119 | 18 | Conditions.cs:119:18:119:21 | access to local variable last | false | 120 | 17 | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| 119 | 18 | Conditions.cs:119:18:119:21 | access to local variable last | true | 121 | 13 | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| 121 | 17 | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | false | 116 | 41 | Conditions.cs:116:41:116:41 | access to local variable i | +| 121 | 17 | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | true | 122 | 17 | Conditions.cs:122:17:122:25 | ...; | | 127 | 32 | cflow.cs:127:32:127:44 | ... == ... | false | 127 | 53 | cflow.cs:127:53:127:57 | this access | | 127 | 32 | cflow.cs:127:32:127:44 | ... == ... | true | 127 | 48 | cflow.cs:127:48:127:49 | "" | | 162 | 48 | cflow.cs:162:48:162:51 | [exception: Exception] true | true | 163 | 9 | cflow.cs:163:9:165:9 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Conditions.cs b/csharp/ql/test/library-tests/controlflow/graph/Conditions.cs index 80a205f732d..d4c5d45a579 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Conditions.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/Conditions.cs @@ -109,4 +109,17 @@ class Conditions x += ""; return x; } + + void M9(string[] args) + { + string s = null; + for(var i = 0; i < args.Length; i++) + { + var last = i == args.Length - 1; + if (!last) + s = ""; + if (last) + s = null; + } + } } diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index e9b2d47aff5..d141f51bd5c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -621,6 +621,46 @@ | post | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:107:13:107:24 | [b (line 102): true] ... > ... | | post | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:108:18:108:18 | [b (line 102): true] access to parameter b | | post | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:109:17:109:23 | ... = ... | +| post | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:24:116:38 | ... < ... | +| post | Conditions.cs:114:5:124:5 | {...} | Conditions.cs:113:10:113:11 | enter M9 | +| post | Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:114:5:124:5 | {...} | +| post | Conditions.cs:115:16:115:16 | access to local variable s | Conditions.cs:115:9:115:24 | ... ...; | +| post | Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:115:20:115:23 | null | +| post | Conditions.cs:115:20:115:23 | null | Conditions.cs:115:16:115:16 | access to local variable s | +| post | Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:115:16:115:23 | String s = ... | +| post | Conditions.cs:116:17:116:17 | access to local variable i | Conditions.cs:116:9:123:9 | for (...;...;...) ... | +| post | Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:21:116:21 | 0 | +| post | Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:17:116:17 | access to local variable i | +| post | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:17:116:21 | Int32 i = ... | +| post | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | +| post | Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:28:116:38 | access to property Length | +| post | Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:24:116:24 | access to local variable i | +| post | Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:28:116:31 | access to parameter args | +| post | Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | +| post | Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:122:17:122:24 | ... = ... | +| post | Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:41:116:41 | access to local variable i | +| post | Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:117:9:123:9 | {...} | +| post | Conditions.cs:118:17:118:20 | access to local variable last | Conditions.cs:118:13:118:44 | ... ...; | +| post | Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:118:24:118:43 | ... == ... | +| post | Conditions.cs:118:24:118:24 | access to local variable i | Conditions.cs:118:17:118:20 | access to local variable last | +| post | Conditions.cs:118:24:118:43 | ... == ... | Conditions.cs:118:29:118:43 | ... - ... | +| post | Conditions.cs:118:29:118:32 | access to parameter args | Conditions.cs:118:24:118:24 | access to local variable i | +| post | Conditions.cs:118:29:118:39 | access to property Length | Conditions.cs:118:29:118:32 | access to parameter args | +| post | Conditions.cs:118:29:118:43 | ... - ... | Conditions.cs:118:43:118:43 | 1 | +| post | Conditions.cs:118:43:118:43 | 1 | Conditions.cs:118:29:118:39 | access to property Length | +| post | Conditions.cs:119:13:120:23 | if (...) ... | Conditions.cs:118:17:118:43 | Boolean last = ... | +| post | Conditions.cs:119:17:119:21 | !... | Conditions.cs:119:13:120:23 | if (...) ... | +| post | Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:119:17:119:21 | !... | +| post | Conditions.cs:120:17:120:17 | [last (line 118): false] access to local variable s | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| post | Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | Conditions.cs:120:21:120:22 | [last (line 118): false] "" | +| post | Conditions.cs:120:21:120:22 | [last (line 118): false] "" | Conditions.cs:120:17:120:17 | [last (line 118): false] access to local variable s | +| post | Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | +| post | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | +| post | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| post | Conditions.cs:122:17:122:17 | access to local variable s | Conditions.cs:122:17:122:25 | ...; | +| post | Conditions.cs:122:17:122:24 | ... = ... | Conditions.cs:122:21:122:24 | null | +| post | Conditions.cs:122:17:122:25 | ...; | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | +| post | Conditions.cs:122:21:122:24 | null | Conditions.cs:122:17:122:17 | access to local variable s | | post | ExitMethods.cs:7:10:7:11 | exit M1 | ExitMethods.cs:10:9:10:15 | return ...; | | post | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:7:10:7:11 | enter M1 | | post | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:20:9:23 | true | @@ -2748,6 +2788,46 @@ | pre | Conditions.cs:109:22:109:23 | "" | Conditions.cs:109:17:109:23 | ... + ... | | pre | Conditions.cs:110:9:110:17 | return ...; | Conditions.cs:102:12:102:13 | exit M8 | | pre | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:9:110:17 | return ...; | +| pre | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:114:5:124:5 | {...} | +| pre | Conditions.cs:114:5:124:5 | {...} | Conditions.cs:115:9:115:24 | ... ...; | +| pre | Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:16:115:16 | access to local variable s | +| pre | Conditions.cs:115:16:115:16 | access to local variable s | Conditions.cs:115:20:115:23 | null | +| pre | Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:116:9:123:9 | for (...;...;...) ... | +| pre | Conditions.cs:115:20:115:23 | null | Conditions.cs:115:16:115:23 | String s = ... | +| pre | Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:17:116:17 | access to local variable i | +| pre | Conditions.cs:116:17:116:17 | access to local variable i | Conditions.cs:116:21:116:21 | 0 | +| pre | Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:24:116:24 | access to local variable i | +| pre | Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:17:116:21 | Int32 i = ... | +| pre | Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:28:116:31 | access to parameter args | +| pre | Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | +| pre | Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:117:9:123:9 | {...} | +| pre | Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:38 | access to property Length | +| pre | Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:24:116:38 | ... < ... | +| pre | Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | +| pre | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:118:13:118:44 | ... ...; | +| pre | Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:17:118:20 | access to local variable last | +| pre | Conditions.cs:118:17:118:20 | access to local variable last | Conditions.cs:118:24:118:24 | access to local variable i | +| pre | Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:119:13:120:23 | if (...) ... | +| pre | Conditions.cs:118:24:118:24 | access to local variable i | Conditions.cs:118:29:118:32 | access to parameter args | +| pre | Conditions.cs:118:24:118:43 | ... == ... | Conditions.cs:118:17:118:43 | Boolean last = ... | +| pre | Conditions.cs:118:29:118:32 | access to parameter args | Conditions.cs:118:29:118:39 | access to property Length | +| pre | Conditions.cs:118:29:118:39 | access to property Length | Conditions.cs:118:43:118:43 | 1 | +| pre | Conditions.cs:118:29:118:43 | ... - ... | Conditions.cs:118:24:118:43 | ... == ... | +| pre | Conditions.cs:118:43:118:43 | 1 | Conditions.cs:118:29:118:43 | ... - ... | +| pre | Conditions.cs:119:13:120:23 | if (...) ... | Conditions.cs:119:17:119:21 | !... | +| pre | Conditions.cs:119:17:119:21 | !... | Conditions.cs:119:18:119:21 | access to local variable last | +| pre | Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| pre | Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| pre | Conditions.cs:120:17:120:17 | [last (line 118): false] access to local variable s | Conditions.cs:120:21:120:22 | [last (line 118): false] "" | +| pre | Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | +| pre | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:120:17:120:17 | [last (line 118): false] access to local variable s | +| pre | Conditions.cs:120:21:120:22 | [last (line 118): false] "" | Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | +| pre | Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | +| pre | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | +| pre | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | Conditions.cs:122:17:122:25 | ...; | +| pre | Conditions.cs:122:17:122:17 | access to local variable s | Conditions.cs:122:21:122:24 | null | +| pre | Conditions.cs:122:17:122:25 | ...; | Conditions.cs:122:17:122:17 | access to local variable s | +| pre | Conditions.cs:122:21:122:24 | null | Conditions.cs:122:17:122:24 | ... = ... | | pre | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:8:5:11:5 | {...} | | pre | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:9:9:9:25 | ...; | | pre | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:10:9:10:15 | return ...; | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ElementGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/ElementGraph.expected index 8867c45ad34..a4158402723 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ElementGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ElementGraph.expected @@ -474,6 +474,46 @@ | Conditions.cs:109:17:109:24 | ...; | Conditions.cs:109:17:109:17 | access to local variable x | semmle.label | successor | | Conditions.cs:109:22:109:23 | "" | Conditions.cs:109:17:109:23 | ... + ... | semmle.label | successor | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:9:110:17 | return ...; | semmle.label | successor | +| Conditions.cs:114:5:124:5 | {...} | Conditions.cs:115:9:115:24 | ... ...; | semmle.label | successor | +| Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:16:115:16 | access to local variable s | semmle.label | successor | +| Conditions.cs:115:16:115:16 | access to local variable s | Conditions.cs:115:20:115:23 | null | semmle.label | successor | +| Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:116:9:123:9 | for (...;...;...) ... | semmle.label | successor | +| Conditions.cs:115:20:115:23 | null | Conditions.cs:115:16:115:23 | String s = ... | semmle.label | successor | +| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:17:116:17 | access to local variable i | semmle.label | successor | +| Conditions.cs:116:17:116:17 | access to local variable i | Conditions.cs:116:21:116:21 | 0 | semmle.label | successor | +| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:24:116:24 | access to local variable i | semmle.label | successor | +| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:17:116:21 | Int32 i = ... | semmle.label | successor | +| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:28:116:31 | access to parameter args | semmle.label | successor | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:117:9:123:9 | {...} | semmle.label | true | +| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:38 | access to property Length | semmle.label | successor | +| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:24:116:38 | ... < ... | semmle.label | successor | +| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | semmle.label | successor | +| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:24:116:24 | access to local variable i | semmle.label | successor | +| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:118:13:118:44 | ... ...; | semmle.label | successor | +| Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:17:118:20 | access to local variable last | semmle.label | successor | +| Conditions.cs:118:17:118:20 | access to local variable last | Conditions.cs:118:24:118:24 | access to local variable i | semmle.label | successor | +| Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:119:13:120:23 | if (...) ... | semmle.label | successor | +| Conditions.cs:118:24:118:24 | access to local variable i | Conditions.cs:118:29:118:32 | access to parameter args | semmle.label | successor | +| Conditions.cs:118:24:118:43 | ... == ... | Conditions.cs:118:17:118:43 | Boolean last = ... | semmle.label | successor | +| Conditions.cs:118:29:118:32 | access to parameter args | Conditions.cs:118:29:118:39 | access to property Length | semmle.label | successor | +| Conditions.cs:118:29:118:39 | access to property Length | Conditions.cs:118:43:118:43 | 1 | semmle.label | successor | +| Conditions.cs:118:29:118:43 | ... - ... | Conditions.cs:118:24:118:43 | ... == ... | semmle.label | successor | +| Conditions.cs:118:43:118:43 | 1 | Conditions.cs:118:29:118:43 | ... - ... | semmle.label | successor | +| Conditions.cs:119:13:120:23 | if (...) ... | Conditions.cs:119:17:119:21 | !... | semmle.label | successor | +| Conditions.cs:119:17:119:21 | !... | Conditions.cs:119:18:119:21 | access to local variable last | semmle.label | successor | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:120:17:120:23 | ...; | semmle.label | false | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:121:13:122:25 | if (...) ... | semmle.label | true | +| Conditions.cs:120:17:120:17 | access to local variable s | Conditions.cs:120:21:120:22 | "" | semmle.label | successor | +| Conditions.cs:120:17:120:22 | ... = ... | Conditions.cs:121:13:122:25 | if (...) ... | semmle.label | successor | +| Conditions.cs:120:17:120:23 | ...; | Conditions.cs:120:17:120:17 | access to local variable s | semmle.label | successor | +| Conditions.cs:120:21:120:22 | "" | Conditions.cs:120:17:120:22 | ... = ... | semmle.label | successor | +| Conditions.cs:121:13:122:25 | if (...) ... | Conditions.cs:121:17:121:20 | access to local variable last | semmle.label | successor | +| Conditions.cs:121:17:121:20 | access to local variable last | Conditions.cs:116:41:116:41 | access to local variable i | semmle.label | false | +| Conditions.cs:121:17:121:20 | access to local variable last | Conditions.cs:122:17:122:25 | ...; | semmle.label | true | +| Conditions.cs:122:17:122:17 | access to local variable s | Conditions.cs:122:21:122:24 | null | semmle.label | successor | +| Conditions.cs:122:17:122:24 | ... = ... | Conditions.cs:116:41:116:41 | access to local variable i | semmle.label | successor | +| Conditions.cs:122:17:122:25 | ...; | Conditions.cs:122:17:122:17 | access to local variable s | semmle.label | successor | +| Conditions.cs:122:21:122:24 | null | Conditions.cs:122:17:122:24 | ... = ... | semmle.label | successor | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:9:9:9:25 | ...; | semmle.label | successor | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:10:9:10:15 | return ...; | semmle.label | successor | | ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:20:9:23 | true | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index bcd5f55c292..2df036510c4 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -478,6 +478,44 @@ | Conditions.cs:109:22:109:23 | "" | Conditions.cs:109:22:109:23 | "" | | Conditions.cs:110:9:110:17 | return ...; | Conditions.cs:110:16:110:16 | access to local variable x | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:16:110:16 | access to local variable x | +| Conditions.cs:114:5:124:5 | {...} | Conditions.cs:114:5:124:5 | {...} | +| Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:9:115:24 | ... ...; | +| Conditions.cs:115:16:115:16 | access to local variable s | Conditions.cs:115:16:115:16 | access to local variable s | +| Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:115:16:115:16 | access to local variable s | +| Conditions.cs:115:20:115:23 | null | Conditions.cs:115:20:115:23 | null | +| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:9:123:9 | for (...;...;...) ... | +| Conditions.cs:116:17:116:17 | access to local variable i | Conditions.cs:116:17:116:17 | access to local variable i | +| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:17:116:17 | access to local variable i | +| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:21:116:21 | 0 | +| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:24 | access to local variable i | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:24:116:24 | access to local variable i | +| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:31 | access to parameter args | +| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:28:116:31 | access to parameter args | +| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | +| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:41:116:41 | access to local variable i | +| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:117:9:123:9 | {...} | +| Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:13:118:44 | ... ...; | +| Conditions.cs:118:17:118:20 | access to local variable last | Conditions.cs:118:17:118:20 | access to local variable last | +| Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:118:17:118:20 | access to local variable last | +| Conditions.cs:118:24:118:24 | access to local variable i | Conditions.cs:118:24:118:24 | access to local variable i | +| Conditions.cs:118:24:118:43 | ... == ... | Conditions.cs:118:24:118:24 | access to local variable i | +| Conditions.cs:118:29:118:32 | access to parameter args | Conditions.cs:118:29:118:32 | access to parameter args | +| Conditions.cs:118:29:118:39 | access to property Length | Conditions.cs:118:29:118:32 | access to parameter args | +| Conditions.cs:118:29:118:43 | ... - ... | Conditions.cs:118:29:118:32 | access to parameter args | +| Conditions.cs:118:43:118:43 | 1 | Conditions.cs:118:43:118:43 | 1 | +| Conditions.cs:119:13:120:23 | if (...) ... | Conditions.cs:119:13:120:23 | if (...) ... | +| Conditions.cs:119:17:119:21 | !... | Conditions.cs:119:17:119:21 | !... | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:119:18:119:21 | access to local variable last | +| Conditions.cs:120:17:120:17 | access to local variable s | Conditions.cs:120:17:120:17 | access to local variable s | +| Conditions.cs:120:17:120:22 | ... = ... | Conditions.cs:120:17:120:17 | access to local variable s | +| Conditions.cs:120:17:120:23 | ...; | Conditions.cs:120:17:120:23 | ...; | +| Conditions.cs:120:21:120:22 | "" | Conditions.cs:120:21:120:22 | "" | +| Conditions.cs:121:13:122:25 | if (...) ... | Conditions.cs:121:13:122:25 | if (...) ... | +| Conditions.cs:121:17:121:20 | access to local variable last | Conditions.cs:121:17:121:20 | access to local variable last | +| Conditions.cs:122:17:122:17 | access to local variable s | Conditions.cs:122:17:122:17 | access to local variable s | +| Conditions.cs:122:17:122:24 | ... = ... | Conditions.cs:122:17:122:17 | access to local variable s | +| Conditions.cs:122:17:122:25 | ...; | Conditions.cs:122:17:122:25 | ...; | +| Conditions.cs:122:21:122:24 | null | Conditions.cs:122:21:122:24 | null | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:8:5:11:5 | {...} | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:20:9:23 | true | | ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:9:9:25 | ...; | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryPoint.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryPoint.expected index f218267882b..000b67ba018 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryPoint.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryPoint.expected @@ -32,6 +32,7 @@ | Conditions.cs:70:9:70:10 | M6 | Conditions.cs:71:5:84:5 | {...} | | Conditions.cs:86:9:86:10 | M7 | Conditions.cs:87:5:100:5 | {...} | | Conditions.cs:102:12:102:13 | M8 | Conditions.cs:103:5:111:5 | {...} | +| Conditions.cs:113:10:113:11 | M9 | Conditions.cs:114:5:124:5 | {...} | | ExitMethods.cs:7:10:7:11 | M1 | ExitMethods.cs:8:5:11:5 | {...} | | ExitMethods.cs:13:10:13:11 | M2 | ExitMethods.cs:14:5:17:5 | {...} | | ExitMethods.cs:19:10:19:11 | M3 | ExitMethods.cs:20:5:23:5 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index e96a67d12e6..21e38d8163d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -672,6 +672,51 @@ | Conditions.cs:109:22:109:23 | "" | Conditions.cs:109:22:109:23 | "" | normal | | Conditions.cs:110:9:110:17 | return ...; | Conditions.cs:110:9:110:17 | return ...; | return | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:16:110:16 | access to local variable x | normal | +| Conditions.cs:114:5:124:5 | {...} | Conditions.cs:116:24:116:38 | ... < ... | false/false | +| Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:16:115:23 | String s = ... | normal | +| Conditions.cs:115:16:115:16 | access to local variable s | Conditions.cs:115:16:115:16 | access to local variable s | normal | +| Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:115:16:115:23 | String s = ... | normal | +| Conditions.cs:115:20:115:23 | null | Conditions.cs:115:20:115:23 | null | normal | +| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:24:116:38 | ... < ... | false/false | +| Conditions.cs:116:17:116:17 | access to local variable i | Conditions.cs:116:17:116:17 | access to local variable i | normal | +| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:17:116:21 | Int32 i = ... | normal | +| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:21:116:21 | 0 | normal | +| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:24 | access to local variable i | normal | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:24:116:38 | ... < ... | false/false | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:24:116:38 | ... < ... | true/true | +| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:31 | access to parameter args | normal | +| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:28:116:38 | access to property Length | normal | +| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | normal | +| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:41:116:43 | ...++ | normal | +| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:121:17:121:20 | access to local variable last | false/false | +| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:122:17:122:24 | ... = ... | normal | +| Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:17:118:43 | Boolean last = ... | normal | +| Conditions.cs:118:17:118:20 | access to local variable last | Conditions.cs:118:17:118:20 | access to local variable last | normal | +| Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:118:17:118:43 | Boolean last = ... | normal | +| Conditions.cs:118:24:118:24 | access to local variable i | Conditions.cs:118:24:118:24 | access to local variable i | normal | +| Conditions.cs:118:24:118:43 | ... == ... | Conditions.cs:118:24:118:43 | ... == ... | normal | +| Conditions.cs:118:29:118:32 | access to parameter args | Conditions.cs:118:29:118:32 | access to parameter args | normal | +| Conditions.cs:118:29:118:39 | access to property Length | Conditions.cs:118:29:118:39 | access to property Length | normal | +| Conditions.cs:118:29:118:43 | ... - ... | Conditions.cs:118:29:118:43 | ... - ... | normal | +| Conditions.cs:118:43:118:43 | 1 | Conditions.cs:118:43:118:43 | 1 | normal | +| Conditions.cs:119:13:120:23 | if (...) ... | Conditions.cs:119:18:119:21 | access to local variable last | false/true | +| Conditions.cs:119:13:120:23 | if (...) ... | Conditions.cs:120:17:120:22 | ... = ... | normal | +| Conditions.cs:119:17:119:21 | !... | Conditions.cs:119:18:119:21 | access to local variable last | false/true | +| Conditions.cs:119:17:119:21 | !... | Conditions.cs:119:18:119:21 | access to local variable last | true/false | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:119:18:119:21 | access to local variable last | false/false | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:119:18:119:21 | access to local variable last | true/true | +| Conditions.cs:120:17:120:17 | access to local variable s | Conditions.cs:120:17:120:17 | access to local variable s | normal | +| Conditions.cs:120:17:120:22 | ... = ... | Conditions.cs:120:17:120:22 | ... = ... | normal | +| Conditions.cs:120:17:120:23 | ...; | Conditions.cs:120:17:120:22 | ... = ... | normal | +| Conditions.cs:120:21:120:22 | "" | Conditions.cs:120:21:120:22 | "" | normal | +| Conditions.cs:121:13:122:25 | if (...) ... | Conditions.cs:121:17:121:20 | access to local variable last | false/false | +| Conditions.cs:121:13:122:25 | if (...) ... | Conditions.cs:122:17:122:24 | ... = ... | normal | +| Conditions.cs:121:17:121:20 | access to local variable last | Conditions.cs:121:17:121:20 | access to local variable last | false/false | +| Conditions.cs:121:17:121:20 | access to local variable last | Conditions.cs:121:17:121:20 | access to local variable last | true/true | +| Conditions.cs:122:17:122:17 | access to local variable s | Conditions.cs:122:17:122:17 | access to local variable s | normal | +| Conditions.cs:122:17:122:24 | ... = ... | Conditions.cs:122:17:122:24 | ... = ... | normal | +| Conditions.cs:122:17:122:25 | ...; | Conditions.cs:122:17:122:24 | ... = ... | normal | +| Conditions.cs:122:21:122:24 | null | Conditions.cs:122:21:122:24 | null | normal | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:10:9:10:15 | return ...; | return | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | normal | | ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 66c8d0bb675..8655ab27d46 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -728,6 +728,49 @@ | Conditions.cs:109:22:109:23 | "" | Conditions.cs:109:17:109:23 | ... + ... | semmle.label | successor | | Conditions.cs:110:9:110:17 | return ...; | Conditions.cs:102:12:102:13 | exit M8 | semmle.label | return | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:9:110:17 | return ...; | semmle.label | successor | +| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:114:5:124:5 | {...} | semmle.label | successor | +| Conditions.cs:114:5:124:5 | {...} | Conditions.cs:115:9:115:24 | ... ...; | semmle.label | successor | +| Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:16:115:16 | access to local variable s | semmle.label | successor | +| Conditions.cs:115:16:115:16 | access to local variable s | Conditions.cs:115:20:115:23 | null | semmle.label | successor | +| Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:116:9:123:9 | for (...;...;...) ... | semmle.label | successor | +| Conditions.cs:115:20:115:23 | null | Conditions.cs:115:16:115:23 | String s = ... | semmle.label | successor | +| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:17:116:17 | access to local variable i | semmle.label | successor | +| Conditions.cs:116:17:116:17 | access to local variable i | Conditions.cs:116:21:116:21 | 0 | semmle.label | successor | +| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:24:116:24 | access to local variable i | semmle.label | successor | +| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:17:116:21 | Int32 i = ... | semmle.label | successor | +| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:28:116:31 | access to parameter args | semmle.label | successor | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | semmle.label | false | +| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:117:9:123:9 | {...} | semmle.label | true | +| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:38 | access to property Length | semmle.label | successor | +| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:24:116:38 | ... < ... | semmle.label | successor | +| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | semmle.label | successor | +| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:24:116:24 | access to local variable i | semmle.label | successor | +| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:118:13:118:44 | ... ...; | semmle.label | successor | +| Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:17:118:20 | access to local variable last | semmle.label | successor | +| Conditions.cs:118:17:118:20 | access to local variable last | Conditions.cs:118:24:118:24 | access to local variable i | semmle.label | successor | +| Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:119:13:120:23 | if (...) ... | semmle.label | successor | +| Conditions.cs:118:24:118:24 | access to local variable i | Conditions.cs:118:29:118:32 | access to parameter args | semmle.label | successor | +| Conditions.cs:118:24:118:43 | ... == ... | Conditions.cs:118:17:118:43 | Boolean last = ... | semmle.label | successor | +| Conditions.cs:118:29:118:32 | access to parameter args | Conditions.cs:118:29:118:39 | access to property Length | semmle.label | successor | +| Conditions.cs:118:29:118:39 | access to property Length | Conditions.cs:118:43:118:43 | 1 | semmle.label | successor | +| Conditions.cs:118:29:118:43 | ... - ... | Conditions.cs:118:24:118:43 | ... == ... | semmle.label | successor | +| Conditions.cs:118:43:118:43 | 1 | Conditions.cs:118:29:118:43 | ... - ... | semmle.label | successor | +| Conditions.cs:119:13:120:23 | if (...) ... | Conditions.cs:119:17:119:21 | !... | semmle.label | successor | +| Conditions.cs:119:17:119:21 | !... | Conditions.cs:119:18:119:21 | access to local variable last | semmle.label | successor | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | semmle.label | false | +| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | semmle.label | true | +| Conditions.cs:120:17:120:17 | [last (line 118): false] access to local variable s | Conditions.cs:120:21:120:22 | [last (line 118): false] "" | semmle.label | successor | +| Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | semmle.label | successor | +| Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:120:17:120:17 | [last (line 118): false] access to local variable s | semmle.label | successor | +| Conditions.cs:120:21:120:22 | [last (line 118): false] "" | Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | semmle.label | successor | +| Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | semmle.label | successor | +| Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | semmle.label | successor | +| Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | Conditions.cs:116:41:116:41 | access to local variable i | semmle.label | false | +| Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | Conditions.cs:122:17:122:25 | ...; | semmle.label | true | +| Conditions.cs:122:17:122:17 | access to local variable s | Conditions.cs:122:21:122:24 | null | semmle.label | successor | +| Conditions.cs:122:17:122:24 | ... = ... | Conditions.cs:116:41:116:41 | access to local variable i | semmle.label | successor | +| Conditions.cs:122:17:122:25 | ...; | Conditions.cs:122:17:122:17 | access to local variable s | semmle.label | successor | +| Conditions.cs:122:21:122:24 | null | Conditions.cs:122:17:122:24 | ... = ... | semmle.label | successor | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:8:5:11:5 | {...} | semmle.label | successor | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:9:9:9:25 | ...; | semmle.label | successor | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:10:9:10:15 | return ...; | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected index e76529ab3ae..d02b28059d6 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected @@ -172,6 +172,136 @@ edges | GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 | GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam | | GlobalDataFlow.cs:399:9:399:11 | value | GlobalDataFlow.cs:399:41:399:46 | access to local variable sink20 | | GlobalDataFlow.cs:410:22:410:35 | "taint source" | GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty | +nodes +| Capture.cs:7:20:7:26 | tainted | +| Capture.cs:9:9:13:9 | SSA capture def(tainted) | +| Capture.cs:12:19:12:24 | access to local variable sink27 | +| Capture.cs:14:9:14:20 | tainted [implicit argument] | +| Capture.cs:18:13:22:13 | SSA capture def(tainted) | +| Capture.cs:21:23:21:28 | access to local variable sink28 | +| Capture.cs:25:9:25:20 | tainted [implicit argument] | +| Capture.cs:27:43:32:9 | SSA capture def(tainted) | +| Capture.cs:30:19:30:24 | access to local variable sink29 | +| Capture.cs:33:9:33:40 | tainted [implicit argument] | +| Capture.cs:57:13:57:35 | SSA def(sink30) | +| Capture.cs:57:22:57:35 | "taint source" | +| Capture.cs:59:9:59:21 | SSA call def(sink30) | +| Capture.cs:60:15:60:20 | access to local variable sink30 | +| Capture.cs:67:17:67:39 | SSA def(sink31) | +| Capture.cs:67:26:67:39 | "taint source" | +| Capture.cs:71:9:71:21 | SSA call def(sink31) | +| Capture.cs:72:15:72:20 | access to local variable sink31 | +| Capture.cs:77:13:77:35 | SSA def(sink32) | +| Capture.cs:77:22:77:35 | "taint source" | +| Capture.cs:80:9:80:41 | SSA call def(sink32) | +| Capture.cs:81:15:81:20 | access to local variable sink32 | +| Capture.cs:101:25:101:31 | tainted | +| Capture.cs:108:9:108:25 | SSA call def(sink33) | +| Capture.cs:108:9:108:25 | tainted [implicit argument] | +| Capture.cs:109:15:109:20 | access to local variable sink33 | +| Capture.cs:120:9:120:25 | SSA call def(sink34) | +| Capture.cs:120:9:120:25 | tainted [implicit argument] | +| Capture.cs:121:15:121:20 | access to local variable sink34 | +| Capture.cs:129:9:129:45 | SSA call def(sink35) | +| Capture.cs:129:9:129:45 | tainted [implicit argument] | +| Capture.cs:130:15:130:20 | access to local variable sink35 | +| Capture.cs:136:22:136:38 | call to local function CaptureThrough4 | +| Capture.cs:136:22:136:38 | tainted [implicit argument] | +| Capture.cs:137:15:137:20 | access to local variable sink36 | +| Capture.cs:144:9:144:32 | SSA call def(sink37) | +| Capture.cs:144:25:144:31 | access to parameter tainted | +| Capture.cs:145:15:145:20 | access to local variable sink37 | +| Capture.cs:170:22:170:32 | call to local function Id | +| Capture.cs:170:25:170:31 | access to parameter tainted | +| Capture.cs:171:15:171:20 | access to local variable sink38 | +| GlobalDataFlow.cs:17:27:17:40 | "taint source" | +| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | +| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | +| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | +| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | +| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | +| GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | +| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | +| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | +| GlobalDataFlow.cs:53:15:53:15 | x | +| GlobalDataFlow.cs:53:24:53:24 | access to parameter x | +| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | +| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | +| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | +| GlobalDataFlow.cs:56:37:56:37 | x | +| GlobalDataFlow.cs:56:46:56:46 | access to parameter x | +| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | +| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | +| GlobalDataFlow.cs:70:21:70:46 | call to method Return | +| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | +| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | +| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | +| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | +| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | +| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | +| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | +| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | +| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | +| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | +| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | +| GlobalDataFlow.cs:131:21:131:34 | delegate call | +| GlobalDataFlow.cs:131:29:131:33 | access to local variable sink3 | +| GlobalDataFlow.cs:132:15:132:19 | access to local variable sink4 | +| GlobalDataFlow.cs:139:21:139:44 | call to method ApplyFunc | +| GlobalDataFlow.cs:139:39:139:43 | access to local variable sink4 | +| GlobalDataFlow.cs:140:15:140:19 | access to local variable sink5 | +| GlobalDataFlow.cs:149:21:149:25 | call to method Out | +| GlobalDataFlow.cs:150:15:150:19 | access to local variable sink6 | +| GlobalDataFlow.cs:152:20:152:24 | SSA def(sink7) | +| GlobalDataFlow.cs:153:15:153:19 | access to local variable sink7 | +| GlobalDataFlow.cs:155:20:155:24 | SSA def(sink8) | +| GlobalDataFlow.cs:156:15:156:19 | access to local variable sink8 | +| GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam | +| GlobalDataFlow.cs:160:15:160:20 | access to local variable sink23 | +| GlobalDataFlow.cs:175:35:175:48 | "taint source" | +| GlobalDataFlow.cs:176:21:176:26 | delegate call | +| GlobalDataFlow.cs:177:15:177:19 | access to local variable sink9 | +| GlobalDataFlow.cs:185:39:185:41 | [implicit call] delegate creation of type Func | +| GlobalDataFlow.cs:186:15:186:20 | access to local variable sink10 | +| GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty | +| GlobalDataFlow.cs:194:15:194:20 | access to local variable sink19 | +| GlobalDataFlow.cs:230:26:230:35 | sinkParam0 | +| GlobalDataFlow.cs:230:26:230:35 | sinkParam0 | +| GlobalDataFlow.cs:232:16:232:25 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:232:16:232:25 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:233:15:233:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:233:15:233:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam1 | +| GlobalDataFlow.cs:238:15:238:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:241:26:241:35 | sinkParam3 | +| GlobalDataFlow.cs:243:15:243:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:246:26:246:35 | sinkParam4 | +| GlobalDataFlow.cs:248:15:248:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:251:26:251:35 | sinkParam5 | +| GlobalDataFlow.cs:253:15:253:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:256:26:256:35 | sinkParam6 | +| GlobalDataFlow.cs:258:15:258:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:261:26:261:35 | sinkParam7 | +| GlobalDataFlow.cs:263:15:263:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:313:16:313:29 | "taint source" | +| GlobalDataFlow.cs:318:13:318:26 | "taint source" | +| GlobalDataFlow.cs:323:13:323:26 | "taint source" | +| GlobalDataFlow.cs:354:41:354:41 | x | +| GlobalDataFlow.cs:354:41:354:41 | x | +| GlobalDataFlow.cs:356:11:356:11 | access to parameter x | +| GlobalDataFlow.cs:356:11:356:11 | access to parameter x | +| GlobalDataFlow.cs:368:52:368:52 | x | +| GlobalDataFlow.cs:368:52:368:52 | x | +| GlobalDataFlow.cs:368:52:368:52 | x | +| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | +| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | +| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | +| GlobalDataFlow.cs:373:39:373:45 | tainted | +| GlobalDataFlow.cs:376:15:376:20 | access to local variable sink11 | +| GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 | +| GlobalDataFlow.cs:399:9:399:11 | value | +| GlobalDataFlow.cs:399:41:399:46 | access to local variable sink20 | +| GlobalDataFlow.cs:410:22:410:35 | "taint source" | #select | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | access to field SinkField0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | access to local variable sink0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index 08dc92d3b26..7c1c2b73e46 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -215,6 +215,181 @@ edges | GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 | GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam | | GlobalDataFlow.cs:399:9:399:11 | value | GlobalDataFlow.cs:399:41:399:46 | access to local variable sink20 | | GlobalDataFlow.cs:410:22:410:35 | "taint source" | GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty | +nodes +| Capture.cs:7:20:7:26 | tainted | +| Capture.cs:9:9:13:9 | SSA capture def(tainted) | +| Capture.cs:12:19:12:24 | access to local variable sink27 | +| Capture.cs:14:9:14:20 | tainted [implicit argument] | +| Capture.cs:18:13:22:13 | SSA capture def(tainted) | +| Capture.cs:21:23:21:28 | access to local variable sink28 | +| Capture.cs:25:9:25:20 | tainted [implicit argument] | +| Capture.cs:27:43:32:9 | SSA capture def(tainted) | +| Capture.cs:30:19:30:24 | access to local variable sink29 | +| Capture.cs:33:9:33:40 | tainted [implicit argument] | +| Capture.cs:57:13:57:35 | SSA def(sink30) | +| Capture.cs:57:22:57:35 | "taint source" | +| Capture.cs:59:9:59:21 | SSA call def(sink30) | +| Capture.cs:60:15:60:20 | access to local variable sink30 | +| Capture.cs:67:17:67:39 | SSA def(sink31) | +| Capture.cs:67:26:67:39 | "taint source" | +| Capture.cs:71:9:71:21 | SSA call def(sink31) | +| Capture.cs:72:15:72:20 | access to local variable sink31 | +| Capture.cs:77:13:77:35 | SSA def(sink32) | +| Capture.cs:77:22:77:35 | "taint source" | +| Capture.cs:80:9:80:41 | SSA call def(sink32) | +| Capture.cs:81:15:81:20 | access to local variable sink32 | +| Capture.cs:101:25:101:31 | tainted | +| Capture.cs:108:9:108:25 | SSA call def(sink33) | +| Capture.cs:108:9:108:25 | tainted [implicit argument] | +| Capture.cs:109:15:109:20 | access to local variable sink33 | +| Capture.cs:120:9:120:25 | SSA call def(sink34) | +| Capture.cs:120:9:120:25 | tainted [implicit argument] | +| Capture.cs:121:15:121:20 | access to local variable sink34 | +| Capture.cs:129:9:129:45 | SSA call def(sink35) | +| Capture.cs:129:9:129:45 | tainted [implicit argument] | +| Capture.cs:130:15:130:20 | access to local variable sink35 | +| Capture.cs:136:22:136:38 | call to local function CaptureThrough4 | +| Capture.cs:136:22:136:38 | tainted [implicit argument] | +| Capture.cs:137:15:137:20 | access to local variable sink36 | +| Capture.cs:144:9:144:32 | SSA call def(sink37) | +| Capture.cs:144:25:144:31 | access to parameter tainted | +| Capture.cs:145:15:145:20 | access to local variable sink37 | +| Capture.cs:170:22:170:32 | call to local function Id | +| Capture.cs:170:25:170:31 | access to parameter tainted | +| Capture.cs:171:15:171:20 | access to local variable sink38 | +| GlobalDataFlow.cs:17:27:17:40 | "taint source" | +| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | +| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | +| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | +| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | +| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | +| GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | +| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | +| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | +| GlobalDataFlow.cs:53:15:53:15 | x | +| GlobalDataFlow.cs:53:24:53:24 | access to parameter x | +| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | +| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | +| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | +| GlobalDataFlow.cs:56:37:56:37 | x | +| GlobalDataFlow.cs:56:46:56:46 | access to parameter x | +| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | +| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | +| GlobalDataFlow.cs:70:21:70:46 | call to method Return | +| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | +| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | +| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | +| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | +| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | +| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | +| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | +| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | +| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | +| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | +| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | +| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | +| GlobalDataFlow.cs:80:23:80:65 | (...) ... | +| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | +| GlobalDataFlow.cs:82:23:82:74 | (...) ... | +| GlobalDataFlow.cs:82:84:82:94 | [implicit call] delegate creation of type Func | +| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | +| GlobalDataFlow.cs:84:23:84:74 | (...) ... | +| GlobalDataFlow.cs:84:125:84:135 | [implicit call] (...) => ... | +| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | +| GlobalDataFlow.cs:86:70:86:121 | (...) ... | +| GlobalDataFlow.cs:86:125:86:135 | [implicit call] (...) => ... | +| GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | +| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | +| GlobalDataFlow.cs:88:43:88:61 | [implicit call] (...) => ... | +| GlobalDataFlow.cs:88:64:88:69 | [implicit call] (...) => ... | +| GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | +| GlobalDataFlow.cs:90:75:90:88 | call to method First | +| GlobalDataFlow.cs:90:91:90:109 | [implicit call] (...) => ... | +| GlobalDataFlow.cs:90:112:90:117 | [implicit call] (...) => ... | +| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | +| GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | +| GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | +| GlobalDataFlow.cs:131:21:131:34 | delegate call | +| GlobalDataFlow.cs:131:29:131:33 | access to local variable sink3 | +| GlobalDataFlow.cs:132:15:132:19 | access to local variable sink4 | +| GlobalDataFlow.cs:139:21:139:44 | call to method ApplyFunc | +| GlobalDataFlow.cs:139:39:139:43 | access to local variable sink4 | +| GlobalDataFlow.cs:140:15:140:19 | access to local variable sink5 | +| GlobalDataFlow.cs:149:21:149:25 | call to method Out | +| GlobalDataFlow.cs:150:15:150:19 | access to local variable sink6 | +| GlobalDataFlow.cs:152:20:152:24 | SSA def(sink7) | +| GlobalDataFlow.cs:153:15:153:19 | access to local variable sink7 | +| GlobalDataFlow.cs:155:20:155:24 | SSA def(sink8) | +| GlobalDataFlow.cs:156:15:156:19 | access to local variable sink8 | +| GlobalDataFlow.cs:157:22:157:31 | call to method OutYield | +| GlobalDataFlow.cs:158:15:158:20 | access to local variable sink12 | +| GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam | +| GlobalDataFlow.cs:160:15:160:20 | access to local variable sink23 | +| GlobalDataFlow.cs:175:35:175:48 | "taint source" | +| GlobalDataFlow.cs:176:21:176:26 | delegate call | +| GlobalDataFlow.cs:177:15:177:19 | access to local variable sink9 | +| GlobalDataFlow.cs:185:39:185:41 | [implicit call] delegate creation of type Func | +| GlobalDataFlow.cs:186:15:186:20 | access to local variable sink10 | +| GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty | +| GlobalDataFlow.cs:194:15:194:20 | access to local variable sink19 | +| GlobalDataFlow.cs:201:39:201:45 | tainted | +| GlobalDataFlow.cs:204:35:204:45 | sinkParam10 | +| GlobalDataFlow.cs:204:58:204:68 | access to parameter sinkParam10 | +| GlobalDataFlow.cs:205:71:205:71 | x | +| GlobalDataFlow.cs:205:89:205:89 | access to parameter x | +| GlobalDataFlow.cs:206:22:206:28 | access to parameter tainted | +| GlobalDataFlow.cs:206:37:206:38 | [implicit call] access to local variable f1 | +| GlobalDataFlow.cs:207:15:207:20 | access to local variable sink24 | +| GlobalDataFlow.cs:208:22:208:28 | access to parameter tainted | +| GlobalDataFlow.cs:208:37:208:38 | [implicit call] access to local variable f2 | +| GlobalDataFlow.cs:209:15:209:20 | access to local variable sink25 | +| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted | +| GlobalDataFlow.cs:210:37:210:48 | [implicit call] delegate creation of type Func | +| GlobalDataFlow.cs:211:15:211:20 | access to local variable sink26 | +| GlobalDataFlow.cs:230:26:230:35 | sinkParam0 | +| GlobalDataFlow.cs:230:26:230:35 | sinkParam0 | +| GlobalDataFlow.cs:232:16:232:25 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:232:16:232:25 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:233:15:233:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:233:15:233:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam1 | +| GlobalDataFlow.cs:238:15:238:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:241:26:241:35 | sinkParam3 | +| GlobalDataFlow.cs:243:15:243:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:246:26:246:35 | sinkParam4 | +| GlobalDataFlow.cs:248:15:248:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:251:26:251:35 | sinkParam5 | +| GlobalDataFlow.cs:253:15:253:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:256:26:256:35 | sinkParam6 | +| GlobalDataFlow.cs:258:15:258:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:261:26:261:35 | sinkParam7 | +| GlobalDataFlow.cs:263:15:263:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:287:31:287:40 | sinkParam8 | +| GlobalDataFlow.cs:289:15:289:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:293:32:293:41 | sinkParam9 | +| GlobalDataFlow.cs:295:15:295:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:299:32:299:42 | sinkParam11 | +| GlobalDataFlow.cs:301:15:301:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:313:16:313:29 | "taint source" | +| GlobalDataFlow.cs:318:13:318:26 | "taint source" | +| GlobalDataFlow.cs:323:13:323:26 | "taint source" | +| GlobalDataFlow.cs:329:22:329:35 | "taint source" | +| GlobalDataFlow.cs:354:41:354:41 | x | +| GlobalDataFlow.cs:354:41:354:41 | x | +| GlobalDataFlow.cs:356:11:356:11 | access to parameter x | +| GlobalDataFlow.cs:356:11:356:11 | access to parameter x | +| GlobalDataFlow.cs:368:52:368:52 | x | +| GlobalDataFlow.cs:368:52:368:52 | x | +| GlobalDataFlow.cs:368:52:368:52 | x | +| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | +| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | +| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | +| GlobalDataFlow.cs:373:39:373:45 | tainted | +| GlobalDataFlow.cs:376:15:376:20 | access to local variable sink11 | +| GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 | +| GlobalDataFlow.cs:399:9:399:11 | value | +| GlobalDataFlow.cs:399:41:399:46 | access to local variable sink20 | +| GlobalDataFlow.cs:410:22:410:35 | "taint source" | #select | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | access to field SinkField0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | access to local variable sink0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.expected b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.expected index e69de29bb2d..4fa64b47674 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.expected @@ -0,0 +1,3 @@ +defReadInconsistency +readReadInconsistency +phiInconsistency diff --git a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql index caa9144fe15..dea9b67b059 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql +++ b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql @@ -1,11 +1,13 @@ import csharp import ControlFlow::Internal -predicate defReadInconsistency(AssignableRead ar, Expr e, boolean b) { +query +predicate defReadInconsistency(AssignableRead ar, Expr e, PreSsa::SimpleAssignable a, boolean b) { exists(AssignableDefinition def | e = def.getExpr() | b = true and exists(PreSsa::Definition ssaDef | + ssaDef.getAssignable() = a | PreSsa::firstReadSameVar(ssaDef, ar) and ssaDef.getDefinition() = def and not exists(Ssa::ExplicitDefinition edef | @@ -18,7 +20,7 @@ predicate defReadInconsistency(AssignableRead ar, Expr e, boolean b) { exists(Ssa::ExplicitDefinition edef | edef.getADefinition() = def and edef.getAFirstRead() = ar and - def.getTarget() instanceof PreSsa::SimpleLocalScopeVariable and + def.getTarget() = a and not exists(PreSsa::Definition ssaDef | PreSsa::firstReadSameVar(ssaDef, ar) and ssaDef.getDefinition() = def @@ -27,22 +29,48 @@ predicate defReadInconsistency(AssignableRead ar, Expr e, boolean b) { ) } -predicate readReadInconsistency(LocalScopeVariableRead read1, LocalScopeVariableRead read2, boolean b) { +query +predicate readReadInconsistency(LocalScopeVariableRead read1, LocalScopeVariableRead read2, PreSsa::SimpleAssignable a, boolean b) { b = true and + a = read1.getTarget() and PreSsa::adjacentReadPairSameVar(read1, read2) and not Ssa::Internal::adjacentReadPairSameVar(read1, read2) or b = false and + a = read1.getTarget() and Ssa::Internal::adjacentReadPairSameVar(read1, read2) and - read1.getTarget() instanceof PreSsa::SimpleLocalScopeVariable and + read1.getTarget() instanceof PreSsa::SimpleAssignable and not PreSsa::adjacentReadPairSameVar(read1, read2) } -from Element e1, Element e2, boolean b, string s -where - defReadInconsistency(e1, e2, b) and - s = "def-read inconsistency (" + b + ")" - or - readReadInconsistency(e1, e2, b) and - s = "read-read inconsistency (" + b + ")" -select e1, e2, s +query +predicate phiInconsistency(ControlFlowElement cfe, Expr e, PreSsa::SimpleAssignable a, boolean b) { + exists(AssignableDefinition adef | + e = adef.getExpr() | + b = true and + exists(PreSsa::Definition def | + a = def.getAssignable() | + adef = def.getAPhiInput+().getDefinition() and + cfe = def.getBasicBlock().getFirstElement() and + not exists(Ssa::PhiNode phi, ControlFlow::BasicBlock bb, Ssa::ExplicitDefinition edef | + edef = phi.getAnUltimateDefinition() | + edef.getADefinition() = adef and + phi.definesAt(bb, _) and + cfe = bb.getFirstNode().getElement() + ) + ) + or + b = false and + exists(Ssa::PhiNode phi, ControlFlow::BasicBlock bb, Ssa::ExplicitDefinition edef | + a = phi.getSourceVariable().getAssignable() | + edef = phi.getAnUltimateDefinition() and + edef.getADefinition() = adef and + phi.definesAt(bb, _) and + cfe = bb.getFirstNode().getElement() and + not exists(PreSsa::Definition def | + adef = def.getAPhiInput+().getDefinition() and + cfe = def.getBasicBlock().getFirstElement() + ) + ) + ) +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/TaintedPath.expected b/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/TaintedPath.expected index fce17c42bd0..9207136a1c6 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/TaintedPath.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/TaintedPath.expected @@ -1,7 +1,25 @@ -| TaintedPath.cs:14:50:14:53 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | -| TaintedPath.cs:19:51:19:54 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | -| TaintedPath.cs:27:30:27:33 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | -| TaintedPath.cs:33:30:33:33 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | -| TaintedPath.cs:38:25:38:31 | access to local variable badPath | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | -| TaintedPath.cs:40:49:40:55 | access to local variable badPath | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | -| TaintedPath.cs:53:26:53:29 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | +edges +| TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:14:50:14:53 | access to local variable path | +| TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:19:51:19:54 | access to local variable path | +| TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:27:30:27:33 | access to local variable path | +| TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:33:30:33:33 | access to local variable path | +| TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:38:25:38:31 | access to local variable badPath | +| TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:40:49:40:55 | access to local variable badPath | +| TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:53:26:53:29 | access to local variable path | +nodes +| TaintedPath.cs:12:23:12:45 | access to property QueryString | +| TaintedPath.cs:14:50:14:53 | access to local variable path | +| TaintedPath.cs:19:51:19:54 | access to local variable path | +| TaintedPath.cs:27:30:27:33 | access to local variable path | +| TaintedPath.cs:33:30:33:33 | access to local variable path | +| TaintedPath.cs:38:25:38:31 | access to local variable badPath | +| TaintedPath.cs:40:49:40:55 | access to local variable badPath | +| TaintedPath.cs:53:26:53:29 | access to local variable path | +#select +| TaintedPath.cs:14:50:14:53 | access to local variable path | TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:14:50:14:53 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | +| TaintedPath.cs:19:51:19:54 | access to local variable path | TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:19:51:19:54 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | +| TaintedPath.cs:27:30:27:33 | access to local variable path | TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:27:30:27:33 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | +| TaintedPath.cs:33:30:33:33 | access to local variable path | TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:33:30:33:33 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | +| TaintedPath.cs:38:25:38:31 | access to local variable badPath | TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:38:25:38:31 | access to local variable badPath | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | +| TaintedPath.cs:40:49:40:55 | access to local variable badPath | TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:40:49:40:55 | access to local variable badPath | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | +| TaintedPath.cs:53:26:53:29 | access to local variable path | TaintedPath.cs:12:23:12:45 | access to property QueryString | TaintedPath.cs:53:26:53:29 | access to local variable path | $@ flows to here and is used in a path. | TaintedPath.cs:12:23:12:45 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-022/ZipSlip/ZipSlip.expected b/csharp/ql/test/query-tests/Security Features/CWE-022/ZipSlip/ZipSlip.expected index f9da54b1b80..a95aff9ad55 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-022/ZipSlip/ZipSlip.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-022/ZipSlip/ZipSlip.expected @@ -1,9 +1,37 @@ -| ZipSlip.cs:24:41:24:52 | access to local variable destFileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:19:31:19:44 | access to property FullName | item path | -| ZipSlip.cs:32:41:32:52 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:16:52:16:65 | access to property FullName | item path | -| ZipSlip.cs:36:45:36:56 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:16:52:16:65 | access to property FullName | item path | -| ZipSlip.cs:40:41:40:52 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:16:52:16:65 | access to property FullName | item path | -| ZipSlip.cs:69:74:69:85 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:62:72:62:85 | access to property FullName | item path | -| ZipSlip.cs:76:71:76:82 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:62:72:62:85 | access to property FullName | item path | -| ZipSlip.cs:83:57:83:68 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:62:72:62:85 | access to property FullName | item path | -| ZipSlip.cs:91:58:91:69 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:62:72:62:85 | access to property FullName | item path | -| ZipSlipBad.cs:10:29:10:40 | access to local variable destFileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.cs:9:59:9:72 | access to property FullName | item path | +edges +| ZipSlip.cs:16:52:16:65 | access to property FullName | ZipSlip.cs:32:41:32:52 | access to local variable destFilePath | +| ZipSlip.cs:16:52:16:65 | access to property FullName | ZipSlip.cs:36:45:36:56 | access to local variable destFilePath | +| ZipSlip.cs:16:52:16:65 | access to property FullName | ZipSlip.cs:39:53:39:89 | call to method Combine | +| ZipSlip.cs:16:52:16:65 | access to property FullName | ZipSlip.cs:40:41:40:52 | access to local variable destFilePath | +| ZipSlip.cs:19:31:19:44 | access to property FullName | ZipSlip.cs:24:41:24:52 | access to local variable destFileName | +| ZipSlip.cs:39:53:39:89 | call to method Combine | ZipSlip.cs:40:41:40:52 | access to local variable destFilePath | +| ZipSlip.cs:62:72:62:85 | access to property FullName | ZipSlip.cs:69:74:69:85 | access to local variable destFilePath | +| ZipSlip.cs:62:72:62:85 | access to property FullName | ZipSlip.cs:76:71:76:82 | access to local variable destFilePath | +| ZipSlip.cs:62:72:62:85 | access to property FullName | ZipSlip.cs:83:57:83:68 | access to local variable destFilePath | +| ZipSlip.cs:62:72:62:85 | access to property FullName | ZipSlip.cs:91:58:91:69 | access to local variable destFilePath | +| ZipSlipBad.cs:9:59:9:72 | access to property FullName | ZipSlipBad.cs:10:29:10:40 | access to local variable destFileName | +nodes +| ZipSlip.cs:16:52:16:65 | access to property FullName | +| ZipSlip.cs:19:31:19:44 | access to property FullName | +| ZipSlip.cs:24:41:24:52 | access to local variable destFileName | +| ZipSlip.cs:32:41:32:52 | access to local variable destFilePath | +| ZipSlip.cs:36:45:36:56 | access to local variable destFilePath | +| ZipSlip.cs:39:53:39:89 | call to method Combine | +| ZipSlip.cs:40:41:40:52 | access to local variable destFilePath | +| ZipSlip.cs:62:72:62:85 | access to property FullName | +| ZipSlip.cs:69:74:69:85 | access to local variable destFilePath | +| ZipSlip.cs:76:71:76:82 | access to local variable destFilePath | +| ZipSlip.cs:83:57:83:68 | access to local variable destFilePath | +| ZipSlip.cs:91:58:91:69 | access to local variable destFilePath | +| ZipSlipBad.cs:9:59:9:72 | access to property FullName | +| ZipSlipBad.cs:10:29:10:40 | access to local variable destFileName | +#select +| ZipSlip.cs:24:41:24:52 | access to local variable destFileName | ZipSlip.cs:19:31:19:44 | access to property FullName | ZipSlip.cs:24:41:24:52 | access to local variable destFileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:19:31:19:44 | access to property FullName | item path | +| ZipSlip.cs:32:41:32:52 | access to local variable destFilePath | ZipSlip.cs:16:52:16:65 | access to property FullName | ZipSlip.cs:32:41:32:52 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:16:52:16:65 | access to property FullName | item path | +| ZipSlip.cs:36:45:36:56 | access to local variable destFilePath | ZipSlip.cs:16:52:16:65 | access to property FullName | ZipSlip.cs:36:45:36:56 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:16:52:16:65 | access to property FullName | item path | +| ZipSlip.cs:40:41:40:52 | access to local variable destFilePath | ZipSlip.cs:16:52:16:65 | access to property FullName | ZipSlip.cs:40:41:40:52 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:16:52:16:65 | access to property FullName | item path | +| ZipSlip.cs:69:74:69:85 | access to local variable destFilePath | ZipSlip.cs:62:72:62:85 | access to property FullName | ZipSlip.cs:69:74:69:85 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:62:72:62:85 | access to property FullName | item path | +| ZipSlip.cs:76:71:76:82 | access to local variable destFilePath | ZipSlip.cs:62:72:62:85 | access to property FullName | ZipSlip.cs:76:71:76:82 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:62:72:62:85 | access to property FullName | item path | +| ZipSlip.cs:83:57:83:68 | access to local variable destFilePath | ZipSlip.cs:62:72:62:85 | access to property FullName | ZipSlip.cs:83:57:83:68 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:62:72:62:85 | access to property FullName | item path | +| ZipSlip.cs:91:58:91:69 | access to local variable destFilePath | ZipSlip.cs:62:72:62:85 | access to property FullName | ZipSlip.cs:91:58:91:69 | access to local variable destFilePath | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlip.cs:62:72:62:85 | access to property FullName | item path | +| ZipSlipBad.cs:10:29:10:40 | access to local variable destFileName | ZipSlipBad.cs:9:59:9:72 | access to property FullName | ZipSlipBad.cs:10:29:10:40 | access to local variable destFileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.cs:9:59:9:72 | access to property FullName | item path | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-078/CommandInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-078/CommandInjection.expected index 8870df306ea..433556e9ede 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-078/CommandInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-078/CommandInjection.expected @@ -1,7 +1,25 @@ -| CommandInjection.cs:26:27:26:47 | ... + ... | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | -| CommandInjection.cs:26:50:26:66 | ... + ... | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | -| CommandInjection.cs:28:63:28:71 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | -| CommandInjection.cs:28:74:28:82 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | -| CommandInjection.cs:32:39:32:47 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | -| CommandInjection.cs:33:40:33:48 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | -| CommandInjection.cs:34:47:34:55 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | +edges +| CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:26:27:26:47 | ... + ... | +| CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:26:50:26:66 | ... + ... | +| CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:28:63:28:71 | access to local variable userInput | +| CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:28:74:28:82 | access to local variable userInput | +| CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:32:39:32:47 | access to local variable userInput | +| CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:33:40:33:48 | access to local variable userInput | +| CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:34:47:34:55 | access to local variable userInput | +nodes +| CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | +| CommandInjection.cs:26:27:26:47 | ... + ... | +| CommandInjection.cs:26:50:26:66 | ... + ... | +| CommandInjection.cs:28:63:28:71 | access to local variable userInput | +| CommandInjection.cs:28:74:28:82 | access to local variable userInput | +| CommandInjection.cs:32:39:32:47 | access to local variable userInput | +| CommandInjection.cs:33:40:33:48 | access to local variable userInput | +| CommandInjection.cs:34:47:34:55 | access to local variable userInput | +#select +| CommandInjection.cs:26:27:26:47 | ... + ... | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:26:27:26:47 | ... + ... | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | +| CommandInjection.cs:26:50:26:66 | ... + ... | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:26:50:26:66 | ... + ... | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | +| CommandInjection.cs:28:63:28:71 | access to local variable userInput | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:28:63:28:71 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | +| CommandInjection.cs:28:74:28:82 | access to local variable userInput | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:28:74:28:82 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | +| CommandInjection.cs:32:39:32:47 | access to local variable userInput | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:32:39:32:47 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | +| CommandInjection.cs:33:40:33:48 | access to local variable userInput | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:33:40:33:48 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | +| CommandInjection.cs:34:47:34:55 | access to local variable userInput | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | CommandInjection.cs:34:47:34:55 | access to local variable userInput | $@ flows to here and is used in a command. | CommandInjection.cs:25:32:25:46 | access to field categoryTextBox | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-078/StoredCommandInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-078/StoredCommandInjection.expected index aaff4b464e4..a66196c3c15 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-078/StoredCommandInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-078/StoredCommandInjection.expected @@ -1 +1,7 @@ -| StoredCommandInjection.cs:24:46:24:80 | ... + ... | $@ flows to here and is used in a command. | StoredCommandInjection.cs:24:54:24:80 | call to method GetString | Stored user-provided value | +edges +| StoredCommandInjection.cs:24:54:24:80 | call to method GetString | StoredCommandInjection.cs:24:46:24:80 | ... + ... | +nodes +| StoredCommandInjection.cs:24:46:24:80 | ... + ... | +| StoredCommandInjection.cs:24:54:24:80 | call to method GetString | +#select +| StoredCommandInjection.cs:24:46:24:80 | ... + ... | StoredCommandInjection.cs:24:54:24:80 | call to method GetString | StoredCommandInjection.cs:24:46:24:80 | ... + ... | $@ flows to here and is used in a command. | StoredCommandInjection.cs:24:54:24:80 | call to method GetString | Stored user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.expected index fef8586c163..fb150f87411 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.expected @@ -1 +1,7 @@ -| StoredXSS.cs:24:44:24:86 | ... + ... | $@ flows to here and is written to HTML or javascript. | StoredXSS.cs:24:60:24:86 | call to method GetString | Stored user-provided value | +edges +| StoredXSS.cs:24:60:24:86 | call to method GetString | StoredXSS.cs:24:44:24:86 | ... + ... | +nodes +| StoredXSS.cs:24:44:24:86 | ... + ... | +| StoredXSS.cs:24:60:24:86 | call to method GetString | +#select +| StoredXSS.cs:24:44:24:86 | ... + ... | StoredXSS.cs:24:60:24:86 | call to method GetString | StoredXSS.cs:24:44:24:86 | ... + ... | $@ flows to here and is written to HTML or JavaScript. | StoredXSS.cs:24:60:24:86 | call to method GetString | Stored user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-089/SecondOrderSqlInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-089/SecondOrderSqlInjection.expected index 272854d84a7..e51bc365ccb 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-089/SecondOrderSqlInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-089/SecondOrderSqlInjection.expected @@ -1 +1,7 @@ -| SecondOrderSqlInjection.cs:21:71:21:145 | ... + ... | $@ flows to here and is used in an SQL query. | SecondOrderSqlInjection.cs:21:119:21:145 | call to method GetString | Stored user-provided value | +edges +| SecondOrderSqlInjection.cs:21:119:21:145 | call to method GetString | SecondOrderSqlInjection.cs:21:71:21:145 | ... + ... | +nodes +| SecondOrderSqlInjection.cs:21:71:21:145 | ... + ... | +| SecondOrderSqlInjection.cs:21:119:21:145 | call to method GetString | +#select +| SecondOrderSqlInjection.cs:21:71:21:145 | ... + ... | SecondOrderSqlInjection.cs:21:119:21:145 | call to method GetString | SecondOrderSqlInjection.cs:21:71:21:145 | ... + ... | $@ flows to here and is used in an SQL query. | SecondOrderSqlInjection.cs:21:119:21:145 | call to method GetString | Stored user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-089/SqlInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-089/SqlInjection.expected index 979c31c8b4d..1bc4ebc4764 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-089/SqlInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-089/SqlInjection.expected @@ -1,9 +1,40 @@ -| SqlInjection.cs:39:50:39:55 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | this ASP.NET user input | -| SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | this ASP.NET user input | -| SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | this ASP.NET user input | -| SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | this ASP.NET user input | -| SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | this ASP.NET user input | -| SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | this ASP.NET user input | -| SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | this ASP.NET user input | -| SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | this ASP.NET user input | -| SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | this ASP.NET user input | +edges +| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | SqlInjection.cs:39:50:39:55 | access to local variable query1 | +| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | SqlInjection.cs:49:62:49:81 | access to property Text | +| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | SqlInjection.cs:61:62:61:81 | access to property Text | +| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | +| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | +| SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | SqlInjection.cs:49:62:49:81 | access to property Text | +| SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | SqlInjection.cs:61:62:61:81 | access to property Text | +| SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | +| SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | +| SqlInjection.cs:49:62:49:81 | access to property Text | SqlInjection.cs:61:62:61:81 | access to property Text | +| SqlInjection.cs:49:62:49:81 | access to property Text | SqlInjection.cs:74:56:74:61 | access to local variable query1 | +| SqlInjection.cs:49:62:49:81 | access to property Text | SqlInjection.cs:75:55:75:60 | access to local variable query1 | +| SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | SqlInjection.cs:61:62:61:81 | access to property Text | +| SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | +| SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | +| SqlInjection.cs:61:62:61:81 | access to property Text | SqlInjection.cs:74:56:74:61 | access to local variable query1 | +| SqlInjection.cs:61:62:61:81 | access to property Text | SqlInjection.cs:75:55:75:60 | access to local variable query1 | +| SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | +| SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | +nodes +| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | +| SqlInjection.cs:39:50:39:55 | access to local variable query1 | +| SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | +| SqlInjection.cs:49:62:49:81 | access to property Text | +| SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | +| SqlInjection.cs:61:62:61:81 | access to property Text | +| SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | +| SqlInjection.cs:74:56:74:61 | access to local variable query1 | +| SqlInjection.cs:75:55:75:60 | access to local variable query1 | +#select +| SqlInjection.cs:39:50:39:55 | access to local variable query1 | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | SqlInjection.cs:39:50:39:55 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | this ASP.NET user input | +| SqlInjection.cs:74:56:74:61 | access to local variable query1 | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | this ASP.NET user input | +| SqlInjection.cs:74:56:74:61 | access to local variable query1 | SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | this ASP.NET user input | +| SqlInjection.cs:74:56:74:61 | access to local variable query1 | SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | this ASP.NET user input | +| SqlInjection.cs:74:56:74:61 | access to local variable query1 | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | this ASP.NET user input | +| SqlInjection.cs:75:55:75:60 | access to local variable query1 | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox | this ASP.NET user input | +| SqlInjection.cs:75:55:75:60 | access to local variable query1 | SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:49:62:49:76 | access to field categoryTextBox | this ASP.NET user input | +| SqlInjection.cs:75:55:75:60 | access to local variable query1 | SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:61:62:61:76 | access to field categoryTextBox | this ASP.NET user input | +| SqlInjection.cs:75:55:75:60 | access to local variable query1 | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox | this ASP.NET user input | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-090/LDAPInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-090/LDAPInjection.expected index 19247fa17e1..4d78cbb644c 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-090/LDAPInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-090/LDAPInjection.expected @@ -1,6 +1,22 @@ -| LDAPInjection.cs:16:54:16:78 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | -| LDAPInjection.cs:18:21:18:45 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | -| LDAPInjection.cs:25:21:25:45 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | -| LDAPInjection.cs:26:53:26:77 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | -| LDAPInjection.cs:29:48:29:70 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | -| LDAPInjection.cs:31:20:31:42 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | +edges +| LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:16:54:16:78 | ... + ... | +| LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:18:21:18:45 | ... + ... | +| LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:25:21:25:45 | ... + ... | +| LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:26:53:26:77 | ... + ... | +| LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:29:48:29:70 | ... + ... | +| LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:31:20:31:42 | ... + ... | +nodes +| LDAPInjection.cs:13:27:13:49 | access to property QueryString | +| LDAPInjection.cs:16:54:16:78 | ... + ... | +| LDAPInjection.cs:18:21:18:45 | ... + ... | +| LDAPInjection.cs:25:21:25:45 | ... + ... | +| LDAPInjection.cs:26:53:26:77 | ... + ... | +| LDAPInjection.cs:29:48:29:70 | ... + ... | +| LDAPInjection.cs:31:20:31:42 | ... + ... | +#select +| LDAPInjection.cs:16:54:16:78 | ... + ... | LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:16:54:16:78 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | +| LDAPInjection.cs:18:21:18:45 | ... + ... | LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:18:21:18:45 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | +| LDAPInjection.cs:25:21:25:45 | ... + ... | LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:25:21:25:45 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | +| LDAPInjection.cs:26:53:26:77 | ... + ... | LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:26:53:26:77 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | +| LDAPInjection.cs:29:48:29:70 | ... + ... | LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:29:48:29:70 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | +| LDAPInjection.cs:31:20:31:42 | ... + ... | LDAPInjection.cs:13:27:13:49 | access to property QueryString | LDAPInjection.cs:31:20:31:42 | ... + ... | $@ flows to here and is used in an LDAP query. | LDAPInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-090/StoredLDAPInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-090/StoredLDAPInjection.expected index eb80d16e9d4..9b1065d2ea2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-090/StoredLDAPInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-090/StoredLDAPInjection.expected @@ -1 +1,7 @@ -| StoredLDAPInjection.cs:24:66:24:109 | ... + ... | $@ flows to here and is used in an LDAP query. | StoredLDAPInjection.cs:24:83:24:109 | call to method GetString | Stored user-provided value | +edges +| StoredLDAPInjection.cs:24:83:24:109 | call to method GetString | StoredLDAPInjection.cs:24:66:24:109 | ... + ... | +nodes +| StoredLDAPInjection.cs:24:66:24:109 | ... + ... | +| StoredLDAPInjection.cs:24:83:24:109 | call to method GetString | +#select +| StoredLDAPInjection.cs:24:66:24:109 | ... + ... | StoredLDAPInjection.cs:24:83:24:109 | call to method GetString | StoredLDAPInjection.cs:24:66:24:109 | ... + ... | $@ flows to here and is used in an LDAP query. | StoredLDAPInjection.cs:24:83:24:109 | call to method GetString | Stored user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-094/CodeInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-094/CodeInjection.expected index 07d9890dd50..696a6e4841a 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-094/CodeInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-094/CodeInjection.expected @@ -1,2 +1,10 @@ -| CodeInjection.cs:31:64:31:67 | access to local variable code | $@ flows to here and is compiled as code. | CodeInjection.cs:25:23:25:45 | access to property QueryString | User-provided value | -| CodeInjection.cs:42:36:42:39 | access to local variable code | $@ flows to here and is compiled as code. | CodeInjection.cs:25:23:25:45 | access to property QueryString | User-provided value | +edges +| CodeInjection.cs:25:23:25:45 | access to property QueryString | CodeInjection.cs:31:64:31:67 | access to local variable code | +| CodeInjection.cs:25:23:25:45 | access to property QueryString | CodeInjection.cs:42:36:42:39 | access to local variable code | +nodes +| CodeInjection.cs:25:23:25:45 | access to property QueryString | +| CodeInjection.cs:31:64:31:67 | access to local variable code | +| CodeInjection.cs:42:36:42:39 | access to local variable code | +#select +| CodeInjection.cs:31:64:31:67 | access to local variable code | CodeInjection.cs:25:23:25:45 | access to property QueryString | CodeInjection.cs:31:64:31:67 | access to local variable code | $@ flows to here and is compiled as code. | CodeInjection.cs:25:23:25:45 | access to property QueryString | User-provided value | +| CodeInjection.cs:42:36:42:39 | access to local variable code | CodeInjection.cs:25:23:25:45 | access to property QueryString | CodeInjection.cs:42:36:42:39 | access to local variable code | $@ flows to here and is compiled as code. | CodeInjection.cs:25:23:25:45 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-099/ResourceInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-099/ResourceInjection.expected index f5e7edfc70d..a362b1d9ad5 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-099/ResourceInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-099/ResourceInjection.expected @@ -1,2 +1,10 @@ -| ResourceInjection.cs:13:57:13:72 | access to local variable connectionString | $@ flows to here and is used in a resource descriptor. | ResourceInjection.cs:10:27:10:49 | access to property QueryString | User-provided value | -| ResourceInjection.cs:15:42:15:57 | access to local variable connectionString | $@ flows to here and is used in a resource descriptor. | ResourceInjection.cs:10:27:10:49 | access to property QueryString | User-provided value | +edges +| ResourceInjection.cs:10:27:10:49 | access to property QueryString | ResourceInjection.cs:13:57:13:72 | access to local variable connectionString | +| ResourceInjection.cs:10:27:10:49 | access to property QueryString | ResourceInjection.cs:15:42:15:57 | access to local variable connectionString | +nodes +| ResourceInjection.cs:10:27:10:49 | access to property QueryString | +| ResourceInjection.cs:13:57:13:72 | access to local variable connectionString | +| ResourceInjection.cs:15:42:15:57 | access to local variable connectionString | +#select +| ResourceInjection.cs:13:57:13:72 | access to local variable connectionString | ResourceInjection.cs:10:27:10:49 | access to property QueryString | ResourceInjection.cs:13:57:13:72 | access to local variable connectionString | $@ flows to here and is used in a resource descriptor. | ResourceInjection.cs:10:27:10:49 | access to property QueryString | User-provided value | +| ResourceInjection.cs:15:42:15:57 | access to local variable connectionString | ResourceInjection.cs:10:27:10:49 | access to property QueryString | ResourceInjection.cs:15:42:15:57 | access to local variable connectionString | $@ flows to here and is used in a resource descriptor. | ResourceInjection.cs:10:27:10:49 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-112/MissingXMLValidation.expected b/csharp/ql/test/query-tests/Security Features/CWE-112/MissingXMLValidation.expected index 210636ea370..2345ce84755 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-112/MissingXMLValidation.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-112/MissingXMLValidation.expected @@ -1,5 +1,31 @@ -| MissingXMLValidation.cs:18:26:18:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because there is no 'XmlReaderSettings' instance specifying schema validation. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | -| MissingXMLValidation.cs:23:26:23:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance does not specify the 'ValidationType' as 'Schema'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | -| MissingXMLValidation.cs:29:26:29:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance does not specify the 'ValidationType' as 'Schema'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | -| MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance specifies 'ProcessInlineSchema'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | -| MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance specifies 'ProcessSchemaLocation'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | +edges +| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:18:26:18:58 | object creation of type StringReader | +| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:23:26:23:58 | object creation of type StringReader | +| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:29:26:29:58 | object creation of type StringReader | +| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:37:26:37:58 | object creation of type StringReader | +| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader | +| MissingXMLValidation.cs:22:42:22:64 | object creation of type XmlReaderSettings | MissingXMLValidation.cs:23:61:23:72 | access to local variable badSettings1 | +| MissingXMLValidation.cs:27:42:27:64 | object creation of type XmlReaderSettings | MissingXMLValidation.cs:29:61:29:72 | access to local variable badSettings2 | +| MissingXMLValidation.cs:32:42:32:64 | object creation of type XmlReaderSettings | MissingXMLValidation.cs:37:61:37:72 | access to local variable goodSettings | +| MissingXMLValidation.cs:40:42:40:64 | object creation of type XmlReaderSettings | MissingXMLValidation.cs:47:61:47:72 | access to local variable badSettings3 | +nodes +| MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | +| MissingXMLValidation.cs:18:26:18:58 | object creation of type StringReader | +| MissingXMLValidation.cs:22:42:22:64 | object creation of type XmlReaderSettings | +| MissingXMLValidation.cs:23:26:23:58 | object creation of type StringReader | +| MissingXMLValidation.cs:23:61:23:72 | access to local variable badSettings1 | +| MissingXMLValidation.cs:27:42:27:64 | object creation of type XmlReaderSettings | +| MissingXMLValidation.cs:29:26:29:58 | object creation of type StringReader | +| MissingXMLValidation.cs:29:61:29:72 | access to local variable badSettings2 | +| MissingXMLValidation.cs:32:42:32:64 | object creation of type XmlReaderSettings | +| MissingXMLValidation.cs:37:26:37:58 | object creation of type StringReader | +| MissingXMLValidation.cs:37:61:37:72 | access to local variable goodSettings | +| MissingXMLValidation.cs:40:42:40:64 | object creation of type XmlReaderSettings | +| MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader | +| MissingXMLValidation.cs:47:61:47:72 | access to local variable badSettings3 | +#select +| MissingXMLValidation.cs:18:26:18:58 | object creation of type StringReader | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:18:26:18:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because there is no 'XmlReaderSettings' instance specifying schema validation. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | +| MissingXMLValidation.cs:23:26:23:58 | object creation of type StringReader | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:23:26:23:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance does not specify the 'ValidationType' as 'Schema'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | +| MissingXMLValidation.cs:29:26:29:58 | object creation of type StringReader | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:29:26:29:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance does not specify the 'ValidationType' as 'Schema'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | +| MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance specifies 'ProcessInlineSchema'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | +| MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | MissingXMLValidation.cs:47:26:47:58 | object creation of type StringReader | $@ flows to here and is processed as XML without validation because the 'XmlReaderSettings' instance specifies 'ProcessSchemaLocation'. | MissingXMLValidation.cs:14:34:14:56 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected index a17b4cbf24d..5cba04b42c2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected @@ -1,2 +1,10 @@ -| LogForging.cs:22:21:22:43 | ... + ... | $@ flows to log entry. | LogForging.cs:19:27:19:49 | access to property QueryString | User-provided value | -| LogForging.cs:28:50:28:72 | ... + ... | $@ flows to log entry. | LogForging.cs:19:27:19:49 | access to property QueryString | User-provided value | +edges +| LogForging.cs:19:27:19:49 | access to property QueryString | LogForging.cs:22:21:22:43 | ... + ... | +| LogForging.cs:19:27:19:49 | access to property QueryString | LogForging.cs:28:50:28:72 | ... + ... | +nodes +| LogForging.cs:19:27:19:49 | access to property QueryString | +| LogForging.cs:22:21:22:43 | ... + ... | +| LogForging.cs:28:50:28:72 | ... + ... | +#select +| LogForging.cs:22:21:22:43 | ... + ... | LogForging.cs:19:27:19:49 | access to property QueryString | LogForging.cs:22:21:22:43 | ... + ... | $@ flows to log entry. | LogForging.cs:19:27:19:49 | access to property QueryString | User-provided value | +| LogForging.cs:28:50:28:72 | ... + ... | LogForging.cs:19:27:19:49 | access to property QueryString | LogForging.cs:28:50:28:72 | ... + ... | $@ flows to log entry. | LogForging.cs:19:27:19:49 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/ExposureInTransmittedData.expected b/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/ExposureInTransmittedData.expected index 39baca89ce8..78ef8bdf19e 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/ExposureInTransmittedData.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/ExposureInTransmittedData.expected @@ -1,9 +1,28 @@ -| ExposureInTransmittedData.cs:16:32:16:39 | access to local variable password | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:16:32:16:39 | access to local variable password | access to local variable password | -| ExposureInTransmittedData.cs:20:32:20:44 | call to method ToString | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:20:32:20:44 | call to method ToString | call to method ToString | -| ExposureInTransmittedData.cs:24:32:24:41 | access to property Message | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:24:32:24:41 | access to property Message | access to property Message | -| ExposureInTransmittedData.cs:25:32:25:44 | call to method ToString | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:25:32:25:44 | call to method ToString | call to method ToString | -| ExposureInTransmittedData.cs:26:32:26:50 | access to indexer | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:26:32:26:38 | access to property Data | access to property Data | -| ExposureInTransmittedData.cs:33:53:33:53 | access to local variable p | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | call to method GetField | -| ExposureInTransmittedData.cs:33:56:33:56 | access to local variable p | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | call to method GetField | -| ExposureInTransmittedData.cs:34:24:34:52 | ... + ... | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | call to method GetField | -| ExposureInTransmittedData.cs:35:27:35:27 | access to local variable p | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | call to method GetField | +edges +| ExposureInTransmittedData.cs:26:32:26:38 | access to property Data | ExposureInTransmittedData.cs:26:32:26:50 | access to indexer | +| ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | ExposureInTransmittedData.cs:33:53:33:53 | access to local variable p | +| ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | ExposureInTransmittedData.cs:33:56:33:56 | access to local variable p | +| ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | ExposureInTransmittedData.cs:34:24:34:52 | ... + ... | +| ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | ExposureInTransmittedData.cs:35:27:35:27 | access to local variable p | +nodes +| ExposureInTransmittedData.cs:16:32:16:39 | access to local variable password | +| ExposureInTransmittedData.cs:20:32:20:44 | call to method ToString | +| ExposureInTransmittedData.cs:24:32:24:41 | access to property Message | +| ExposureInTransmittedData.cs:25:32:25:44 | call to method ToString | +| ExposureInTransmittedData.cs:26:32:26:38 | access to property Data | +| ExposureInTransmittedData.cs:26:32:26:50 | access to indexer | +| ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | +| ExposureInTransmittedData.cs:33:53:33:53 | access to local variable p | +| ExposureInTransmittedData.cs:33:56:33:56 | access to local variable p | +| ExposureInTransmittedData.cs:34:24:34:52 | ... + ... | +| ExposureInTransmittedData.cs:35:27:35:27 | access to local variable p | +#select +| ExposureInTransmittedData.cs:16:32:16:39 | access to local variable password | ExposureInTransmittedData.cs:16:32:16:39 | access to local variable password | ExposureInTransmittedData.cs:16:32:16:39 | access to local variable password | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:16:32:16:39 | access to local variable password | access to local variable password | +| ExposureInTransmittedData.cs:20:32:20:44 | call to method ToString | ExposureInTransmittedData.cs:20:32:20:44 | call to method ToString | ExposureInTransmittedData.cs:20:32:20:44 | call to method ToString | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:20:32:20:44 | call to method ToString | call to method ToString | +| ExposureInTransmittedData.cs:24:32:24:41 | access to property Message | ExposureInTransmittedData.cs:24:32:24:41 | access to property Message | ExposureInTransmittedData.cs:24:32:24:41 | access to property Message | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:24:32:24:41 | access to property Message | access to property Message | +| ExposureInTransmittedData.cs:25:32:25:44 | call to method ToString | ExposureInTransmittedData.cs:25:32:25:44 | call to method ToString | ExposureInTransmittedData.cs:25:32:25:44 | call to method ToString | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:25:32:25:44 | call to method ToString | call to method ToString | +| ExposureInTransmittedData.cs:26:32:26:50 | access to indexer | ExposureInTransmittedData.cs:26:32:26:38 | access to property Data | ExposureInTransmittedData.cs:26:32:26:50 | access to indexer | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:26:32:26:38 | access to property Data | access to property Data | +| ExposureInTransmittedData.cs:33:53:33:53 | access to local variable p | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | ExposureInTransmittedData.cs:33:53:33:53 | access to local variable p | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | call to method GetField | +| ExposureInTransmittedData.cs:33:56:33:56 | access to local variable p | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | ExposureInTransmittedData.cs:33:56:33:56 | access to local variable p | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | call to method GetField | +| ExposureInTransmittedData.cs:34:24:34:52 | ... + ... | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | ExposureInTransmittedData.cs:34:24:34:52 | ... + ... | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | call to method GetField | +| ExposureInTransmittedData.cs:35:27:35:27 | access to local variable p | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | ExposureInTransmittedData.cs:35:27:35:27 | access to local variable p | Sensitive information from $@ flows to here, and is transmitted to the user. | ExposureInTransmittedData.cs:32:17:32:36 | call to method GetField | call to method GetField | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected index f4bfdef798b..7d3578bc71e 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected @@ -1,5 +1,14 @@ -| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | call to method ToString | -| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex | access to local variable ex | -| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | access to local variable ex | -| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | access to property StackTrace | -| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | call to method ToString | +edges +| ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | +nodes +| ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex | +| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | +| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | +| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | +| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | +#select +| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | call to method ToString | +| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex | access to local variable ex | +| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | access to local variable ex | +| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | access to property StackTrace | +| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | call to method ToString | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-312/CleartextStorage.expected b/csharp/ql/test/query-tests/Security Features/CWE-312/CleartextStorage.expected index a5a2ca8b2f9..7d564153bca 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-312/CleartextStorage.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-312/CleartextStorage.expected @@ -1,5 +1,13 @@ -| CleartextStorage.cs:14:50:14:59 | access to field accountKey | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:14:50:14:59 | access to field accountKey | access to field accountKey | -| CleartextStorage.cs:15:62:15:74 | call to method GetPassword | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:15:62:15:74 | call to method GetPassword | call to method GetPassword | -| CleartextStorage.cs:16:69:16:81 | call to method GetPassword | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:16:69:16:81 | call to method GetPassword | call to method GetPassword | -| CleartextStorage.cs:17:50:17:63 | call to method GetAccountID | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:17:50:17:63 | call to method GetAccountID | call to method GetAccountID | -| CleartextStorage.cs:25:21:25:33 | call to method GetPassword | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:25:21:25:33 | call to method GetPassword | call to method GetPassword | +edges +nodes +| CleartextStorage.cs:14:50:14:59 | access to field accountKey | +| CleartextStorage.cs:15:62:15:74 | call to method GetPassword | +| CleartextStorage.cs:16:69:16:81 | call to method GetPassword | +| CleartextStorage.cs:17:50:17:63 | call to method GetAccountID | +| CleartextStorage.cs:25:21:25:33 | call to method GetPassword | +#select +| CleartextStorage.cs:14:50:14:59 | access to field accountKey | CleartextStorage.cs:14:50:14:59 | access to field accountKey | CleartextStorage.cs:14:50:14:59 | access to field accountKey | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:14:50:14:59 | access to field accountKey | access to field accountKey | +| CleartextStorage.cs:15:62:15:74 | call to method GetPassword | CleartextStorage.cs:15:62:15:74 | call to method GetPassword | CleartextStorage.cs:15:62:15:74 | call to method GetPassword | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:15:62:15:74 | call to method GetPassword | call to method GetPassword | +| CleartextStorage.cs:16:69:16:81 | call to method GetPassword | CleartextStorage.cs:16:69:16:81 | call to method GetPassword | CleartextStorage.cs:16:69:16:81 | call to method GetPassword | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:16:69:16:81 | call to method GetPassword | call to method GetPassword | +| CleartextStorage.cs:17:50:17:63 | call to method GetAccountID | CleartextStorage.cs:17:50:17:63 | call to method GetAccountID | CleartextStorage.cs:17:50:17:63 | call to method GetAccountID | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:17:50:17:63 | call to method GetAccountID | call to method GetAccountID | +| CleartextStorage.cs:25:21:25:33 | call to method GetPassword | CleartextStorage.cs:25:21:25:33 | call to method GetPassword | CleartextStorage.cs:25:21:25:33 | call to method GetPassword | Sensitive data returned by $@ is stored here. | CleartextStorage.cs:25:21:25:33 | call to method GetPassword | call to method GetPassword | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-327/DontInstallRootCert/DontInstallRootCert.expected b/csharp/ql/test/query-tests/Security Features/CWE-327/DontInstallRootCert/DontInstallRootCert.expected index fb8bf1f0ea2..5ef8bf77643 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-327/DontInstallRootCert/DontInstallRootCert.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-327/DontInstallRootCert/DontInstallRootCert.expected @@ -1,3 +1,15 @@ -| Test.cs:20:13:20:17 | access to local variable store | Certificate added to the root certificate store. | -| Test.cs:30:13:30:17 | access to local variable store | Certificate added to the root certificate store. | -| Test.cs:75:13:75:17 | access to local variable store | Certificate added to the root certificate store. | +edges +| Test.cs:17:31:17:59 | object creation of type X509Store | Test.cs:20:13:20:17 | access to local variable store | +| Test.cs:27:31:27:86 | object creation of type X509Store | Test.cs:30:13:30:17 | access to local variable store | +| Test.cs:72:31:72:86 | object creation of type X509Store | Test.cs:75:13:75:17 | access to local variable store | +nodes +| Test.cs:17:31:17:59 | object creation of type X509Store | +| Test.cs:20:13:20:17 | access to local variable store | +| Test.cs:27:31:27:86 | object creation of type X509Store | +| Test.cs:30:13:30:17 | access to local variable store | +| Test.cs:72:31:72:86 | object creation of type X509Store | +| Test.cs:75:13:75:17 | access to local variable store | +#select +| Test.cs:20:13:20:17 | access to local variable store | Test.cs:17:31:17:59 | object creation of type X509Store | Test.cs:20:13:20:17 | access to local variable store | Certificate added to the root certificate store. | +| Test.cs:30:13:30:17 | access to local variable store | Test.cs:27:31:27:86 | object creation of type X509Store | Test.cs:30:13:30:17 | access to local variable store | Certificate added to the root certificate store. | +| Test.cs:75:13:75:17 | access to local variable store | Test.cs:72:31:72:86 | object creation of type X509Store | Test.cs:75:13:75:17 | access to local variable store | Certificate added to the root certificate store. | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected index 215587f5754..a5fb3480409 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected @@ -1,3 +1,24 @@ -| InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:28:29:28:43 | call to method Next | call to method Next | -| InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:60:31:60:39 | call to method Next | call to method Next | -| InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:72:31:72:39 | call to method Next | call to method Next | +edges +| InsecureRandomness.cs:28:29:28:43 | call to method Next | InsecureRandomness.cs:29:27:29:61 | call to method GetString | +| InsecureRandomness.cs:28:29:28:43 | call to method Next | InsecureRandomness.cs:31:16:31:32 | call to method ToString | +| InsecureRandomness.cs:29:27:29:61 | call to method GetString | InsecureRandomness.cs:31:16:31:32 | call to method ToString | +| InsecureRandomness.cs:31:16:31:32 | call to method ToString | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | +| InsecureRandomness.cs:60:31:60:39 | call to method Next | InsecureRandomness.cs:62:16:62:32 | call to method ToString | +| InsecureRandomness.cs:62:16:62:32 | call to method ToString | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | +| InsecureRandomness.cs:72:31:72:39 | call to method Next | InsecureRandomness.cs:74:16:74:21 | access to local variable result | +| InsecureRandomness.cs:74:16:74:21 | access to local variable result | InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer | +nodes +| InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | +| InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | +| InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer | +| InsecureRandomness.cs:28:29:28:43 | call to method Next | +| InsecureRandomness.cs:29:27:29:61 | call to method GetString | +| InsecureRandomness.cs:31:16:31:32 | call to method ToString | +| InsecureRandomness.cs:60:31:60:39 | call to method Next | +| InsecureRandomness.cs:62:16:62:32 | call to method ToString | +| InsecureRandomness.cs:72:31:72:39 | call to method Next | +| InsecureRandomness.cs:74:16:74:21 | access to local variable result | +#select +| InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | InsecureRandomness.cs:28:29:28:43 | call to method Next | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:28:29:28:43 | call to method Next | call to method Next | +| InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | InsecureRandomness.cs:60:31:60:39 | call to method Next | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:60:31:60:39 | call to method Next | call to method Next | +| InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer | InsecureRandomness.cs:72:31:72:39 | call to method Next | InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:72:31:72:39 | call to method Next | call to method Next | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-359/ExposureOfPrivateInformation.expected b/csharp/ql/test/query-tests/Security Features/CWE-359/ExposureOfPrivateInformation.expected index 96397029155..e0a0bcbe3fe 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-359/ExposureOfPrivateInformation.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-359/ExposureOfPrivateInformation.expected @@ -1,3 +1,9 @@ -| ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | access to indexer | -| ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | call to method getTelephone | -| ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | call to method getTelephone | +edges +nodes +| ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | +| ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | +| ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | +#select +| ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:18:50:18:84 | access to indexer | access to indexer | +| ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:20:50:20:65 | call to method getTelephone | call to method getTelephone | +| ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | Private data returned by $@ is written to an external location. | ExposureOfPrivateInformation.cs:24:21:24:36 | call to method getTelephone | call to method getTelephone | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.expected b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.expected index eec21ad90a1..ea4b2b5a605 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.expected @@ -1,14 +1,51 @@ -| UrlRedirect.cs:14:31:14:61 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:14:31:14:53 | access to property QueryString | user-provided value | -| UrlRedirect.cs:39:44:39:74 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:39:44:39:66 | access to property QueryString | user-provided value | -| UrlRedirect.cs:40:47:40:77 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:40:47:40:69 | access to property QueryString | user-provided value | -| UrlRedirect.cs:49:29:49:31 | access to local variable url | Untrusted URL redirection due to $@. | UrlRedirect.cs:24:22:24:44 | access to property QueryString | user-provided value | -| UrlRedirectCore.cs:18:22:18:26 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | -| UrlRedirectCore.cs:21:44:21:48 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | -| UrlRedirectCore.cs:27:46:27:50 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | -| UrlRedirectCore.cs:33:66:33:70 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | -| UrlRedirectCore.cs:36:49:36:53 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | -| UrlRedirectCore.cs:39:69:39:73 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | -| UrlRedirectCore.cs:42:39:42:53 | ... + ... | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | -| UrlRedirectCore.cs:50:28:50:32 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | -| UrlRedirectCore.cs:55:32:55:45 | object creation of type Uri | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | -| UrlRedirectCore.cs:58:31:58:35 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | +edges +| UrlRedirect.cs:14:31:14:53 | access to property QueryString | UrlRedirect.cs:14:31:14:61 | access to indexer | +| UrlRedirect.cs:24:22:24:44 | access to property QueryString | UrlRedirect.cs:49:29:49:31 | access to local variable url | +| UrlRedirect.cs:39:44:39:66 | access to property QueryString | UrlRedirect.cs:39:44:39:74 | access to indexer | +| UrlRedirect.cs:40:47:40:69 | access to property QueryString | UrlRedirect.cs:40:47:40:77 | access to indexer | +| UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:18:22:18:26 | access to parameter value | +| UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:21:44:21:48 | call to operator implicit conversion | +| UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:27:46:27:50 | call to operator implicit conversion | +| UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:33:66:33:70 | access to parameter value | +| UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:36:49:36:53 | call to operator implicit conversion | +| UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:39:69:39:73 | access to parameter value | +| UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:42:39:42:53 | ... + ... | +| UrlRedirectCore.cs:47:51:47:55 | value | UrlRedirectCore.cs:50:28:50:32 | access to parameter value | +| UrlRedirectCore.cs:47:51:47:55 | value | UrlRedirectCore.cs:55:32:55:45 | object creation of type Uri | +| UrlRedirectCore.cs:47:51:47:55 | value | UrlRedirectCore.cs:58:31:58:35 | access to parameter value | +nodes +| UrlRedirect.cs:14:31:14:53 | access to property QueryString | +| UrlRedirect.cs:14:31:14:61 | access to indexer | +| UrlRedirect.cs:24:22:24:44 | access to property QueryString | +| UrlRedirect.cs:39:44:39:66 | access to property QueryString | +| UrlRedirect.cs:39:44:39:74 | access to indexer | +| UrlRedirect.cs:40:47:40:69 | access to property QueryString | +| UrlRedirect.cs:40:47:40:77 | access to indexer | +| UrlRedirect.cs:49:29:49:31 | access to local variable url | +| UrlRedirectCore.cs:15:44:15:48 | value | +| UrlRedirectCore.cs:18:22:18:26 | access to parameter value | +| UrlRedirectCore.cs:21:44:21:48 | call to operator implicit conversion | +| UrlRedirectCore.cs:27:46:27:50 | call to operator implicit conversion | +| UrlRedirectCore.cs:33:66:33:70 | access to parameter value | +| UrlRedirectCore.cs:36:49:36:53 | call to operator implicit conversion | +| UrlRedirectCore.cs:39:69:39:73 | access to parameter value | +| UrlRedirectCore.cs:42:39:42:53 | ... + ... | +| UrlRedirectCore.cs:47:51:47:55 | value | +| UrlRedirectCore.cs:50:28:50:32 | access to parameter value | +| UrlRedirectCore.cs:55:32:55:45 | object creation of type Uri | +| UrlRedirectCore.cs:58:31:58:35 | access to parameter value | +#select +| UrlRedirect.cs:14:31:14:61 | access to indexer | UrlRedirect.cs:14:31:14:53 | access to property QueryString | UrlRedirect.cs:14:31:14:61 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:14:31:14:53 | access to property QueryString | user-provided value | +| UrlRedirect.cs:39:44:39:74 | access to indexer | UrlRedirect.cs:39:44:39:66 | access to property QueryString | UrlRedirect.cs:39:44:39:74 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:39:44:39:66 | access to property QueryString | user-provided value | +| UrlRedirect.cs:40:47:40:77 | access to indexer | UrlRedirect.cs:40:47:40:69 | access to property QueryString | UrlRedirect.cs:40:47:40:77 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:40:47:40:69 | access to property QueryString | user-provided value | +| UrlRedirect.cs:49:29:49:31 | access to local variable url | UrlRedirect.cs:24:22:24:44 | access to property QueryString | UrlRedirect.cs:49:29:49:31 | access to local variable url | Untrusted URL redirection due to $@. | UrlRedirect.cs:24:22:24:44 | access to property QueryString | user-provided value | +| UrlRedirectCore.cs:18:22:18:26 | access to parameter value | UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:18:22:18:26 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:21:44:21:48 | call to operator implicit conversion | UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:21:44:21:48 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:27:46:27:50 | call to operator implicit conversion | UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:27:46:27:50 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:33:66:33:70 | access to parameter value | UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:33:66:33:70 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:36:49:36:53 | call to operator implicit conversion | UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:36:49:36:53 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:39:69:39:73 | access to parameter value | UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:39:69:39:73 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:42:39:42:53 | ... + ... | UrlRedirectCore.cs:15:44:15:48 | value | UrlRedirectCore.cs:42:39:42:53 | ... + ... | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:50:28:50:32 | access to parameter value | UrlRedirectCore.cs:47:51:47:55 | value | UrlRedirectCore.cs:50:28:50:32 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | +| UrlRedirectCore.cs:55:32:55:45 | object creation of type Uri | UrlRedirectCore.cs:47:51:47:55 | value | UrlRedirectCore.cs:55:32:55:45 | object creation of type Uri | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | +| UrlRedirectCore.cs:58:31:58:35 | access to parameter value | UrlRedirectCore.cs:47:51:47:55 | value | UrlRedirectCore.cs:58:31:58:35 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-611/UntrustedDataInsecureXml.expected b/csharp/ql/test/query-tests/Security Features/CWE-611/UntrustedDataInsecureXml.expected index 59363eed855..5f68dc30cd0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-611/UntrustedDataInsecureXml.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-611/UntrustedDataInsecureXml.expected @@ -1 +1,10 @@ -| Test.cs:13:50:13:84 | access to indexer | $@ flows to here and is loaded insecurely as XML (DTD processing is enabled with an insecure resolver). | Test.cs:13:50:13:72 | access to property QueryString | User-provided value | +edges +| Test.cs:13:50:13:72 | access to property QueryString | Test.cs:13:50:13:84 | access to indexer | +| Test.cs:18:38:18:60 | object creation of type XmlReaderSettings | Test.cs:23:55:23:62 | access to local variable settings | +nodes +| Test.cs:13:50:13:72 | access to property QueryString | +| Test.cs:13:50:13:84 | access to indexer | +| Test.cs:18:38:18:60 | object creation of type XmlReaderSettings | +| Test.cs:23:55:23:62 | access to local variable settings | +#select +| Test.cs:13:50:13:84 | access to indexer | Test.cs:13:50:13:72 | access to property QueryString | Test.cs:13:50:13:84 | access to indexer | $@ flows to here and is loaded insecurely as XML (DTD processing is enabled with an insecure resolver). | Test.cs:13:50:13:72 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-643/StoredXPathInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-643/StoredXPathInjection.expected index 8054b637031..3415ec96976 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-643/StoredXPathInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-643/StoredXPathInjection.expected @@ -1,4 +1,15 @@ -| StoredXPathInjection.cs:27:45:27:148 | ... + ... | $@ flows to here and is used in an XPath expression. | StoredXPathInjection.cs:24:39:24:65 | call to method GetString | Stored user-provided value | -| StoredXPathInjection.cs:27:45:27:148 | ... + ... | $@ flows to here and is used in an XPath expression. | StoredXPathInjection.cs:25:39:25:65 | call to method GetString | Stored user-provided value | -| StoredXPathInjection.cs:30:41:30:144 | ... + ... | $@ flows to here and is used in an XPath expression. | StoredXPathInjection.cs:24:39:24:65 | call to method GetString | Stored user-provided value | -| StoredXPathInjection.cs:30:41:30:144 | ... + ... | $@ flows to here and is used in an XPath expression. | StoredXPathInjection.cs:25:39:25:65 | call to method GetString | Stored user-provided value | +edges +| StoredXPathInjection.cs:24:39:24:65 | call to method GetString | StoredXPathInjection.cs:27:45:27:148 | ... + ... | +| StoredXPathInjection.cs:24:39:24:65 | call to method GetString | StoredXPathInjection.cs:30:41:30:144 | ... + ... | +| StoredXPathInjection.cs:25:39:25:65 | call to method GetString | StoredXPathInjection.cs:27:45:27:148 | ... + ... | +| StoredXPathInjection.cs:25:39:25:65 | call to method GetString | StoredXPathInjection.cs:30:41:30:144 | ... + ... | +nodes +| StoredXPathInjection.cs:24:39:24:65 | call to method GetString | +| StoredXPathInjection.cs:25:39:25:65 | call to method GetString | +| StoredXPathInjection.cs:27:45:27:148 | ... + ... | +| StoredXPathInjection.cs:30:41:30:144 | ... + ... | +#select +| StoredXPathInjection.cs:27:45:27:148 | ... + ... | StoredXPathInjection.cs:24:39:24:65 | call to method GetString | StoredXPathInjection.cs:27:45:27:148 | ... + ... | $@ flows to here and is used in an XPath expression. | StoredXPathInjection.cs:24:39:24:65 | call to method GetString | Stored user-provided value | +| StoredXPathInjection.cs:27:45:27:148 | ... + ... | StoredXPathInjection.cs:25:39:25:65 | call to method GetString | StoredXPathInjection.cs:27:45:27:148 | ... + ... | $@ flows to here and is used in an XPath expression. | StoredXPathInjection.cs:25:39:25:65 | call to method GetString | Stored user-provided value | +| StoredXPathInjection.cs:30:41:30:144 | ... + ... | StoredXPathInjection.cs:24:39:24:65 | call to method GetString | StoredXPathInjection.cs:30:41:30:144 | ... + ... | $@ flows to here and is used in an XPath expression. | StoredXPathInjection.cs:24:39:24:65 | call to method GetString | Stored user-provided value | +| StoredXPathInjection.cs:30:41:30:144 | ... + ... | StoredXPathInjection.cs:25:39:25:65 | call to method GetString | StoredXPathInjection.cs:30:41:30:144 | ... + ... | $@ flows to here and is used in an XPath expression. | StoredXPathInjection.cs:25:39:25:65 | call to method GetString | Stored user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-643/XPathInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-643/XPathInjection.expected index 31f05d8da31..84f46930c1a 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-643/XPathInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-643/XPathInjection.expected @@ -1,4 +1,15 @@ -| XPathInjection.cs:16:33:16:136 | ... + ... | $@ flows to here and is used in an XPath expression. | XPathInjection.cs:12:27:12:49 | access to property QueryString | User-provided value | -| XPathInjection.cs:16:33:16:136 | ... + ... | $@ flows to here and is used in an XPath expression. | XPathInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | -| XPathInjection.cs:19:29:19:132 | ... + ... | $@ flows to here and is used in an XPath expression. | XPathInjection.cs:12:27:12:49 | access to property QueryString | User-provided value | -| XPathInjection.cs:19:29:19:132 | ... + ... | $@ flows to here and is used in an XPath expression. | XPathInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | +edges +| XPathInjection.cs:12:27:12:49 | access to property QueryString | XPathInjection.cs:16:33:16:136 | ... + ... | +| XPathInjection.cs:12:27:12:49 | access to property QueryString | XPathInjection.cs:19:29:19:132 | ... + ... | +| XPathInjection.cs:13:27:13:49 | access to property QueryString | XPathInjection.cs:16:33:16:136 | ... + ... | +| XPathInjection.cs:13:27:13:49 | access to property QueryString | XPathInjection.cs:19:29:19:132 | ... + ... | +nodes +| XPathInjection.cs:12:27:12:49 | access to property QueryString | +| XPathInjection.cs:13:27:13:49 | access to property QueryString | +| XPathInjection.cs:16:33:16:136 | ... + ... | +| XPathInjection.cs:19:29:19:132 | ... + ... | +#select +| XPathInjection.cs:16:33:16:136 | ... + ... | XPathInjection.cs:12:27:12:49 | access to property QueryString | XPathInjection.cs:16:33:16:136 | ... + ... | $@ flows to here and is used in an XPath expression. | XPathInjection.cs:12:27:12:49 | access to property QueryString | User-provided value | +| XPathInjection.cs:16:33:16:136 | ... + ... | XPathInjection.cs:13:27:13:49 | access to property QueryString | XPathInjection.cs:16:33:16:136 | ... + ... | $@ flows to here and is used in an XPath expression. | XPathInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | +| XPathInjection.cs:19:29:19:132 | ... + ... | XPathInjection.cs:12:27:12:49 | access to property QueryString | XPathInjection.cs:19:29:19:132 | ... + ... | $@ flows to here and is used in an XPath expression. | XPathInjection.cs:12:27:12:49 | access to property QueryString | User-provided value | +| XPathInjection.cs:19:29:19:132 | ... + ... | XPathInjection.cs:13:27:13:49 | access to property QueryString | XPathInjection.cs:19:29:19:132 | ... + ... | $@ flows to here and is used in an XPath expression. | XPathInjection.cs:13:27:13:49 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/ReDoS.expected b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/ReDoS.expected index 86e0282dddf..370665a4e63 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/ReDoS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/ReDoS.expected @@ -1,5 +1,41 @@ -| ExponentialRegex.cs:17:40:17:48 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | -| ExponentialRegex.cs:18:42:18:50 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | -| ExponentialRegex.cs:21:139:21:147 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | -| ExponentialRegex.cs:24:43:24:51 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | -| ExponentialRegex.cs:26:21:26:29 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | +edges +| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX | +| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX | +| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | ExponentialRegex.cs:30:32:30:47 | access to field JAVA_CLASS_REGEX | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:17:40:17:48 | access to local variable userInput | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:18:42:18:50 | access to local variable userInput | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:21:139:21:147 | access to local variable userInput | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:24:43:24:51 | access to local variable userInput | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:26:21:26:29 | access to local variable userInput | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:28:47:28:55 | access to local variable userInput | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:29:90:29:98 | access to local variable userInput | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:30:21:30:29 | access to local variable userInput | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:32:57:32:65 | access to local variable userInput | +| ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX | ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX | +| ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX | ExponentialRegex.cs:30:32:30:47 | access to field JAVA_CLASS_REGEX | +| ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX | ExponentialRegex.cs:30:32:30:47 | access to field JAVA_CLASS_REGEX | +nodes +| ExponentialRegex.cs:9:55:9:83 | "^(([a-z])+.)+[A-Z]([a-z])+$" | +| ExponentialRegex.cs:13:28:13:50 | access to property QueryString | +| ExponentialRegex.cs:17:19:17:31 | "^([a-z]+)+$" | +| ExponentialRegex.cs:17:40:17:48 | access to local variable userInput | +| ExponentialRegex.cs:18:19:18:31 | "^([a-z]*)*$" | +| ExponentialRegex.cs:18:42:18:50 | access to local variable userInput | +| ExponentialRegex.cs:21:19:21:130 | "^([a-zA-Z0-9])(([\\-.]\|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})\|([a-z]{2,3}[.]{1}[a-z]{2,3}))$" | +| ExponentialRegex.cs:21:139:21:147 | access to local variable userInput | +| ExponentialRegex.cs:24:19:24:34 | access to field JAVA_CLASS_REGEX | +| ExponentialRegex.cs:24:43:24:51 | access to local variable userInput | +| ExponentialRegex.cs:26:21:26:29 | access to local variable userInput | +| ExponentialRegex.cs:26:32:26:47 | access to field JAVA_CLASS_REGEX | +| ExponentialRegex.cs:28:47:28:55 | access to local variable userInput | +| ExponentialRegex.cs:29:19:29:31 | "^([a-z]+)+$" | +| ExponentialRegex.cs:29:90:29:98 | access to local variable userInput | +| ExponentialRegex.cs:30:21:30:29 | access to local variable userInput | +| ExponentialRegex.cs:30:32:30:47 | access to field JAVA_CLASS_REGEX | +| ExponentialRegex.cs:32:57:32:65 | access to local variable userInput | +#select +| ExponentialRegex.cs:17:40:17:48 | access to local variable userInput | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:17:40:17:48 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | +| ExponentialRegex.cs:18:42:18:50 | access to local variable userInput | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:18:42:18:50 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | +| ExponentialRegex.cs:21:139:21:147 | access to local variable userInput | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:21:139:21:147 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | +| ExponentialRegex.cs:24:43:24:51 | access to local variable userInput | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:24:43:24:51 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | +| ExponentialRegex.cs:26:21:26:29 | access to local variable userInput | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | ExponentialRegex.cs:26:21:26:29 | access to local variable userInput | $@ flows to regular expression operation with dangerous regex. | ExponentialRegex.cs:13:28:13:50 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/ReDoS.expected b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/ReDoS.expected index e69de29bb2d..140050954bc 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/ReDoS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/ReDoS.expected @@ -0,0 +1,7 @@ +edges +| ExponentialRegex.cs:15:28:15:50 | access to property QueryString | ExponentialRegex.cs:18:40:18:48 | access to local variable userInput | +nodes +| ExponentialRegex.cs:15:28:15:50 | access to property QueryString | +| ExponentialRegex.cs:18:19:18:31 | "^([a-z]+)+$" | +| ExponentialRegex.cs:18:40:18:48 | access to local variable userInput | +#select diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/RegexInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/RegexInjection.expected index c3638ab2608..b17c5030694 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/RegexInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/RegexInjection.expected @@ -1 +1,7 @@ -| RegexInjection.cs:16:19:16:23 | access to local variable regex | $@ flows to the construction of a regular expression. | RegexInjection.cs:12:24:12:46 | access to property QueryString | User-provided value | +edges +| RegexInjection.cs:12:24:12:46 | access to property QueryString | RegexInjection.cs:16:19:16:23 | access to local variable regex | +nodes +| RegexInjection.cs:12:24:12:46 | access to property QueryString | +| RegexInjection.cs:16:19:16:23 | access to local variable regex | +#select +| RegexInjection.cs:16:19:16:23 | access to local variable regex | RegexInjection.cs:12:24:12:46 | access to property QueryString | RegexInjection.cs:16:19:16:23 | access to local variable regex | $@ flows to the construction of a regular expression. | RegexInjection.cs:12:24:12:46 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-798/HardcodedConnectionString.expected b/csharp/ql/test/query-tests/Security Features/CWE-798/HardcodedConnectionString.expected index 6854cbafe32..6d67b199670 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-798/HardcodedConnectionString.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-798/HardcodedConnectionString.expected @@ -1,2 +1,19 @@ -| HardcodedCredentials.cs:56:48:56:63 | "Password=12345" | 'ConnectionString' property includes hard-coded credentials set in $@. | HardcodedCredentials.cs:56:30:56:64 | object creation of type SqlConnection | object creation of type SqlConnection | -| HardcodedCredentials.cs:58:49:58:63 | "User Id=12345" | 'ConnectionString' property includes hard-coded credentials set in $@. | HardcodedCredentials.cs:58:31:58:64 | object creation of type SqlConnection | object creation of type SqlConnection | +edges +| HardcodedCredentials.cs:49:30:49:60 | array creation of type Byte[] | HardcodedCredentials.cs:52:13:52:23 | access to local variable rawCertData | +nodes +| HardcodedCredentials.cs:17:25:17:36 | "myPa55word" | +| HardcodedCredentials.cs:33:19:33:28 | "username" | +| HardcodedCredentials.cs:47:39:47:53 | "myNewPa55word" | +| HardcodedCredentials.cs:49:30:49:60 | array creation of type Byte[] | +| HardcodedCredentials.cs:52:13:52:23 | access to local variable rawCertData | +| HardcodedCredentials.cs:53:13:53:24 | "myPa55word" | +| HardcodedCredentials.cs:56:48:56:63 | "Password=12345" | +| HardcodedCredentials.cs:58:49:58:63 | "User Id=12345" | +| HardcodedCredentials.cs:76:31:76:42 | "myusername" | +| HardcodedCredentials.cs:76:45:76:56 | "mypassword" | +| TestHardcodedCredentials.cs:21:31:21:42 | "myusername" | +| TestHardcodedCredentials.cs:21:45:21:56 | "mypassword" | +| TestHardcodedCredentials.cs:26:19:26:28 | "username" | +#select +| HardcodedCredentials.cs:56:48:56:63 | "Password=12345" | HardcodedCredentials.cs:56:48:56:63 | "Password=12345" | HardcodedCredentials.cs:56:48:56:63 | "Password=12345" | 'ConnectionString' property includes hard-coded credentials set in $@. | HardcodedCredentials.cs:56:30:56:64 | object creation of type SqlConnection | object creation of type SqlConnection | +| HardcodedCredentials.cs:58:49:58:63 | "User Id=12345" | HardcodedCredentials.cs:58:49:58:63 | "User Id=12345" | HardcodedCredentials.cs:58:49:58:63 | "User Id=12345" | 'ConnectionString' property includes hard-coded credentials set in $@. | HardcodedCredentials.cs:58:31:58:64 | object creation of type SqlConnection | object creation of type SqlConnection | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-798/HardcodedCredentials.expected b/csharp/ql/test/query-tests/Security Features/CWE-798/HardcodedCredentials.expected index 0aa0caa94f6..20d70fe7a37 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-798/HardcodedCredentials.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-798/HardcodedCredentials.expected @@ -1,8 +1,23 @@ -| HardcodedCredentials.cs:17:25:17:36 | "myPa55word" | The hard-coded value "myPa55word" flows to $@ which is compared against $@. | HardcodedCredentials.cs:17:25:17:36 | "myPa55word" | "myPa55word" | HardcodedCredentials.cs:17:13:17:20 | access to local variable password | access to local variable password | -| HardcodedCredentials.cs:33:19:33:28 | "username" | The hard-coded value "username" flows to the $@ parameter in $@. | HardcodedCredentials.cs:33:19:33:28 | "username" | name | HardcodedCredentials.cs:31:31:45:13 | object creation of type MembershipUser | object creation of type MembershipUser | -| HardcodedCredentials.cs:47:39:47:53 | "myNewPa55word" | The hard-coded value "myNewPa55word" flows to the $@ parameter in $@. | HardcodedCredentials.cs:47:39:47:53 | "myNewPa55word" | newPassword | HardcodedCredentials.cs:47:9:47:54 | call to method ChangePassword | call to method ChangePassword | -| HardcodedCredentials.cs:49:30:49:60 | array creation of type Byte[] | This hard-coded value flows to the $@ parameter in $@. | HardcodedCredentials.cs:52:13:52:23 | access to local variable rawCertData | rawData | HardcodedCredentials.cs:51:33:53:25 | object creation of type X509Certificate2 | object creation of type X509Certificate2 | -| HardcodedCredentials.cs:53:13:53:24 | "myPa55word" | The hard-coded value "myPa55word" flows to the $@ parameter in $@. | HardcodedCredentials.cs:53:13:53:24 | "myPa55word" | password | HardcodedCredentials.cs:51:33:53:25 | object creation of type X509Certificate2 | object creation of type X509Certificate2 | -| HardcodedCredentials.cs:76:31:76:42 | "myusername" | The hard-coded value "myusername" flows to the $@ parameter in $@. | HardcodedCredentials.cs:76:31:76:42 | "myusername" | username | HardcodedCredentials.cs:76:9:76:57 | call to method CreateUser | call to method CreateUser | -| HardcodedCredentials.cs:76:45:76:56 | "mypassword" | The hard-coded value "mypassword" flows to the $@ parameter in $@. | HardcodedCredentials.cs:76:45:76:56 | "mypassword" | password | HardcodedCredentials.cs:76:9:76:57 | call to method CreateUser | call to method CreateUser | -| TestHardcodedCredentials.cs:26:19:26:28 | "username" | The hard-coded value "username" flows to the $@ parameter in $@. | TestHardcodedCredentials.cs:26:19:26:28 | "username" | name | TestHardcodedCredentials.cs:24:31:38:13 | object creation of type MembershipUser | object creation of type MembershipUser | +edges +| HardcodedCredentials.cs:49:30:49:60 | array creation of type Byte[] | HardcodedCredentials.cs:52:13:52:23 | access to local variable rawCertData | +nodes +| HardcodedCredentials.cs:17:25:17:36 | "myPa55word" | +| HardcodedCredentials.cs:33:19:33:28 | "username" | +| HardcodedCredentials.cs:47:39:47:53 | "myNewPa55word" | +| HardcodedCredentials.cs:49:30:49:60 | array creation of type Byte[] | +| HardcodedCredentials.cs:52:13:52:23 | access to local variable rawCertData | +| HardcodedCredentials.cs:53:13:53:24 | "myPa55word" | +| HardcodedCredentials.cs:76:31:76:42 | "myusername" | +| HardcodedCredentials.cs:76:45:76:56 | "mypassword" | +| TestHardcodedCredentials.cs:21:31:21:42 | "myusername" | +| TestHardcodedCredentials.cs:21:45:21:56 | "mypassword" | +| TestHardcodedCredentials.cs:26:19:26:28 | "username" | +#select +| HardcodedCredentials.cs:17:25:17:36 | "myPa55word" | HardcodedCredentials.cs:17:25:17:36 | "myPa55word" | HardcodedCredentials.cs:17:25:17:36 | "myPa55word" | The hard-coded value "myPa55word" flows to $@ which is compared against $@. | HardcodedCredentials.cs:17:25:17:36 | "myPa55word" | "myPa55word" | HardcodedCredentials.cs:17:13:17:20 | access to local variable password | access to local variable password | +| HardcodedCredentials.cs:33:19:33:28 | "username" | HardcodedCredentials.cs:33:19:33:28 | "username" | HardcodedCredentials.cs:33:19:33:28 | "username" | The hard-coded value "username" flows to the $@ parameter in $@. | HardcodedCredentials.cs:33:19:33:28 | "username" | name | HardcodedCredentials.cs:31:31:45:13 | object creation of type MembershipUser | object creation of type MembershipUser | +| HardcodedCredentials.cs:47:39:47:53 | "myNewPa55word" | HardcodedCredentials.cs:47:39:47:53 | "myNewPa55word" | HardcodedCredentials.cs:47:39:47:53 | "myNewPa55word" | The hard-coded value "myNewPa55word" flows to the $@ parameter in $@. | HardcodedCredentials.cs:47:39:47:53 | "myNewPa55word" | newPassword | HardcodedCredentials.cs:47:9:47:54 | call to method ChangePassword | call to method ChangePassword | +| HardcodedCredentials.cs:49:30:49:60 | array creation of type Byte[] | HardcodedCredentials.cs:49:30:49:60 | array creation of type Byte[] | HardcodedCredentials.cs:52:13:52:23 | access to local variable rawCertData | This hard-coded value flows to the $@ parameter in $@. | HardcodedCredentials.cs:52:13:52:23 | access to local variable rawCertData | rawData | HardcodedCredentials.cs:51:33:53:25 | object creation of type X509Certificate2 | object creation of type X509Certificate2 | +| HardcodedCredentials.cs:53:13:53:24 | "myPa55word" | HardcodedCredentials.cs:53:13:53:24 | "myPa55word" | HardcodedCredentials.cs:53:13:53:24 | "myPa55word" | The hard-coded value "myPa55word" flows to the $@ parameter in $@. | HardcodedCredentials.cs:53:13:53:24 | "myPa55word" | password | HardcodedCredentials.cs:51:33:53:25 | object creation of type X509Certificate2 | object creation of type X509Certificate2 | +| HardcodedCredentials.cs:76:31:76:42 | "myusername" | HardcodedCredentials.cs:76:31:76:42 | "myusername" | HardcodedCredentials.cs:76:31:76:42 | "myusername" | The hard-coded value "myusername" flows to the $@ parameter in $@. | HardcodedCredentials.cs:76:31:76:42 | "myusername" | username | HardcodedCredentials.cs:76:9:76:57 | call to method CreateUser | call to method CreateUser | +| HardcodedCredentials.cs:76:45:76:56 | "mypassword" | HardcodedCredentials.cs:76:45:76:56 | "mypassword" | HardcodedCredentials.cs:76:45:76:56 | "mypassword" | The hard-coded value "mypassword" flows to the $@ parameter in $@. | HardcodedCredentials.cs:76:45:76:56 | "mypassword" | password | HardcodedCredentials.cs:76:9:76:57 | call to method CreateUser | call to method CreateUser | +| TestHardcodedCredentials.cs:26:19:26:28 | "username" | TestHardcodedCredentials.cs:26:19:26:28 | "username" | TestHardcodedCredentials.cs:26:19:26:28 | "username" | The hard-coded value "username" flows to the $@ parameter in $@. | TestHardcodedCredentials.cs:26:19:26:28 | "username" | name | TestHardcodedCredentials.cs:24:31:38:13 | object creation of type MembershipUser | object creation of type MembershipUser | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-807/ConditionalBypass.expected b/csharp/ql/test/query-tests/Security Features/CWE-807/ConditionalBypass.expected index af5a1417fa5..016f6b802df 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-807/ConditionalBypass.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-807/ConditionalBypass.expected @@ -1,8 +1,30 @@ -| ConditionalBypass.cs:19:13:19:33 | call to method login | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:18:13:18:30 | ... == ... | this condition | ConditionalBypass.cs:14:26:14:48 | access to property QueryString | user input | -| ConditionalBypass.cs:25:13:25:33 | call to method login | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:24:13:24:45 | call to method Equals | this condition | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | user input | -| ConditionalBypass.cs:31:13:31:33 | call to method login | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:29:13:29:40 | ... == ... | this condition | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | user input | -| ConditionalBypass.cs:35:13:35:39 | call to method reCheckAuth | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:29:13:29:40 | ... == ... | this condition | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | user input | -| ConditionalBypass.cs:48:13:48:33 | call to method login | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:46:13:46:46 | ... == ... | this condition | ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | user input | -| ConditionalBypass.cs:53:13:53:33 | call to method login | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:51:13:51:29 | access to property HostName | this condition | ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | user input | -| ConditionalBypass.cs:75:13:75:33 | call to method login | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:74:13:74:40 | ... == ... | this condition | ConditionalBypass.cs:72:34:72:52 | access to property Cookies | user input | -| ConditionalBypass.cs:87:13:87:33 | call to method login | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:86:13:86:40 | ... == ... | this condition | ConditionalBypass.cs:85:34:85:52 | access to property Cookies | user input | +edges +| ConditionalBypass.cs:14:26:14:48 | access to property QueryString | ConditionalBypass.cs:18:13:18:30 | ... == ... | +| ConditionalBypass.cs:21:34:21:52 | access to property Cookies | ConditionalBypass.cs:24:13:24:45 | call to method Equals | +| ConditionalBypass.cs:21:34:21:52 | access to property Cookies | ConditionalBypass.cs:29:13:29:40 | ... == ... | +| ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | ConditionalBypass.cs:46:13:46:46 | ... == ... | +| ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | ConditionalBypass.cs:51:13:51:29 | access to property HostName | +| ConditionalBypass.cs:72:34:72:52 | access to property Cookies | ConditionalBypass.cs:74:13:74:40 | ... == ... | +| ConditionalBypass.cs:85:34:85:52 | access to property Cookies | ConditionalBypass.cs:86:13:86:40 | ... == ... | +nodes +| ConditionalBypass.cs:14:26:14:48 | access to property QueryString | +| ConditionalBypass.cs:18:13:18:30 | ... == ... | +| ConditionalBypass.cs:21:34:21:52 | access to property Cookies | +| ConditionalBypass.cs:24:13:24:45 | call to method Equals | +| ConditionalBypass.cs:29:13:29:40 | ... == ... | +| ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | +| ConditionalBypass.cs:46:13:46:46 | ... == ... | +| ConditionalBypass.cs:51:13:51:29 | access to property HostName | +| ConditionalBypass.cs:72:34:72:52 | access to property Cookies | +| ConditionalBypass.cs:74:13:74:40 | ... == ... | +| ConditionalBypass.cs:85:34:85:52 | access to property Cookies | +| ConditionalBypass.cs:86:13:86:40 | ... == ... | +#select +| ConditionalBypass.cs:19:13:19:33 | call to method login | ConditionalBypass.cs:14:26:14:48 | access to property QueryString | ConditionalBypass.cs:18:13:18:30 | ... == ... | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:18:13:18:30 | ... == ... | this condition | ConditionalBypass.cs:14:26:14:48 | access to property QueryString | user input | +| ConditionalBypass.cs:25:13:25:33 | call to method login | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | ConditionalBypass.cs:24:13:24:45 | call to method Equals | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:24:13:24:45 | call to method Equals | this condition | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | user input | +| ConditionalBypass.cs:31:13:31:33 | call to method login | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | ConditionalBypass.cs:29:13:29:40 | ... == ... | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:29:13:29:40 | ... == ... | this condition | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | user input | +| ConditionalBypass.cs:35:13:35:39 | call to method reCheckAuth | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | ConditionalBypass.cs:29:13:29:40 | ... == ... | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:29:13:29:40 | ... == ... | this condition | ConditionalBypass.cs:21:34:21:52 | access to property Cookies | user input | +| ConditionalBypass.cs:48:13:48:33 | call to method login | ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | ConditionalBypass.cs:46:13:46:46 | ... == ... | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:46:13:46:46 | ... == ... | this condition | ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | user input | +| ConditionalBypass.cs:53:13:53:33 | call to method login | ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | ConditionalBypass.cs:51:13:51:29 | access to property HostName | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:51:13:51:29 | access to property HostName | this condition | ConditionalBypass.cs:44:32:44:66 | call to method GetHostByAddress | user input | +| ConditionalBypass.cs:75:13:75:33 | call to method login | ConditionalBypass.cs:72:34:72:52 | access to property Cookies | ConditionalBypass.cs:74:13:74:40 | ... == ... | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:74:13:74:40 | ... == ... | this condition | ConditionalBypass.cs:72:34:72:52 | access to property Cookies | user input | +| ConditionalBypass.cs:87:13:87:33 | call to method login | ConditionalBypass.cs:85:34:85:52 | access to property Cookies | ConditionalBypass.cs:86:13:86:40 | ... == ... | Sensitive method may not be executed depending on $@, which flows from $@. | ConditionalBypass.cs:86:13:86:40 | ... == ... | this condition | ConditionalBypass.cs:85:34:85:52 | access to property Cookies | user input | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-838/InappropriateEncoding.expected b/csharp/ql/test/query-tests/Security Features/CWE-838/InappropriateEncoding.expected index bd909a8d5cd..5f031e3db29 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-838/InappropriateEncoding.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-838/InappropriateEncoding.expected @@ -1,12 +1,45 @@ -| HtmlEncode.cs:12:28:12:65 | ... + ... | This HTML expression may include data from a $@. | HtmlEncode.cs:12:40:12:65 | call to method UrlEncode | possibly inappropriately encoded value | -| InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | This SQL expression may include data from a $@. | InappropriateEncoding.cs:15:28:15:40 | call to method Encode | possibly inappropriately encoded value | -| InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | This SQL expression may include data from a $@. | InappropriateEncoding.cs:68:16:68:42 | call to method Replace | possibly inappropriately encoded value | -| InappropriateEncoding.cs:33:22:33:34 | call to method Encode | This HTML expression may include data from a $@. | InappropriateEncoding.cs:33:22:33:34 | call to method Encode | possibly inappropriately encoded value | -| InappropriateEncoding.cs:34:22:34:49 | call to method UrlEncode | This HTML expression may include data from a $@. | InappropriateEncoding.cs:34:22:34:49 | call to method UrlEncode | possibly inappropriately encoded value | -| InappropriateEncoding.cs:35:22:35:73 | call to method UrlEncode | This HTML expression may include data from a $@. | InappropriateEncoding.cs:35:22:35:73 | call to method UrlEncode | possibly inappropriately encoded value | -| InappropriateEncoding.cs:37:32:37:43 | access to local variable encodedValue | This HTML expression may include data from a $@. | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | possibly inappropriately encoded value | -| InappropriateEncoding.cs:38:22:38:59 | ... + ... | This HTML expression may include data from a $@. | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | possibly inappropriately encoded value | -| InappropriateEncoding.cs:39:22:39:71 | call to method Format | This HTML expression may include data from a $@. | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | possibly inappropriately encoded value | -| InappropriateEncoding.cs:58:31:58:42 | access to local variable encodedValue | This URL expression may include data from a $@. | InappropriateEncoding.cs:57:28:57:56 | call to method HtmlEncode | possibly inappropriately encoded value | -| SqlEncode.cs:17:46:17:50 | access to local variable query | This SQL expression may include data from a $@. | SqlEncode.cs:16:62:16:87 | call to method Replace | possibly inappropriately encoded value | -| UrlEncode.cs:12:31:12:69 | ... + ... | This URL expression may include data from a $@. | UrlEncode.cs:12:43:12:69 | call to method HtmlEncode | possibly inappropriately encoded value | +edges +| HtmlEncode.cs:12:40:12:65 | call to method UrlEncode | HtmlEncode.cs:12:28:12:65 | ... + ... | +| InappropriateEncoding.cs:15:28:15:40 | call to method Encode | InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | +| InappropriateEncoding.cs:15:28:15:40 | call to method Encode | InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | +| InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | InappropriateEncoding.cs:37:32:37:43 | access to local variable encodedValue | +| InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | InappropriateEncoding.cs:38:22:38:59 | ... + ... | +| InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | InappropriateEncoding.cs:39:22:39:71 | call to method Format | +| InappropriateEncoding.cs:57:28:57:56 | call to method HtmlEncode | InappropriateEncoding.cs:58:31:58:42 | access to local variable encodedValue | +| InappropriateEncoding.cs:68:16:68:42 | call to method Replace | InappropriateEncoding.cs:15:28:15:40 | call to method Encode | +| SqlEncode.cs:16:62:16:87 | call to method Replace | SqlEncode.cs:17:46:17:50 | access to local variable query | +| UrlEncode.cs:12:43:12:69 | call to method HtmlEncode | UrlEncode.cs:12:31:12:69 | ... + ... | +nodes +| HtmlEncode.cs:12:28:12:65 | ... + ... | +| HtmlEncode.cs:12:40:12:65 | call to method UrlEncode | +| InappropriateEncoding.cs:15:28:15:40 | call to method Encode | +| InappropriateEncoding.cs:15:28:15:40 | call to method Encode | +| InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | +| InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | +| InappropriateEncoding.cs:33:22:33:34 | call to method Encode | +| InappropriateEncoding.cs:34:22:34:49 | call to method UrlEncode | +| InappropriateEncoding.cs:35:22:35:73 | call to method UrlEncode | +| InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | +| InappropriateEncoding.cs:37:32:37:43 | access to local variable encodedValue | +| InappropriateEncoding.cs:38:22:38:59 | ... + ... | +| InappropriateEncoding.cs:39:22:39:71 | call to method Format | +| InappropriateEncoding.cs:57:28:57:56 | call to method HtmlEncode | +| InappropriateEncoding.cs:58:31:58:42 | access to local variable encodedValue | +| InappropriateEncoding.cs:68:16:68:42 | call to method Replace | +| SqlEncode.cs:16:62:16:87 | call to method Replace | +| SqlEncode.cs:17:46:17:50 | access to local variable query | +| UrlEncode.cs:12:31:12:69 | ... + ... | +| UrlEncode.cs:12:43:12:69 | call to method HtmlEncode | +#select +| HtmlEncode.cs:12:28:12:65 | ... + ... | HtmlEncode.cs:12:40:12:65 | call to method UrlEncode | HtmlEncode.cs:12:28:12:65 | ... + ... | This HTML expression may include data from a $@. | HtmlEncode.cs:12:40:12:65 | call to method UrlEncode | possibly inappropriately encoded value | +| InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | InappropriateEncoding.cs:15:28:15:40 | call to method Encode | InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | This SQL expression may include data from a $@. | InappropriateEncoding.cs:15:28:15:40 | call to method Encode | possibly inappropriately encoded value | +| InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | InappropriateEncoding.cs:68:16:68:42 | call to method Replace | InappropriateEncoding.cs:20:46:20:51 | access to local variable query1 | This SQL expression may include data from a $@. | InappropriateEncoding.cs:68:16:68:42 | call to method Replace | possibly inappropriately encoded value | +| InappropriateEncoding.cs:33:22:33:34 | call to method Encode | InappropriateEncoding.cs:33:22:33:34 | call to method Encode | InappropriateEncoding.cs:33:22:33:34 | call to method Encode | This HTML expression may include data from a $@. | InappropriateEncoding.cs:33:22:33:34 | call to method Encode | possibly inappropriately encoded value | +| InappropriateEncoding.cs:34:22:34:49 | call to method UrlEncode | InappropriateEncoding.cs:34:22:34:49 | call to method UrlEncode | InappropriateEncoding.cs:34:22:34:49 | call to method UrlEncode | This HTML expression may include data from a $@. | InappropriateEncoding.cs:34:22:34:49 | call to method UrlEncode | possibly inappropriately encoded value | +| InappropriateEncoding.cs:35:22:35:73 | call to method UrlEncode | InappropriateEncoding.cs:35:22:35:73 | call to method UrlEncode | InappropriateEncoding.cs:35:22:35:73 | call to method UrlEncode | This HTML expression may include data from a $@. | InappropriateEncoding.cs:35:22:35:73 | call to method UrlEncode | possibly inappropriately encoded value | +| InappropriateEncoding.cs:37:32:37:43 | access to local variable encodedValue | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | InappropriateEncoding.cs:37:32:37:43 | access to local variable encodedValue | This HTML expression may include data from a $@. | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | possibly inappropriately encoded value | +| InappropriateEncoding.cs:38:22:38:59 | ... + ... | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | InappropriateEncoding.cs:38:22:38:59 | ... + ... | This HTML expression may include data from a $@. | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | possibly inappropriately encoded value | +| InappropriateEncoding.cs:39:22:39:71 | call to method Format | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | InappropriateEncoding.cs:39:22:39:71 | call to method Format | This HTML expression may include data from a $@. | InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | possibly inappropriately encoded value | +| InappropriateEncoding.cs:58:31:58:42 | access to local variable encodedValue | InappropriateEncoding.cs:57:28:57:56 | call to method HtmlEncode | InappropriateEncoding.cs:58:31:58:42 | access to local variable encodedValue | This URL expression may include data from a $@. | InappropriateEncoding.cs:57:28:57:56 | call to method HtmlEncode | possibly inappropriately encoded value | +| SqlEncode.cs:17:46:17:50 | access to local variable query | SqlEncode.cs:16:62:16:87 | call to method Replace | SqlEncode.cs:17:46:17:50 | access to local variable query | This SQL expression may include data from a $@. | SqlEncode.cs:16:62:16:87 | call to method Replace | possibly inappropriately encoded value | +| UrlEncode.cs:12:31:12:69 | ... + ... | UrlEncode.cs:12:43:12:69 | call to method HtmlEncode | UrlEncode.cs:12:31:12:69 | ... + ... | This URL expression may include data from a $@. | UrlEncode.cs:12:43:12:69 | call to method HtmlEncode | possibly inappropriately encoded value | diff --git a/java/ql/src/Metrics/History/HChurn.ql b/java/ql/src/Metrics/History/HChurn.ql index 59cc7c8e634..dda841556f8 100644 --- a/java/ql/src/Metrics/History/HChurn.ql +++ b/java/ql/src/Metrics/History/HChurn.ql @@ -6,6 +6,7 @@ * @metricType file * @metricAggregate avg sum max * @id java/vcs/churn-per-file + * @deprecated */ import java diff --git a/java/ql/src/Metrics/History/HLinesAdded.ql b/java/ql/src/Metrics/History/HLinesAdded.ql index 4aa6adc74bd..e04fef82820 100644 --- a/java/ql/src/Metrics/History/HLinesAdded.ql +++ b/java/ql/src/Metrics/History/HLinesAdded.ql @@ -6,6 +6,7 @@ * @metricType file * @metricAggregate avg sum max * @id java/vcs/added-lines-per-file + * @deprecated */ import java diff --git a/java/ql/src/Metrics/History/HLinesDeleted.ql b/java/ql/src/Metrics/History/HLinesDeleted.ql index 4e476da307c..d0e923f9be7 100644 --- a/java/ql/src/Metrics/History/HLinesDeleted.ql +++ b/java/ql/src/Metrics/History/HLinesDeleted.ql @@ -6,6 +6,7 @@ * @metricType file * @metricAggregate avg sum max * @id java/vcs/deleted-lines-per-file + * @deprecated */ import java diff --git a/java/ql/src/Metrics/History/HNumberOfAuthors.ql b/java/ql/src/Metrics/History/HNumberOfAuthors.ql index fef9bc3cfdf..895eea57e8d 100644 --- a/java/ql/src/Metrics/History/HNumberOfAuthors.ql +++ b/java/ql/src/Metrics/History/HNumberOfAuthors.ql @@ -6,6 +6,7 @@ * @metricType file * @metricAggregate avg min max * @id java/vcs/authors-per-file + * @deprecated */ import java diff --git a/java/ql/src/Metrics/History/HNumberOfChanges.ql b/java/ql/src/Metrics/History/HNumberOfChanges.ql index 5209ebd7af7..c8f3a085b81 100644 --- a/java/ql/src/Metrics/History/HNumberOfChanges.ql +++ b/java/ql/src/Metrics/History/HNumberOfChanges.ql @@ -6,6 +6,7 @@ * @metricType file * @metricAggregate avg min max sum * @id java/vcs/commits-per-file + * @deprecated */ import java diff --git a/java/ql/src/Metrics/History/HNumberOfRecentChanges.ql b/java/ql/src/Metrics/History/HNumberOfRecentChanges.ql index e5006895faf..772470fe04c 100644 --- a/java/ql/src/Metrics/History/HNumberOfRecentChanges.ql +++ b/java/ql/src/Metrics/History/HNumberOfRecentChanges.ql @@ -6,6 +6,7 @@ * @metricType file * @metricAggregate avg min max sum * @id java/vcs/recent-commits-per-file + * @deprecated */ import java diff --git a/java/ql/src/filters/RecentDefects.ql b/java/ql/src/filters/RecentDefects.ql index 573ca6f5448..d52a79d0f0a 100644 --- a/java/ql/src/filters/RecentDefects.ql +++ b/java/ql/src/filters/RecentDefects.ql @@ -3,6 +3,7 @@ * @description Filter a defect query to only include results in files that have been changed recently, and modify the message. * @kind problem * @id java/recently-changed-file-filter + * @deprecated */ import java diff --git a/java/ql/src/filters/RecentDefectsForMetric.ql b/java/ql/src/filters/RecentDefectsForMetric.ql index 3587ea20d7b..8414508b1c0 100644 --- a/java/ql/src/filters/RecentDefectsForMetric.ql +++ b/java/ql/src/filters/RecentDefectsForMetric.ql @@ -3,6 +3,7 @@ * @description Filter a metric query to only include results in files that have been changed recently, and modify the message. * @kind treemap * @id java/recently-changed-file-metric-filter + * @deprecated */ import java diff --git a/javascript/extractor/lib/typescript/src/ast_extractor.ts b/javascript/extractor/lib/typescript/src/ast_extractor.ts index e69714dd580..3264abcb368 100644 --- a/javascript/extractor/lib/typescript/src/ast_extractor.ts +++ b/javascript/extractor/lib/typescript/src/ast_extractor.ts @@ -9,6 +9,7 @@ export interface AugmentedSourceFile extends ts.SourceFile { parseDiagnostics?: any[]; $tokens?: Token[]; $symbol?: number; + $lineStarts?: ReadonlyArray; } export interface AugmentedNode extends ts.Node { @@ -21,9 +22,7 @@ export interface AugmentedNode extends ts.Node { $overloadIndex?: number; } -export interface AugmentedPos extends ts.LineAndCharacter { - $offset?: number; -} +export type AugmentedPos = number; export interface Token { kind: ts.SyntaxKind; @@ -66,8 +65,10 @@ function forEachNode(ast: ts.Node, callback: (node: ts.Node) => void) { } export function augmentAst(ast: AugmentedSourceFile, code: string, project: Project | null) { + ast.$lineStarts = ast.getLineStarts(); + /** - * Converts a numeric offset to a position object with line and column information. + * Converts a numeric offset to the value expected by the Java counterpart of the extractor. */ function augmentPos(pos: number, shouldSkipWhitespace?: boolean): AugmentedPos { // skip over leading spaces/comments @@ -75,9 +76,7 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj skipWhiteSpace.lastIndex = pos; pos += skipWhiteSpace.exec(code)[0].length; } - let posObject: AugmentedPos = ast.getLineAndCharacterOfPosition(pos); - posObject.$offset = pos; - return posObject; + return pos; } // Find the position of all tokens where the scanner requires parse-tree information. diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index ad257458996..68e05e46eb4 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -111,7 +111,7 @@ import com.semmle.util.trap.TrapWriter; * *

* The filtering phase is parameterised by a list of include/exclude patterns in the style of - * {@link ProjectLayout} specifications. There are some built-in include patterns discussed + * {@link ProjectLayout} specifications. There are some built-in include/exclude patterns discussed * below. Additionally, the environment variable LGTM_INDEX_FILTERS is interpreted * as a newline-separated list of patterns to append to that list (hence taking precedence over * the built-in patterns). Unlike for {@link ProjectLayout}, patterns in @@ -140,6 +140,15 @@ import com.semmle.util.trap.TrapWriter; *

* *

+ * The default exclusion patterns cause the following files to be excluded: + *

+ *
    + *
  • All JavaScript files whose name ends with -min.js or .min.js. + * Such files typically contain minified code. Since LGTM by default does not show results + * in minified files, it is not usually worth extracting them in the first place.
  • + *
+ * + *

* JavaScript files are normally extracted with {@link SourceType#AUTO}, but an explicit * source type can be specified in the environment variable LGTM_INDEX_SOURCE_TYPE. *

@@ -317,6 +326,10 @@ public class AutoBuild { patterns.add("**/.eslintrc*"); patterns.add("**/package.json"); + // exclude files whose name strongly suggests they are minified + patterns.add("-**/*.min.js"); + patterns.add("-**/*-min.js"); + String base = LGTM_SRC.toString().replace('\\', '/'); // process `$LGTM_INDEX_FILTERS` for (String pattern : Main.NEWLINE.split(getEnvVar("LGTM_INDEX_FILTERS", ""))) { diff --git a/javascript/extractor/src/com/semmle/js/extractor/test/AutoBuildTests.java b/javascript/extractor/src/com/semmle/js/extractor/test/AutoBuildTests.java index 7969c093f4e..300fa708289 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/test/AutoBuildTests.java +++ b/javascript/extractor/src/com/semmle/js/extractor/test/AutoBuildTests.java @@ -433,4 +433,23 @@ public class AutoBuildTests { addFile(true, LGTM_SRC, "tst.js"); runTest(); } + + @Test + public void minifiedFilesAreExcluded() throws IOException { + addFile(true, LGTM_SRC, "admin.js"); + addFile(false, LGTM_SRC, "jquery.min.js"); + addFile(false, LGTM_SRC, "lib", "lodash-min.js"); + addFile(true, LGTM_SRC, "compute_min.js"); + runTest(); + } + + @Test + public void minifiedFilesCanBeReIncluded() throws IOException { + envVars.put("LGTM_INDEX_FILTERS", "include:**/*.min.js\ninclude:**/*-min.js"); + addFile(true, LGTM_SRC, "admin.js"); + addFile(true, LGTM_SRC, "jquery.min.js"); + addFile(true, LGTM_SRC, "lib", "lodash-min.js"); + addFile(true, LGTM_SRC, "compute_min.js"); + runTest(); + } } diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java index 42c6fb11bec..c462686ea90 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java @@ -162,6 +162,7 @@ public class TypeScriptASTConverter { private final JsonObject syntaxKinds; private final Map nodeFlagMap = new LinkedHashMap<>(); private final Map syntaxKindMap = new LinkedHashMap<>(); + private int[] lineStarts; private int syntaxKindExtends; @@ -199,6 +200,8 @@ public class TypeScriptASTConverter { * into a parser {@link Result}. */ public Result convertAST(JsonObject ast, String source) { + this.lineStarts = toIntArray(ast.getAsJsonArray("$lineStarts")); + List errors = new ArrayList(); // process parse diagnostics (i.e., syntax errors) reported by the TypeScript compiler @@ -207,11 +210,8 @@ public class TypeScriptASTConverter { for (JsonElement elt : parseDiagnostics) { JsonObject parseDiagnostic = elt.getAsJsonObject(); String message = parseDiagnostic.get("messageText").getAsString(); - JsonObject pos = parseDiagnostic.get("$pos").getAsJsonObject(); - int line = pos.get("line").getAsInt() + 1; - int column = pos.get("character").getAsInt(); - int offset = pos.get("$offset").getAsInt(); - errors.add(new ParseError(message, line, column, offset)); + Position pos = getPosition(parseDiagnostic.get("$pos")); + errors.add(new ParseError(message, pos.getLine(), pos.getColumn(), pos.getOffset())); } return new Result(source, null, new ArrayList<>(), new ArrayList<>(), errors); } @@ -231,6 +231,36 @@ public class TypeScriptASTConverter { return new Result(source, converted, tokens, comments, errors); } + /** + * Converts a JSON array to an int array. + * The array is assumed to only contain integers. + */ + private static int[] toIntArray(JsonArray array) { + int[] result = new int[array.size()]; + for (int i = 0; i < array.size(); ++i) { + result[i] = array.get(i).getAsInt(); + } + return result; + } + + private int getLineFromPos(int pos) { + int low = 0, high = this.lineStarts.length - 1; + while (low < high) { + int mid = high - ((high - low) >> 1); // Get middle, rounding up. + int startOfLine = lineStarts[mid]; + if (startOfLine <= pos) { + low = mid; + } else { + high = mid - 1; + } + } + return low; + } + + private int getColumnFromLinePos(int line, int pos) { + return pos - lineStarts[line]; + } + /** * Extract tokens and comments from the given TypeScript AST. */ @@ -238,7 +268,7 @@ public class TypeScriptASTConverter { for (JsonElement elt : ast.get("$tokens").getAsJsonArray()) { JsonObject token = elt.getAsJsonObject(); String text = token.get("text").getAsString(); - Position start = getPosition(token.get("tokenPos").getAsJsonObject(), true); + Position start = getPosition(token.get("tokenPos")); Position end = advance(start, text); SourceLocation loc = new SourceLocation(text, start, end); String kind = getKind(token); @@ -886,7 +916,7 @@ public class TypeScriptASTConverter { } else { superInterfaces = convertSuperInterfaceClause(supers); } - afterHead = heritageClause.get("$end").getAsJsonObject().get("$offset").getAsInt(); + afterHead = heritageClause.get("$end").getAsInt(); } if (superInterfaces == null) { superInterfaces = new ArrayList<>(); @@ -2191,8 +2221,8 @@ public class TypeScriptASTConverter { * Get the source location of the given AST node. */ private SourceLocation getSourceLocation(JsonObject node) { - Position start = getPosition(node.get("$pos").getAsJsonObject(), true); - Position end = getPosition(node.get("$end").getAsJsonObject(), false); + Position start = getPosition(node.get("$pos")); + Position end = getPosition(node.get("$end")); int startOffset = start.getOffset(); int endOffset = end.getOffset(); if (startOffset > endOffset) @@ -2207,15 +2237,11 @@ public class TypeScriptASTConverter { * For start positions, we need to skip over whitespace, which is included in * the positions reported by the TypeScript compiler. */ - private Position getPosition(JsonObject pos, boolean isStart) { - int line = pos.get("line").getAsInt() + 1; - int column = pos.get("character").getAsInt(); - int offset = pos.get("$offset").getAsInt(); - if (isStart) { - while (offset < source.length() && Character.isWhitespace(source.charAt(offset))) - ++offset; - } - return new Position(line, column, offset); + private Position getPosition(JsonElement elm) { + int offset = elm.getAsInt(); + int line = getLineFromPos(offset); + int column = getColumnFromLinePos(line, offset); + return new Position(line + 1, column, offset); } private Iterable getModifiers(JsonObject node) { diff --git a/javascript/ql/src/DOM/AmbiguousIdAttribute.ql b/javascript/ql/src/DOM/AmbiguousIdAttribute.ql index 8e9e7a6a2f7..f0304515731 100644 --- a/javascript/ql/src/DOM/AmbiguousIdAttribute.ql +++ b/javascript/ql/src/DOM/AmbiguousIdAttribute.ql @@ -4,7 +4,7 @@ * same id attribute, it may be interpreted differently * by different browsers. * @kind problem - * @problem.severity error + * @problem.severity warning * @id js/duplicate-html-id * @tags maintainability * correctness diff --git a/javascript/ql/src/DOM/ConflictingAttributes.ql b/javascript/ql/src/DOM/ConflictingAttributes.ql index e0f2094899f..9e4cf1cdccd 100644 --- a/javascript/ql/src/DOM/ConflictingAttributes.ql +++ b/javascript/ql/src/DOM/ConflictingAttributes.ql @@ -3,7 +3,7 @@ * @description If an HTML element has two attributes with the same name * but different values, its behavior may be browser-dependent. * @kind problem - * @problem.severity error + * @problem.severity warning * @id js/conflicting-html-attribute * @tags maintainability * correctness diff --git a/javascript/ql/src/DOM/TargetBlank.ql b/javascript/ql/src/DOM/TargetBlank.ql index a59954a6aba..cc48d548074 100644 --- a/javascript/ql/src/DOM/TargetBlank.ql +++ b/javascript/ql/src/DOM/TargetBlank.ql @@ -13,6 +13,7 @@ import javascript import semmle.javascript.frameworks.Templating +import semmle.javascript.RestrictedLocations /** * Holds if the href attribute contains a host that we cannot determine statically. @@ -53,4 +54,4 @@ where // `e` is a link that opens in a new browsing context (that is, it has `ta not exists (DOM::AttributeDefinition attr | attr = e.getAnAttribute() | not exists(attr.getName()) ) -select e, "External links without noopener/noreferrer are a potential security risk." +select (FirstLineOf)e, "External links without noopener/noreferrer are a potential security risk." diff --git a/javascript/ql/src/Declarations/MissingThisQualifier.ql b/javascript/ql/src/Declarations/MissingThisQualifier.ql index e6218a4a0d4..9a57ec987f8 100644 --- a/javascript/ql/src/Declarations/MissingThisQualifier.ql +++ b/javascript/ql/src/Declarations/MissingThisQualifier.ql @@ -50,5 +50,14 @@ where maybeMissingThis(call, intendedTarget, gv) decl.isNamespaceExport() and call.getContainer().getEnclosingContainer*() instanceof NamespaceDeclaration ) + or + // call to global function with additional arguments + exists (Function self | + intendedTarget.getBody() = self and + call.getEnclosingFunction() = self and + call.flow().(DataFlow::CallNode).getNumArgument() > self.getNumParameter() and + not self.hasRestParameter() and + not self.usesArgumentsObject() + ) ) select call, "This call refers to a global function, and not the local method $@.", intendedTarget, intendedTarget.getName() diff --git a/javascript/ql/src/Declarations/MissingVarDecl.ql b/javascript/ql/src/Declarations/MissingVarDecl.ql index 8bc0cf92d0a..4a180408cb5 100644 --- a/javascript/ql/src/Declarations/MissingVarDecl.ql +++ b/javascript/ql/src/Declarations/MissingVarDecl.ql @@ -3,7 +3,7 @@ * @description If a variable is not declared as a local variable, it becomes a global variable * by default, which may be unintentional and could lead to unexpected behavior. * @kind problem - * @problem.severity error + * @problem.severity warning * @id js/missing-variable-declaration * @tags reliability * maintainability diff --git a/javascript/ql/src/Declarations/MixedStaticInstanceThisAccess.ql b/javascript/ql/src/Declarations/MixedStaticInstanceThisAccess.ql index 8ba3de13a3a..bd7d8fe9f14 100644 --- a/javascript/ql/src/Declarations/MixedStaticInstanceThisAccess.ql +++ b/javascript/ql/src/Declarations/MixedStaticInstanceThisAccess.ql @@ -10,15 +10,19 @@ */ import javascript +/** Holds if `base` declares or inherits method `m` with the given `name`. */ +predicate hasMethod(ClassDefinition base, string name, MethodDefinition m) { + m = base.getMethod(name) or + hasMethod(base.getSuperClassDefinition(), name, m) +} /** * Holds if `access` is in`fromMethod`, and it references `toMethod` through `this`. */ predicate isLocalMethodAccess(PropAccess access, MethodDefinition fromMethod, MethodDefinition toMethod) { - fromMethod.getDeclaringClass() = toMethod.getDeclaringClass() and + hasMethod(fromMethod.getDeclaringClass(), access.getPropertyName(), toMethod) and access.getEnclosingFunction() = fromMethod.getBody() and - access.getBase() instanceof ThisExpr and - access.getPropertyName() = toMethod.getName() + access.getBase() instanceof ThisExpr } string getKind(MethodDefinition m) { diff --git a/javascript/ql/src/Expressions/DuplicateCondition.ql b/javascript/ql/src/Expressions/DuplicateCondition.ql index 8eb5d606aba..02872ae16dc 100644 --- a/javascript/ql/src/Expressions/DuplicateCondition.ql +++ b/javascript/ql/src/Expressions/DuplicateCondition.ql @@ -3,7 +3,7 @@ * @description If two conditions in an 'if'-'else if' chain are identical, the * second condition will never hold. * @kind problem - * @problem.severity error + * @problem.severity warning * @id js/duplicate-condition * @tags maintainability * correctness diff --git a/javascript/ql/src/Expressions/DuplicateSwitchCase.ql b/javascript/ql/src/Expressions/DuplicateSwitchCase.ql index 1361c60b6e6..57a04fcaf3e 100644 --- a/javascript/ql/src/Expressions/DuplicateSwitchCase.ql +++ b/javascript/ql/src/Expressions/DuplicateSwitchCase.ql @@ -3,7 +3,7 @@ * @description If two cases in a switch statement have the same label, the second case * will never be executed. * @kind problem - * @problem.severity error + * @problem.severity warning * @id js/duplicate-switch-case * @tags maintainability * correctness diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.actual b/javascript/ql/src/Security/CWE-089/SqlInjection.actual deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/javascript/ql/src/semmle/javascript/Classes.qll b/javascript/ql/src/semmle/javascript/Classes.qll index 637f828beff..cfdb16b76cf 100644 --- a/javascript/ql/src/semmle/javascript/Classes.qll +++ b/javascript/ql/src/semmle/javascript/Classes.qll @@ -216,6 +216,13 @@ class ClassDefinition extends @classdefinition, ClassOrInterface, AST::ValueNode ) } + /** + * Gets the definition of the super class of this class, if it can be determined. + */ + ClassDefinition getSuperClassDefinition() { + result = getSuperClass().analyze().getAValue().(AbstractClass).getClass() + } + } /** diff --git a/javascript/ql/src/semmle/javascript/Stmt.qll b/javascript/ql/src/semmle/javascript/Stmt.qll index 486298a3896..e076011ee44 100644 --- a/javascript/ql/src/semmle/javascript/Stmt.qll +++ b/javascript/ql/src/semmle/javascript/Stmt.qll @@ -224,6 +224,12 @@ class NgInjectDirective extends KnownDirective { NgInjectDirective() { getDirectiveText().regexpMatch("ng(No)?Inject") } } +/** A YUI compressor directive. */ +class YuiDirective extends KnownDirective { + YuiDirective() { + getDirectiveText().regexpMatch("([a-z0-9_]+:nomunge, ?)*([a-z0-9_]+:nomunge)") + } +} /** A SystemJS `deps` directive. */ class SystemJSDepsDirective extends KnownDirective { diff --git a/javascript/ql/src/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll b/javascript/ql/src/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll new file mode 100644 index 00000000000..0a069dbd87c --- /dev/null +++ b/javascript/ql/src/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll @@ -0,0 +1,158 @@ +/** + * Provides classes for working with analysis-specific abstract values. + * + * Implement a subclass of `CustomAbstractValueDefinition` when the builtin + * abstract values of `AbstractValues.qll` are not expressive enough. + * + * For performance reasons, all subclasses of `CustomAbstractValueDefinition` + * should be part of the standard library. + */ + +import javascript +private import internal.AbstractValuesImpl +private import InferredTypes + +/** + * An abstract representation of an analysis-specific value. + * + * Wraps a `CustomAbstractValueDefinition`. + */ +class CustomAbstractValueFromDefinition extends AbstractValue, TCustomAbstractValueFromDefinition { + + CustomAbstractValueDefinition def; + + CustomAbstractValueFromDefinition() { + this = TCustomAbstractValueFromDefinition(def) + } + + override InferredType getType() { + result = def.getType() + } + + override boolean getBooleanValue() { + result = def.getBooleanValue() + } + + override PrimitiveAbstractValue toPrimitive() { + result = def.toPrimitive() + } + + override predicate isCoercibleToNumber() { + def.isCoercibleToNumber() + } + + override predicate isIndefinite(DataFlow::Incompleteness cause) { + def.isIndefinite(cause) + } + + override DefiniteAbstractValue getAPrototype() { + result = def.getAPrototype() + } + + override predicate hasLocationInfo(string f, int startline, int startcolumn, int endline, int endcolumn) { + def.getLocation().hasLocationInfo(f, startline, startcolumn, endline, endcolumn) + } + + override string toString() { + result = def.toString() + } + + /** + * Gets the definition that induces this value. + */ + CustomAbstractValueDefinition getDefinition() { + result = def + } + + /** Holds if this is a value whose properties the type inference tracks. */ + predicate shouldTrackProperties() { + def.shouldTrackProperties() + } + +} + +/** + * A data-flow node that induces an analysis-specific abstract value. + * + * Enables modular extensions of `AbstractValue`. + * + * For performance reasons, all subclasses of this class should be part + * of the standard library. + */ +abstract class CustomAbstractValueDefinition extends Locatable { + + /** + * Gets the type of some concrete value represented by the induced + * abstract value. + */ + abstract InferredType getType(); + + /** + * Gets the Boolean value that some concrete value represented by the + * induced abstract value coerces to. + */ + abstract boolean getBooleanValue(); + + /** + * Gets an abstract primitive value the induced abstract value coerces + * to. + * + * This abstractly models the `ToPrimitive` coercion described in the + * ECMAScript language specification. + */ + abstract PrimitiveAbstractValue toPrimitive(); + + /** + * Holds if the induced abstract value is coercible to a number, that + * is, it represents at least one concrete value for which the + * `ToNumber` conversion does not yield `NaN`. + */ + abstract predicate isCoercibleToNumber(); + + /** + * Holds if the induced abstract value is an indefinite value arising + * from the incompleteness `cause`. + */ + predicate isIndefinite(DataFlow::Incompleteness cause) { + none() + } + + /** + * Gets an abstract value that represents a prototype object of the + * induced abstract value. + */ + AbstractValue getAPrototype() { + exists (AbstractProtoProperty proto | + proto.getBase() = getAbstractValue() and + result = proto.getAValue() + ) + } + + /** + * Gets the induced abstract value. + */ + AbstractValue getAbstractValue() { + result.(CustomAbstractValueFromDefinition).getDefinition() = this + } + + /** Holds if this is a value whose properties the type inference tracks. */ + abstract predicate shouldTrackProperties(); + +} + +/** + * Flow analysis for custom abstract values. + */ +class CustomAbstractValueFromDefinitionNode extends DataFlow::AnalyzedNode, DataFlow::ValueNode { + + CustomAbstractValueFromDefinition val; + + CustomAbstractValueFromDefinitionNode() { + val = TCustomAbstractValueFromDefinition(this.getAstNode()) + } + + override AbstractValue getALocalValue() { + result = val + } + +} \ No newline at end of file diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll index bcf572aae61..c82d0e42dbb 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll @@ -77,5 +77,6 @@ predicate shouldAlwaysTrackProperties(AbstractValue baseVal) { predicate shouldTrackProperties(AbstractValue baseVal) { shouldAlwaysTrackProperties(baseVal) or baseVal instanceof AbstractObjectLiteral or - baseVal instanceof AbstractInstance + baseVal instanceof AbstractInstance or + baseVal.(CustomAbstractValueFromDefinition).shouldTrackProperties() } diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll index bd6c7ea996e..36a22a95f09 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll @@ -6,6 +6,7 @@ import semmle.javascript.dataflow.AbstractValues private import semmle.javascript.dataflow.InferredTypes +import semmle.javascript.dataflow.CustomAbstractValueDefinitions /** An abstract value inferred by the flow analysis. */ cached newtype TAbstractValue = @@ -101,6 +102,9 @@ cached newtype TAbstractValue = or /** A custom abstract value induced by `tag`. */ TCustomAbstractValue(CustomAbstractValueTag tag) + or + /** A custom abstract value induced by `def`. */ + TCustomAbstractValueFromDefinition(CustomAbstractValueDefinition def) /** * Gets a definite abstract value with the given type. diff --git a/javascript/ql/src/semmle/javascript/linters/JSLint.qll b/javascript/ql/src/semmle/javascript/linters/JSLint.qll index 1cf6730ab18..136122f01bd 100644 --- a/javascript/ql/src/semmle/javascript/linters/JSLint.qll +++ b/javascript/ql/src/semmle/javascript/linters/JSLint.qll @@ -9,6 +9,11 @@ private string getDirectiveName(SlashStarComment c) { result = c.getText().regexpCapture("(?s)\\s*(\\w+)\\b.*", 1) } +/** Gets a function at the specified location. */ +private Function getFunctionAt(string filepath, int startline, int startcolumn, int endline, int endcolumn) { + result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) +} + /** A JSLint directive. */ abstract class JSLintDirective extends SlashStarComment { /** @@ -36,7 +41,7 @@ abstract class JSLintDirective extends SlashStarComment { private Function getASurroundingFunction() { exists (string path, int fsl, int fsc, int fel, int fec, int dsl, int dsc, int del, int dec | - result.getLocation().hasLocationInfo(path, fsl, fsc, fel, fec) and + result = getFunctionAt(path, fsl, fsc, fel, fec) and this.getLocation().hasLocationInfo(path, dsl, dsc, del, dec) | // the function starts before this directive (fsl < dsl or (fsl = dsl and fsc <= dsc)) @@ -96,6 +101,11 @@ abstract class JSLintGlobal extends Linting::GlobalDeclaration, JSLintDirective override predicate appliesTo(ExprOrStmt s) { JSLintDirective.super.appliesTo(s) } + + override predicate declaresGlobalForAccess(GlobalVarAccess gva) { + declaresGlobal(gva.getName(), _) and + getScope() = gva.getContainer().getEnclosingContainer*() + } } /** A JSLint `global` directive. */ diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll index a0987cc21ef..7ab3b0689c2 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll @@ -52,7 +52,7 @@ module CleartextLogging { } override predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) { - any (TaintTracking::StringConcatenationTaintStep s).step(src, trg) + StringConcatenation::taintStep(src, trg) or exists (string name | name = "toString" or name = "valueOf" | src.(DataFlow::SourceNode).getAMethodCall(name) = trg diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.expected b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.expected new file mode 100644 index 00000000000..e7d73ca3b88 --- /dev/null +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.expected @@ -0,0 +1,2 @@ +| tst.js:4:16:4:50 | { custo ... false } | tst.js:4:16:4:50 | { custo ... false } | false | false | +| tst.js:5:16:5:49 | { custo ... true } | tst.js:5:16:5:49 | { custo ... true } | false | true | diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql new file mode 100644 index 00000000000..810cd457d05 --- /dev/null +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql @@ -0,0 +1,57 @@ +import javascript +import semmle.javascript.dataflow.InferredTypes +import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps +import semmle.javascript.dataflow.internal.AbstractPropertiesImpl as AbstractPropertiesImpl +import semmle.javascript.dataflow.CustomAbstractValueDefinitions + +class MyCustomAbstractValueDefinition extends CustomAbstractValueDefinition { + + DataFlow::ValueNode node; + + MyCustomAbstractValueDefinition() { + DataFlow::valueNode(this) = node and + node instanceof DataFlow::ObjectLiteralNode and + exists (DataFlow::PropWrite pwn | + pwn.writes(node, "custom", any(BooleanLiteral l | l.getValue() = "true").flow()) + ) + } + + override boolean getBooleanValue() { + result = true + } + + override predicate isCoercibleToNumber() { + none() + } + + override PrimitiveAbstractValue toPrimitive() { + result = TAbstractOtherString() + } + + override InferredType getType() { result = TTObject() } + + override predicate shouldTrackProperties() { + exists (DataFlow::PropWrite pwn | + pwn.writes(node, "trackProps", any(BooleanLiteral l | l.getValue() = "true").flow()) + ) + } + +} + +boolean flowProps(AbstractValue val) { + if FlowSteps::shouldTrackProperties(val) then + result = true + else + result = false +} + +boolean typeProps(AbstractValue val) { + if AbstractPropertiesImpl::shouldTrackProperties(val) then + result = true + else + result = false +} + +from MyCustomAbstractValueDefinition def, AbstractValue val +where def.getAbstractValue() = val +select def, val, flowProps(val), typeProps(val) diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.expected b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.expected new file mode 100644 index 00000000000..e75af733c53 --- /dev/null +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.expected @@ -0,0 +1,8 @@ +| tst.js:4:16:4:50 | { custo ... false } | tst.js:4:16:4:50 | { custo ... false } | +| tst.js:5:16:5:49 | { custo ... true } | tst.js:5:16:5:49 | { custo ... true } | +| tst.js:15:9:15:21 | result = obj3 | tst.js:4:16:4:50 | { custo ... false } | +| tst.js:15:18:15:21 | obj3 | tst.js:4:16:4:50 | { custo ... false } | +| tst.js:18:9:18:21 | result = obj4 | tst.js:5:16:5:49 | { custo ... true } | +| tst.js:18:18:18:21 | obj4 | tst.js:5:16:5:49 | { custo ... true } | +| tst.js:21:5:21:10 | result | tst.js:4:16:4:50 | { custo ... false } | +| tst.js:21:5:21:10 | result | tst.js:5:16:5:49 | { custo ... true } | diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql new file mode 100644 index 00000000000..0d8eb67043d --- /dev/null +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql @@ -0,0 +1,40 @@ +import javascript +import semmle.javascript.dataflow.InferredTypes +import semmle.javascript.dataflow.CustomAbstractValueDefinitions + +class MyCustomAbstractValueDefinition extends CustomAbstractValueDefinition { + + DataFlow::ValueNode node; + + MyCustomAbstractValueDefinition() { + DataFlow::valueNode(this) = node and + node instanceof DataFlow::ObjectLiteralNode and + exists (DataFlow::PropWrite pwn | + pwn.writes(node, "custom", any(BooleanLiteral l | l.getValue() = "true").flow()) + ) + } + + override boolean getBooleanValue() { + result = true + } + + override predicate isCoercibleToNumber() { + none() + } + + override PrimitiveAbstractValue toPrimitive() { + result = TAbstractOtherString() + } + + override InferredType getType() { result = TTObject() } + + override predicate shouldTrackProperties() { + none() + } + +} + +from AnalyzedValueNode n, MyCustomAbstractValueDefinition def, CustomAbstractValueFromDefinition val +where def.getAbstractValue() = val and + n.getAValue() = val +select n, val \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/tst.js b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/tst.js new file mode 100644 index 00000000000..f89eaba4854 --- /dev/null +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/tst.js @@ -0,0 +1,22 @@ +(function() { + var obj1 = { custom: false, trackProps: false }; + var obj2 = { custom: false, trackProps: true }; + var obj3 = { custom: true, trackProps: false }; + var obj4 = { custom: true, trackProps: true }; + + var result; + if (x1) { + result = obj1; + } + if (x2) { + result = obj2; + } + if (x3) { + result = obj3; + } + if (x4) { + result = obj4; + } + + result; +})(); diff --git a/javascript/ql/test/query-tests/DOM/TargetBlank/TargetBlank.expected b/javascript/ql/test/query-tests/DOM/TargetBlank/TargetBlank.expected index 44418490bda..6f0af3473f2 100644 --- a/javascript/ql/test/query-tests/DOM/TargetBlank/TargetBlank.expected +++ b/javascript/ql/test/query-tests/DOM/TargetBlank/TargetBlank.expected @@ -1,3 +1,6 @@ +| tst.html:23:1:23:61 | ... | External links without noopener/noreferrer are a potential security risk. | +| tst.html:24:1:24:48 | ... | External links without noopener/noreferrer are a potential security risk. | +| tst.html:25:1:25:36 | ... | External links without noopener/noreferrer are a potential security risk. | | tst.js:18:1:18:43 | | External links without noopener/noreferrer are a potential security risk. | | tst.js:19:1:19:58 | | External links without noopener/noreferrer are a potential security risk. | | tst.js:20:1:20:51 | | External links without noopener/noreferrer are a potential security risk. | diff --git a/javascript/ql/test/query-tests/DOM/TargetBlank/tst.html b/javascript/ql/test/query-tests/DOM/TargetBlank/tst.html index 1a16fb7d786..ded63fefde7 100644 --- a/javascript/ql/test/query-tests/DOM/TargetBlank/tst.html +++ b/javascript/ql/test/query-tests/DOM/TargetBlank/tst.html @@ -14,10 +14,17 @@ Example Example -

NOT OK, because of dynamic URL

+

OK, because of constant prefix

Example Example Example +

NOT OK, because of dynamic URL

+Example +Example + + Example + + diff --git a/javascript/ql/test/query-tests/Declarations/MissingThisQualifier/MissingThisQualifier.expected b/javascript/ql/test/query-tests/Declarations/MissingThisQualifier/MissingThisQualifier.expected index 37122e8266b..c9bd449006f 100644 --- a/javascript/ql/test/query-tests/Declarations/MissingThisQualifier/MissingThisQualifier.expected +++ b/javascript/ql/test/query-tests/Declarations/MissingThisQualifier/MissingThisQualifier.expected @@ -1,4 +1,5 @@ | abstract-missing.ts:3:5:3:24 | setAudioProperties() | This call refers to a global function, and not the local method $@. | abstract-missing.ts:6:3:6:32 | abstrac ... ties(); | setAudioProperties | +| indirection.js:7:9:7:20 | m("default") | This call refers to a global function, and not the local method $@. | indirection.js:2:5:4:5 | m() {\\n ... K\\n } | m | | missing1.js:3:5:3:24 | setAudioProperties() | This call refers to a global function, and not the local method $@. | missing1.js:6:3:7:3 | setAudi ... (){\\n } | setAudioProperties | | missing2.js:3:5:3:24 | setAudioProperties() | This call refers to a global function, and not the local method $@. | missing2.js:7:3:8:3 | static ... (){\\n } | setAudioProperties | | namespaces-uses.ts:3:5:3:20 | globalFunction() | This call refers to a global function, and not the local method $@. | namespaces-uses.ts:2:3:4:3 | globalF ... OK\\n } | globalFunction | diff --git a/javascript/ql/test/query-tests/Declarations/MissingThisQualifier/indirection.js b/javascript/ql/test/query-tests/Declarations/MissingThisQualifier/indirection.js new file mode 100644 index 00000000000..086a8ba03c2 --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/MissingThisQualifier/indirection.js @@ -0,0 +1,9 @@ +class X { + m() { + m("default"); // OK + } + + resty(...x) { + m("default"); // NOT OK + } +} diff --git a/javascript/ql/test/query-tests/Declarations/MixedStaticInstanceThisAccess/MixedStaticInstanceThisAccess.expected b/javascript/ql/test/query-tests/Declarations/MixedStaticInstanceThisAccess/MixedStaticInstanceThisAccess.expected index efb708b4e47..1e5f4d64324 100644 --- a/javascript/ql/test/query-tests/Declarations/MixedStaticInstanceThisAccess/MixedStaticInstanceThisAccess.expected +++ b/javascript/ql/test/query-tests/Declarations/MixedStaticInstanceThisAccess/MixedStaticInstanceThisAccess.expected @@ -1,2 +1,3 @@ | instanceStatic.js:3:9:3:16 | this.baz | Access to instance method $@ from static method $@ is not possible through `this`. | instanceStatic.js:5:5:7:5 | baz(){\\n\\n } | baz | instanceStatic.js:2:5:4:5 | static ... K\\n } | bar | | staticInstance.js:3:9:3:16 | this.baz | Access to static method $@ from instance method $@ is not possible through `this`. | staticInstance.js:5:5:6:5 | static baz(){\\n } | baz | staticInstance.js:2:5:4:5 | bar(){\\n ... K\\n } | bar | +| tst.js:66:9:66:14 | this.f | Access to instance method $@ from static method $@ is not possible through `this`. | tst.js:60:5:62:5 | f() {\\n\\n } | f | tst.js:65:5:67:5 | static ... K\\n } | test | diff --git a/javascript/ql/test/query-tests/Declarations/MixedStaticInstanceThisAccess/tst.js b/javascript/ql/test/query-tests/Declarations/MixedStaticInstanceThisAccess/tst.js index 74bb77217a2..a00731827d8 100644 --- a/javascript/ql/test/query-tests/Declarations/MixedStaticInstanceThisAccess/tst.js +++ b/javascript/ql/test/query-tests/Declarations/MixedStaticInstanceThisAccess/tst.js @@ -41,3 +41,28 @@ class C4 { } } C4.f = x; + +class C5_super { + f() { + + } +} +class C5 extends C5_super{ + static f() { + + } + test() { + this.f; // OK + } +} + +class C6_super { + f() { + + } +} +class C6 extends C6_super{ + static test() { + this.f; // NOT OK + } +} diff --git a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.expected b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.expected index 26a54cf8612..4968baa31ee 100644 --- a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.expected +++ b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.expected @@ -13,3 +13,5 @@ | UnknownDirective.js:14:5:14:14 | "use bar"; | Unknown directive: 'use bar'. | | UnknownDirective.js:38:5:38:17 | "[0, 0, 0];"; | Unknown directive: '[0, 0, 0];'. | | UnknownDirective.js:39:5:39:65 | "[0, 0, ... , 0];"; | Unknown directive: '[0, 0, 0, 0, 0, 0, 0 ... (truncated)'. | +| UnknownDirective.js:45:5:45:15 | ":nomunge"; | Unknown directive: ':nomunge'. | +| UnknownDirective.js:46:5:46:30 | "foo(), ... munge"; | Unknown directive: 'foo(), bar, baz:nomu ... (truncated)'. | diff --git a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js index 5f38a2eb1a0..fc0da8bde43 100644 --- a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js +++ b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js @@ -38,3 +38,10 @@ function data() { "[0, 0, 0];"; // NOT OK "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];"; // NOT OK } + +function yui() { + "foo:nomunge"; // OK + "bar:nomunge, baz:nomunge,qux:nomunge"; // OK + ":nomunge"; // NOT OK + "foo(), bar, baz:nomunge"; // NOT OK +} diff --git a/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected index fb3e8e11bba..e562c22f904 100644 --- a/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected +++ b/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected @@ -22,10 +22,7 @@ nodes | passwords.js:28:16:28:17 | {} | | passwords.js:29:17:29:20 | obj3 | | passwords.js:30:14:30:21 | password | -| passwords.js:77:9:77:55 | temp | -| passwords.js:77:16:77:55 | { encry ... sword } | | passwords.js:77:37:77:53 | req.body.password | -| passwords.js:78:17:78:20 | temp | | passwords.js:78:17:78:38 | temp.en ... assword | | passwords.js:80:9:80:25 | secret | | passwords.js:80:18:80:25 | password | @@ -49,6 +46,13 @@ nodes | passwords.js:123:17:123:48 | name + ... lueOf() | | passwords.js:123:31:123:38 | password | | passwords.js:123:31:123:48 | password.valueOf() | +| passwords.js:127:9:132:5 | config | +| passwords.js:127:18:132:5 | {\\n ... )\\n } | +| passwords.js:130:12:130:19 | password | +| passwords.js:131:12:131:24 | getPassword() | +| passwords.js:135:17:135:22 | config | +| passwords.js:136:17:136:24 | config.x | +| passwords.js:137:17:137:24 | config.y | | passwords_in_browser1.js:2:13:2:20 | password | | passwords_in_browser2.js:2:13:2:20 | password | | passwords_in_server_1.js:6:13:6:20 | password | @@ -71,11 +75,7 @@ edges | passwords.js:28:9:28:17 | obj3 | passwords.js:29:17:29:20 | obj3 | | passwords.js:28:16:28:17 | {} | passwords.js:28:9:28:17 | obj3 | | passwords.js:30:14:30:21 | password | passwords.js:28:16:28:17 | {} | -| passwords.js:77:9:77:55 | temp | passwords.js:78:17:78:20 | temp | -| passwords.js:77:16:77:55 | { encry ... sword } | passwords.js:77:9:77:55 | temp | -| passwords.js:77:37:77:53 | req.body.password | passwords.js:77:16:77:55 | { encry ... sword } | | passwords.js:77:37:77:53 | req.body.password | passwords.js:78:17:78:38 | temp.en ... assword | -| passwords.js:78:17:78:20 | temp | passwords.js:78:17:78:38 | temp.en ... assword | | passwords.js:80:9:80:25 | secret | passwords.js:81:24:81:29 | secret | | passwords.js:80:18:80:25 | password | passwords.js:80:9:80:25 | secret | | passwords.js:81:24:81:29 | secret | passwords.js:81:17:81:31 | `pw: ${secret}` | @@ -89,6 +89,12 @@ edges | passwords.js:122:31:122:49 | password.toString() | passwords.js:122:17:122:49 | name + ... tring() | | passwords.js:123:31:123:38 | password | passwords.js:123:31:123:48 | password.valueOf() | | passwords.js:123:31:123:48 | password.valueOf() | passwords.js:123:17:123:48 | name + ... lueOf() | +| passwords.js:127:9:132:5 | config | passwords.js:135:17:135:22 | config | +| passwords.js:127:18:132:5 | {\\n ... )\\n } | passwords.js:127:9:132:5 | config | +| passwords.js:130:12:130:19 | password | passwords.js:127:18:132:5 | {\\n ... )\\n } | +| passwords.js:130:12:130:19 | password | passwords.js:136:17:136:24 | config.x | +| passwords.js:131:12:131:24 | getPassword() | passwords.js:127:18:132:5 | {\\n ... )\\n } | +| passwords.js:131:12:131:24 | getPassword() | passwords.js:137:17:137:24 | config.y | | passwords_in_server_5.js:4:7:4:24 | req.query.password | passwords_in_server_5.js:7:12:7:12 | x | | passwords_in_server_5.js:7:12:7:12 | x | passwords_in_server_5.js:8:17:8:17 | x | #select @@ -113,6 +119,11 @@ edges | passwords.js:119:21:119:46 | "Passwo ... assword | passwords.js:119:39:119:46 | password | passwords.js:119:21:119:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:119:39:119:46 | password | an access to password | | passwords.js:122:17:122:49 | name + ... tring() | passwords.js:122:31:122:38 | password | passwords.js:122:17:122:49 | name + ... tring() | Sensitive data returned by $@ is logged here. | passwords.js:122:31:122:38 | password | an access to password | | passwords.js:123:17:123:48 | name + ... lueOf() | passwords.js:123:31:123:38 | password | passwords.js:123:17:123:48 | name + ... lueOf() | Sensitive data returned by $@ is logged here. | passwords.js:123:31:123:38 | password | an access to password | +| passwords.js:135:17:135:22 | config | passwords.js:127:18:132:5 | {\\n ... )\\n } | passwords.js:135:17:135:22 | config | Sensitive data returned by $@ is logged here. | passwords.js:127:18:132:5 | {\\n ... )\\n } | an access to password | +| passwords.js:135:17:135:22 | config | passwords.js:130:12:130:19 | password | passwords.js:135:17:135:22 | config | Sensitive data returned by $@ is logged here. | passwords.js:130:12:130:19 | password | an access to password | +| passwords.js:135:17:135:22 | config | passwords.js:131:12:131:24 | getPassword() | passwords.js:135:17:135:22 | config | Sensitive data returned by $@ is logged here. | passwords.js:131:12:131:24 | getPassword() | a call to getPassword | +| passwords.js:136:17:136:24 | config.x | passwords.js:130:12:130:19 | password | passwords.js:136:17:136:24 | config.x | Sensitive data returned by $@ is logged here. | passwords.js:130:12:130:19 | password | an access to password | +| passwords.js:137:17:137:24 | config.y | passwords.js:131:12:131:24 | getPassword() | passwords.js:137:17:137:24 | config.y | Sensitive data returned by $@ is logged here. | passwords.js:131:12:131:24 | getPassword() | a call to getPassword | | passwords_in_server_1.js:6:13:6:20 | password | passwords_in_server_1.js:6:13:6:20 | password | passwords_in_server_1.js:6:13:6:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_1.js:6:13:6:20 | password | an access to password | | passwords_in_server_2.js:3:13:3:20 | password | passwords_in_server_2.js:3:13:3:20 | password | passwords_in_server_2.js:3:13:3:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_2.js:3:13:3:20 | password | an access to password | | passwords_in_server_3.js:2:13:2:20 | password | passwords_in_server_3.js:2:13:2:20 | password | passwords_in_server_3.js:2:13:2:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_3.js:2:13:2:20 | password | an access to password | diff --git a/javascript/ql/test/query-tests/Security/CWE-312/passwords.js b/javascript/ql/test/query-tests/Security/CWE-312/passwords.js index 24be2573e60..d752ba7493f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-312/passwords.js +++ b/javascript/ql/test/query-tests/Security/CWE-312/passwords.js @@ -122,3 +122,18 @@ console.log(name + ", " + password.toString()); // NOT OK console.log(name + ", " + password.valueOf()); // NOT OK }); + +(function() { + var config = { + password: x, + hostname: "tarski", + x: password, + y: getPassword() + }; + var cfg = x? config: config; + console.log(config.hostname); // OK + console.log(config); // NOT OK + console.log(config.x); // NOT OK + console.log(config.y); // NOT OK + console.log(config[x]); // OK (probably) +});