mirror of
https://github.com/github/codeql.git
synced 2026-05-26 09:01:22 +02:00
Compare commits
7 Commits
revert-465
...
igfoo/48-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62cbd2506c | ||
|
|
ce9432edda | ||
|
|
8d67418870 | ||
|
|
7068a2b5be | ||
|
|
0e9fefd383 | ||
|
|
79a91bb2a2 | ||
|
|
c3efacf2df |
@@ -4,6 +4,6 @@
|
||||
"slevesque.vscode-zipexplorer"
|
||||
],
|
||||
"settings": {
|
||||
"codeQL.runningQueries.memory": 2048
|
||||
"codeQL.experimentalBqrsParsing": true
|
||||
}
|
||||
}
|
||||
|
||||
2
.github/codeql/codeql-config.yml
vendored
2
.github/codeql/codeql-config.yml
vendored
@@ -7,5 +7,3 @@ paths-ignore:
|
||||
- '/cpp/'
|
||||
- '/java/'
|
||||
- '/python/'
|
||||
- '/javascript/ql/test'
|
||||
- '/javascript/extractor/tests'
|
||||
|
||||
11
.github/workflows/labeler.yml
vendored
11
.github/workflows/labeler.yml
vendored
@@ -1,11 +0,0 @@
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v2
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
49
.github/workflows/query-list.yml
vendored
49
.github/workflows/query-list.yml
vendored
@@ -1,49 +0,0 @@
|
||||
name: Build code scanning query list
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'rc/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/query-list.yml'
|
||||
- 'misc/scripts/generate-code-scanning-query-list.py'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Clone self (github/codeql)
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: codeql
|
||||
- name: Clone github/codeql-go
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'github/codeql-go'
|
||||
path: codeql-go
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Download CodeQL CLI
|
||||
uses: dsaltares/fetch-gh-release-asset@aa37ae5c44d3c9820bc12fe675e8670ecd93bd1c
|
||||
with:
|
||||
repo: "github/codeql-cli-binaries"
|
||||
version: "latest"
|
||||
file: "codeql-linux64.zip"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Unzip CodeQL CLI
|
||||
run: unzip -d codeql-cli codeql-linux64.zip
|
||||
- name: Build code scanning query list
|
||||
run: |
|
||||
PATH="$PATH:codeql-cli/codeql" python codeql/misc/scripts/generate-code-scanning-query-list.py > code-scanning-query-list.csv
|
||||
- name: Upload code scanning query list
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: code-scanning-query-list
|
||||
path: code-scanning-query-list.csv
|
||||
|
||||
4
.vscode/extensions.json
vendored
4
.vscode/extensions.json
vendored
@@ -3,8 +3,8 @@
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"GitHub.vscode-codeql"
|
||||
"github.vscode-codeql"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ You can use the [interactive query console](https://lgtm.com/help/lgtm/using-que
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/main/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
|
||||
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/master/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -4,26 +4,20 @@ The following changes in version 1.25 affect Java analysis in all applications.
|
||||
|
||||
## General improvements
|
||||
|
||||
The Java autobuilder has been improved to detect more Gradle Java versions.
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|------------------------------|------------------------|-----------------------------------|
|
||||
| Hard-coded credential in API call (`java/hardcoded-credential-api-call`) | More results | The query now recognizes the `BasicAWSCredentials` class of the Amazon client SDK library with hardcoded access key/secret key. |
|
||||
| Deserialization of user-controlled data (`java/unsafe-deserialization`) | Fewer false positive results | The query no longer reports results using `org.apache.commons.io.serialization.ValidatingObjectInputStream`. |
|
||||
| Use of a broken or risky cryptographic algorithm (`java/weak-cryptographic-algorithm`) | More results | The query now recognizes the `MessageDigest.getInstance` method. |
|
||||
| Use of a potentially broken or risky cryptographic algorithm (`java/potentially-weak-cryptographic-algorithm`) | More results | The query now recognizes the `MessageDigest.getInstance` method. |
|
||||
| Reading from a world writable file (`java/world-writable-file-read`) | More results | The query now recognizes more JDK file operations. |
|
||||
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The data-flow library has been improved with more taint flow modeling for the
|
||||
Collections framework and other classes of the JDK. This affects all security
|
||||
queries using data flow and can yield additional results.
|
||||
* The data-flow library has been improved with more taint flow modeling for the
|
||||
Spring framework. This affects all security queries using data flow and can
|
||||
yield additional results on project that rely on the Spring framework.
|
||||
* The data-flow library has been improved, which affects most security queries by potentially
|
||||
adding more results. Flow through methods now takes nested field reads/writes into account.
|
||||
For example, the library is able to track flow from `"taint"` to `sink()` via the method
|
||||
@@ -45,5 +39,3 @@ The Java autobuilder has been improved to detect more Gradle Java versions.
|
||||
}
|
||||
}
|
||||
```
|
||||
* The library has been extended with more support for Java 14 features
|
||||
(`switch` expressions and pattern-matching for `instanceof`).
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
- [yargs](https://www.npmjs.com/package/yargs)
|
||||
- [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server)
|
||||
|
||||
* TypeScript 4.0 is now supported.
|
||||
* TypeScript 3.9 is now supported.
|
||||
|
||||
* TypeScript code embedded in HTML and Vue files is now extracted and analyzed.
|
||||
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
# Improvements to Python analysis
|
||||
|
||||
The following changes in version 1.25 affect Python analysis in all applications.
|
||||
|
||||
## General improvements
|
||||
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|----------------------------|------------------------|------------------------------------------------------------------|
|
||||
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* Importing `semmle.python.web.HttpRequest` will no longer import `UntrustedStringKind` transitively. `UntrustedStringKind` is the most commonly used non-abstract subclass of `ExternalStringKind`. If not imported (by one mean or another), taint-tracking queries that concern `ExternalStringKind` will not produce any results. Please ensure such queries contain an explicit import (`import semmle.python.security.strings.Untrusted`).
|
||||
* Added model of taint sources for HTTP servers using `http.server`.
|
||||
* Added taint modeling of routed parameters in Flask.
|
||||
* Improved modeling of built-in methods on strings for taint tracking.
|
||||
* Improved classification of test files.
|
||||
* New class `BoundMethodValue` represents a bound method during runtime.
|
||||
* The query `py/command-line-injection` now recognizes command execution with the `fabric` and `invoke` Python libraries.
|
||||
|
||||
@@ -13,19 +13,13 @@ The following changes in version 1.26 affect C/C++ analysis in all applications.
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|----------------------------|------------------------|------------------------------------------------------------------|
|
||||
| Declaration hides parameter (`cpp/declaration-hides-parameter`) | Fewer false positive results | False positives involving template functions have been fixed. |
|
||||
| Inconsistent direction of for loop (`cpp/inconsistent-loop-direction`) | Fewer false positive results | The query now accounts for intentional wrapping of an unsigned loop counter. |
|
||||
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | | The precision of this query has been decreased from "high" to "medium". As a result, the query is still run but results are no longer displayed on LGTM by default. |
|
||||
| Comparison result is always the same (`cpp/constant-comparison`) | More correct results | Bounds on expressions involving multiplication can now be determined in more cases. |
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The QL class `Block`, denoting the `{ ... }` statement, is renamed to `BlockStmt`.
|
||||
* The models library now models many taint flows through `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
|
||||
* The models library now models some taint flows through `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
|
||||
* The models library now models many more taint flows through `std::string`.
|
||||
* The models library now models many taint flows through `std::istream` and `std::ostream`.
|
||||
* The models library now models some taint flows through `std::shared_ptr`, `std::unique_ptr`, `std::make_shared` and `std::make_unique`.
|
||||
* The models library now models many taint flows through `std::pair`, `std::map`, `std::unordered_map`, `std::set` and `std::unordered_set`.
|
||||
* The models library now models `bcopy`.
|
||||
* The `SimpleRangeAnalysis` library now supports multiplications of the form
|
||||
`e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant.
|
||||
|
||||
31
change-notes/1.26/analysis-csharp.md
Normal file
31
change-notes/1.26/analysis-csharp.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Improvements to C# analysis
|
||||
|
||||
The following changes in version 1.26 affect C# analysis in all applications.
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|------------------------------|------------------------|-----------------------------------|
|
||||
|
||||
|
||||
## Removal of old queries
|
||||
|
||||
## Changes to code extraction
|
||||
|
||||
* Partial method bodies are extracted. Previously, partial method bodies were skipped completely.
|
||||
* Inferring the lengths of implicitely sized arrays is fixed. Previously, multidimensional arrays were always extracted with the same length for
|
||||
each dimension. With the fix, the array sizes `2` and `1` are extracted for `new int[,]{{1},{2}}`. Previously `2` and `2` were extracted.
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
## Changes to autobuilder
|
||||
|
||||
## Changes to tooling support
|
||||
|
||||
* The Abstract Syntax Tree of C# files can be printed in Visual Studio Code.
|
||||
@@ -1,20 +0,0 @@
|
||||
# Improvements to Java analysis
|
||||
|
||||
The following changes in version 1.26 affect Java analysis in all applications.
|
||||
|
||||
## General improvements
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|------------------------------|------------------------|-----------------------------------|
|
||||
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
@@ -2,49 +2,19 @@
|
||||
|
||||
## General improvements
|
||||
|
||||
* Angular-specific taint sources and sinks are now recognized by the security queries.
|
||||
|
||||
* Support for React has improved, with better handling of react hooks, react-router path parameters, lazy-loaded components, and components transformed using `react-redux` and/or `styled-components`.
|
||||
|
||||
* Dynamic imports are now analyzed more precisely.
|
||||
|
||||
* Support for the following frameworks and libraries has been improved:
|
||||
- [@angular/*](https://www.npmjs.com/package/@angular/core)
|
||||
- [AWS Serverless](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
|
||||
- [Alibaba Serverless](https://www.alibabacloud.com/help/doc-detail/156876.htm)
|
||||
- [debounce](https://www.npmjs.com/package/debounce)
|
||||
- [bluebird](https://www.npmjs.com/package/bluebird)
|
||||
- [call-limit](https://www.npmjs.com/package/call-limit)
|
||||
- [classnames](https://www.npmjs.com/package/classnames)
|
||||
- [clsx](https://www.npmjs.com/package/clsx)
|
||||
- [express](https://www.npmjs.com/package/express)
|
||||
- [fast-json-stable-stringify](https://www.npmjs.com/package/fast-json-stable-stringify)
|
||||
- [fast-safe-stringify](https://www.npmjs.com/package/fast-safe-stringify)
|
||||
- [http](https://nodejs.org/api/http.html)
|
||||
- [javascript-stringify](https://www.npmjs.com/package/javascript-stringify)
|
||||
- [js-stringify](https://www.npmjs.com/package/js-stringify)
|
||||
- [json-stable-stringify](https://www.npmjs.com/package/json-stable-stringify)
|
||||
- [json-stringify-safe](https://www.npmjs.com/package/json-stringify-safe)
|
||||
- [json3](https://www.npmjs.com/package/json3)
|
||||
- [jQuery throttle / debounce](https://github.com/cowboy/jquery-throttle-debounce)
|
||||
- [lodash](https://www.npmjs.com/package/lodash)
|
||||
- [lodash.debounce](https://www.npmjs.com/package/lodash.debounce)
|
||||
- [lodash.throttle](https://www.npmjs.com/package/lodash.throttle)
|
||||
- [needle](https://www.npmjs.com/package/needle)
|
||||
- [object-inspect](https://www.npmjs.com/package/object-inspect)
|
||||
- [pretty-format](https://www.npmjs.com/package/pretty-format)
|
||||
- [react](https://www.npmjs.com/package/react)
|
||||
- [react-router-dom](https://www.npmjs.com/package/react-router-dom)
|
||||
- [react-redux](https://www.npmjs.com/package/react-redux)
|
||||
- [redis](https://www.npmjs.com/package/redis)
|
||||
- [redux](https://www.npmjs.com/package/redux)
|
||||
- [stringify-object](https://www.npmjs.com/package/stringify-object)
|
||||
- [styled-components](https://www.npmjs.com/package/styled-components)
|
||||
- [throttle-debounce](https://www.npmjs.com/package/throttle-debounce)
|
||||
- [underscore](https://www.npmjs.com/package/underscore)
|
||||
|
||||
* Analyzing files with the ".cjs" extension is now supported.
|
||||
* ES2021 features are now supported.
|
||||
|
||||
## New queries
|
||||
|
||||
@@ -56,18 +26,8 @@
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
|
||||
| Potentially unsafe external link (`js/unsafe-external-link`) | Fewer results | This query no longer flags URLs constructed using a template system where only the hash or query part of the URL is dynamic. |
|
||||
| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an inclusion check. |
|
||||
| Ambiguous HTML id attribute (`js/duplicate-html-id`) | Results no longer shown | Precision tag reduced to "low". The query is no longer run by default. |
|
||||
| Unused loop iteration variable (`js/unused-loop-variable`) | Fewer results | This query no longer flags variables in a destructuring array assignment that are not the last variable in the destructed array. |
|
||||
| Unsafe shell command constructed from library input (`js/shell-command-constructed-from-input`) | More results | This query now recognizes more commands where colon, dash, and underscore are used. |
|
||||
| Unsafe jQuery plugin (`js/unsafe-jquery-plugin`) | More results | This query now detects more unsafe uses of nested option properties. |
|
||||
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | More results | This query now recognizes some unsafe uses of `importScripts()` inside WebWorkers. |
|
||||
| Missing CSRF middleware (`js/missing-token-validation`) | More results | This query now recognizes writes to cookie and session variables as potentially vulnerable to CSRF attacks. |
|
||||
| Missing CSRF middleware (`js/missing-token-validation`) | Fewer results | This query now recognizes more ways of protecting against CSRF attacks. |
|
||||
| Client-side cross-site scripting (`js/xss`) | More results | This query now tracks data flow from `location.hash` more precisely. |
|
||||
|
||||
|
||||
## Changes to libraries
|
||||
* The predicate `TypeAnnotation.hasQualifiedName` now works in more cases when the imported library was not present during extraction.
|
||||
* The class `DomBasedXss::Configuration` has been deprecated, as it has been split into `DomBasedXss::HtmlInjectionConfiguration` and `DomBasedXss::JQueryHtmlOrSelectorInjectionConfiguration`. Unless specifically working with jQuery sinks, subclasses should instead be based on `HtmlInjectionConfiguration`. To use both configurations in a query, see [Xss.ql](https://github.com/github/codeql/blob/main/javascript/ql/src/Security/CWE-079/Xss.ql) for an example.
|
||||
|
||||
@@ -19,17 +19,15 @@
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll"
|
||||
"python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll",
|
||||
"python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll"
|
||||
],
|
||||
"DataFlow Java/C++/C#/Python Common": [
|
||||
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll"
|
||||
"python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll"
|
||||
],
|
||||
"TaintTracking::Configuration Java/C++/C#/Python": [
|
||||
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
@@ -43,37 +41,14 @@
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll",
|
||||
"java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll"
|
||||
"python/ql/src/experimental/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
|
||||
],
|
||||
"DataFlow Java/C++/C#/Python Consistency checks": [
|
||||
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
|
||||
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll"
|
||||
],
|
||||
"SsaReadPosition Java/C#": [
|
||||
"java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"
|
||||
],
|
||||
"Sign Java/C#": [
|
||||
"java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll"
|
||||
],
|
||||
"SignAnalysis Java/C#": [
|
||||
"java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll"
|
||||
],
|
||||
"Bound Java/C#": [
|
||||
"java/ql/src/semmle/code/java/dataflow/Bound.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/Bound.qll"
|
||||
],
|
||||
"ModulusAnalysis Java/C#": [
|
||||
"java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/ModulusAnalysis.qll"
|
||||
"python/ql/src/experimental/dataflow/internal/DataFlowImplConsistency.qll"
|
||||
],
|
||||
"C++ SubBasicBlocks": [
|
||||
"cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll",
|
||||
@@ -112,7 +87,7 @@
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/Operand.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll"
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll"
|
||||
],
|
||||
"IR IRType": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll",
|
||||
@@ -134,11 +109,11 @@
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/internal/OperandTag.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/internal/OperandTag.qll"
|
||||
],
|
||||
"IR TInstruction": [
|
||||
"IR TInstruction":[
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TInstruction.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll"
|
||||
],
|
||||
"IR TIRVariable": [
|
||||
"IR TIRVariable":[
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/internal/TIRVariable.qll"
|
||||
],
|
||||
@@ -350,79 +325,15 @@
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll"
|
||||
],
|
||||
"C# ControlFlowReachability": [
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll"
|
||||
],
|
||||
"Inline Test Expectations": [
|
||||
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"python/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||
],
|
||||
"C++ ExternalAPIs": [
|
||||
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
|
||||
"cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll"
|
||||
],
|
||||
"C++ SafeExternalAPIFunction": [
|
||||
"cpp/ql/src/Security/CWE/CWE-020/SafeExternalAPIFunction.qll",
|
||||
"cpp/ql/src/Security/CWE/CWE-020/ir/SafeExternalAPIFunction.qll"
|
||||
],
|
||||
"XML": [
|
||||
"cpp/ql/src/semmle/code/cpp/XML.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/XML.qll",
|
||||
"java/ql/src/semmle/code/xml/XML.qll",
|
||||
"javascript/ql/src/semmle/javascript/XML.qll",
|
||||
"python/ql/src/semmle/python/xml/XML.qll"
|
||||
],
|
||||
"DuplicationProblems.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/DuplicationProblems.qhelp",
|
||||
"csharp/ql/src/Metrics/Files/DuplicationProblems.qhelp",
|
||||
"javascript/ql/src/Metrics/DuplicationProblems.qhelp",
|
||||
"python/ql/src/Metrics/DuplicationProblems.qhelp"
|
||||
],
|
||||
"CommentedOutCodeQuery.qhelp": [
|
||||
"cpp/ql/src/Documentation/CommentedOutCodeQuery.qhelp",
|
||||
"python/ql/src/Lexical/CommentedOutCodeQuery.qhelp",
|
||||
"csharp/ql/src/Bad Practices/Comments/CommentedOutCodeQuery.qhelp",
|
||||
"java/ql/src/Violations of Best Practice/Comments/CommentedOutCodeQuery.qhelp",
|
||||
"javascript/ql/src/Comments/CommentedOutCodeQuery.qhelp"
|
||||
],
|
||||
"FLinesOfCodeReferences.qhelp": [
|
||||
"java/ql/src/Metrics/Files/FLinesOfCodeReferences.qhelp",
|
||||
"javascript/ql/src/Metrics/FLinesOfCodeReferences.qhelp"
|
||||
],
|
||||
"FCommentRatioCommon.qhelp": [
|
||||
"java/ql/src/Metrics/Files/FCommentRatioCommon.qhelp",
|
||||
"javascript/ql/src/Metrics/FCommentRatioCommon.qhelp"
|
||||
],
|
||||
"FLinesOfCodeOverview.qhelp": [
|
||||
"java/ql/src/Metrics/Files/FLinesOfCodeOverview.qhelp",
|
||||
"javascript/ql/src/Metrics/FLinesOfCodeOverview.qhelp"
|
||||
],
|
||||
"CommentedOutCodeMetricOverview.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/CommentedOutCodeMetricOverview.qhelp",
|
||||
"csharp/ql/src/Metrics/Files/CommentedOutCodeMetricOverview.qhelp",
|
||||
"java/ql/src/Metrics/Files/CommentedOutCodeMetricOverview.qhelp",
|
||||
"javascript/ql/src/Comments/CommentedOutCodeMetricOverview.qhelp",
|
||||
"python/ql/src/Lexical/CommentedOutCodeMetricOverview.qhelp"
|
||||
],
|
||||
"FLinesOfDuplicatedCodeCommon.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.qhelp",
|
||||
"java/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.qhelp",
|
||||
"javascript/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.qhelp",
|
||||
"python/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.qhelp"
|
||||
],
|
||||
"CommentedOutCodeReferences.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp",
|
||||
"csharp/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp",
|
||||
"java/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp",
|
||||
"javascript/ql/src/Comments/CommentedOutCodeReferences.qhelp",
|
||||
"python/ql/src/Lexical/CommentedOutCodeReferences.qhelp"
|
||||
],
|
||||
"IDE Contextual Queries": [
|
||||
"cpp/ql/src/IDEContextual.qll",
|
||||
"csharp/ql/src/IDEContextual.qll",
|
||||
"java/ql/src/IDEContextual.qll",
|
||||
"javascript/ql/src/IDEContextual.qll",
|
||||
"python/ql/src/analysis/IDEContextual.qll"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
|
||||
<ApplicationIcon />
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* The `SimpleRangeAnalysis` library has gained support for several language
|
||||
constructs it did not support previously. These improvements primarily affect
|
||||
the queries `cpp/constant-comparison`, `cpp/comparison-with-wider-type`, and
|
||||
`cpp/integer-multiplication-cast-to-long`. The newly supported language
|
||||
features are:
|
||||
* Multiplication of unsigned numbers.
|
||||
* Multiplication by a constant.
|
||||
* Reference-typed function parameters.
|
||||
* Comparing a variable not equal to an endpoint of its range, thus narrowing the range by one.
|
||||
* Using `if (x)` or `if (!x)` or similar to test for equality to zero.
|
||||
* The `SimpleRangeAnalysis` library can now be extended with custom rules. See
|
||||
examples in
|
||||
`cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/`.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* The `cpp/wrong-type-format-argument` and `cpp/non-portable-printf` queries have been hardened so that they do not produce nonsensical results on databases that contain errors (specifically the `ErroneousType`).
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* The 'Not enough memory allocated for pointer type' (cpp/allocation-too-small) and 'Not enough memory allocated for array of pointer type' (cpp/suspicious-allocation-size) queries have been improved. Previously some allocations would be reported by both queries, this no longer occurs. In addition more allocation functions are now understood by both queries.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* Two issues causing the 'Unused local variable' query (`cpp/unused-local-variable`) to produce false positive results have been fixed.
|
||||
@@ -1,3 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* Various classes in `semmle.code.cpp.models.implementations` have been made private. Users should not depend on library implementation details.
|
||||
* The `OperatorNewAllocationFunction`, `OperatorDeleteDeallocationFunction`, `Iterator` and `Snprintf` classes now have interfaces in `semmle.code.cpp.models.interfaces`.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* A new query (`cpp/unsafe-use-of-this`) has been added. The query finds pure virtual function calls whose qualifier is an object under construction.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* The queries `cpp/local-variable-hides-global-variable` and `cpp/missing-header-guard` now have severity `recommendation` instead of `warning`.
|
||||
@@ -9,7 +9,6 @@
|
||||
+ semmlecode-cpp-queries/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql: /Correctness/Dangerous Conversions
|
||||
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.ql: /Correctness/Dangerous Conversions
|
||||
+ semmlecode-cpp-queries/Security/CWE/CWE-253/HResultBooleanConversion.ql: /Correctness/Dangerous Conversions
|
||||
+ semmlecode-cpp-queries/Likely Bugs/OO/UnsafeUseOfThis.ql: /Correctness/Dangerous Conversions
|
||||
# Consistent Use
|
||||
+ semmlecode-cpp-queries/Critical/ReturnValueIgnored.ql: /Correctness/Consistent Use
|
||||
+ semmlecode-cpp-queries/Likely Bugs/InconsistentCheckReturnNull.ql: /Correctness/Consistent Use
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
|
||||
import cpp
|
||||
|
||||
from BlockStmt blk
|
||||
from Block blk
|
||||
where blk.getNumStmt() = 0
|
||||
select blk
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
import cpp
|
||||
|
||||
from IfStmt i
|
||||
where i.getThen().(BlockStmt).getNumStmt() = 0
|
||||
where i.getThen().(Block).getNumStmt() = 0
|
||||
select i
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
|
||||
import cpp
|
||||
|
||||
from BlockStmt b
|
||||
from Block b
|
||||
where b.getNumStmt() = 1
|
||||
select b
|
||||
|
||||
@@ -14,7 +14,7 @@ import cpp
|
||||
|
||||
class ComplexStmt extends Stmt {
|
||||
ComplexStmt() {
|
||||
exists(BlockStmt body |
|
||||
exists(Block body |
|
||||
body = this.(Loop).getStmt() or
|
||||
body = this.(SwitchStmt).getStmt()
|
||||
|
|
||||
@@ -24,7 +24,7 @@ class ComplexStmt extends Stmt {
|
||||
}
|
||||
}
|
||||
|
||||
from BlockStmt b, int n, ComplexStmt complexStmt
|
||||
from Block b, int n, ComplexStmt complexStmt
|
||||
where
|
||||
n = strictcount(ComplexStmt s | s = b.getAStmt()) and
|
||||
n > 3 and
|
||||
|
||||
@@ -39,7 +39,7 @@ void good() {
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>MSDN Library for MFC: <a href="https://docs.microsoft.com/en-us/cpp/mfc/exceptions-catching-and-deleting-exceptions">Exceptions: Catching and Deleting Exceptions</a>.</li>
|
||||
<li>MSDN Library for MFC: <a href="http://msdn.microsoft.com/en-us/library/0e5twxsh(v=vs.110).aspx">Exceptions: Catching and Deleting Exceptions</a>.</li>
|
||||
|
||||
|
||||
</references>
|
||||
|
||||
@@ -11,17 +11,6 @@
|
||||
|
||||
import cpp
|
||||
|
||||
/**
|
||||
* Gets the template that a function `f` is constructed from, or just `f` if it
|
||||
* is not from a template instantiation.
|
||||
*/
|
||||
Function getConstructedFrom(Function f) {
|
||||
f.isConstructedFrom(result)
|
||||
or
|
||||
not f.isConstructedFrom(_) and
|
||||
result = f
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameter of `f` with name `name`, which has to come from the
|
||||
* _definition_ of `f` and not a prototype declaration.
|
||||
@@ -29,17 +18,13 @@ Function getConstructedFrom(Function f) {
|
||||
* This should not happen in a single application but since we
|
||||
* have a system wide view it is likely to happen for instance for
|
||||
* the main function.
|
||||
*
|
||||
* Note: we use `getConstructedFrom` to ensure that we look at template
|
||||
* functions rather than their instantiations. We get better results this way
|
||||
* as the instantiation is artificial and may have inherited parameter names
|
||||
* from the declaration rather than the definition.
|
||||
*/
|
||||
ParameterDeclarationEntry functionParameterNames(Function f, string name) {
|
||||
exists(FunctionDeclarationEntry fe |
|
||||
result.getFunctionDeclarationEntry() = fe and
|
||||
getConstructedFrom(f).getDefinition() = fe and
|
||||
fe.getFunction() = f and
|
||||
fe.getLocation() = f.getDefinitionLocation() and
|
||||
result.getFile() = fe.getFile() and // Work around CPP-331
|
||||
strictcount(f.getDefinitionLocation()) = 1 and
|
||||
result.getName() = name
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ where
|
||||
shadowing(lv1, lv2) and
|
||||
not lv1.isCompilerGenerated() and
|
||||
not lv2.isCompilerGenerated() and
|
||||
not lv1.getParentScope().(BlockStmt).isInMacroExpansion() and
|
||||
not lv2.getParentScope().(BlockStmt).isInMacroExpansion()
|
||||
not lv1.getParentScope().(Block).isInMacroExpansion() and
|
||||
not lv2.getParentScope().(Block).isInMacroExpansion()
|
||||
select lv1, "Variable " + lv1.getName() + " hides another variable of the same name (on $@).", lv2,
|
||||
"line " + lv2.getLocation().getStartLine().toString()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name Local variable hides global variable
|
||||
* @description A local variable or parameter that hides a global variable of the same name. This may be confusing. Consider renaming one of the variables.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @problem.severity warning
|
||||
* @precision very-high
|
||||
* @id cpp/local-variable-hides-global-variable
|
||||
* @tags maintainability
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import cpp
|
||||
|
||||
predicate emptyBlock(ControlStructure s, BlockStmt b) {
|
||||
predicate emptyBlock(ControlStructure s, Block b) {
|
||||
b = s.getAChild() and
|
||||
not exists(b.getAChild()) and
|
||||
not b.isInMacroExpansion() and
|
||||
@@ -23,7 +23,7 @@ predicate emptyBlock(ControlStructure s, BlockStmt b) {
|
||||
|
||||
class AffectedFile extends File {
|
||||
AffectedFile() {
|
||||
exists(BlockStmt b |
|
||||
exists(Block b |
|
||||
emptyBlock(_, b) and
|
||||
this = b.getFile()
|
||||
)
|
||||
@@ -37,7 +37,7 @@ class AffectedFile extends File {
|
||||
class BlockOrNonChild extends Element {
|
||||
BlockOrNonChild() {
|
||||
(
|
||||
this instanceof BlockStmt
|
||||
this instanceof Block
|
||||
or
|
||||
this instanceof Comment
|
||||
or
|
||||
@@ -78,7 +78,7 @@ class BlockOrNonChild extends Element {
|
||||
/**
|
||||
* A block that contains a non-child element.
|
||||
*/
|
||||
predicate emptyBlockContainsNonchild(BlockStmt b) {
|
||||
predicate emptyBlockContainsNonchild(Block b) {
|
||||
emptyBlock(_, b) and
|
||||
exists(BlockOrNonChild c, AffectedFile file |
|
||||
c.(BlockOrNonChild).getStartRankIn(file) = 1 + b.(BlockOrNonChild).getStartRankIn(file) and
|
||||
@@ -91,7 +91,7 @@ predicate emptyBlockContainsNonchild(BlockStmt b) {
|
||||
* A block that is entirely on one line, which also contains a comment. Chances
|
||||
* are the comment is intended to refer to the block.
|
||||
*/
|
||||
predicate lineComment(BlockStmt b) {
|
||||
predicate lineComment(Block b) {
|
||||
emptyBlock(_, b) and
|
||||
exists(Location bLocation, File f, int line |
|
||||
bLocation = b.getLocation() and
|
||||
@@ -106,7 +106,7 @@ predicate lineComment(BlockStmt b) {
|
||||
)
|
||||
}
|
||||
|
||||
from ControlStructure s, BlockStmt eb
|
||||
from ControlStructure s, Block eb
|
||||
where
|
||||
emptyBlock(s, eb) and
|
||||
not emptyBlockContainsNonchild(eb) and
|
||||
|
||||
@@ -57,12 +57,5 @@ where
|
||||
not declarationHasSideEffects(v) and
|
||||
not exists(AsmStmt s | f = s.getEnclosingFunction()) and
|
||||
not v.getAnAttribute().getName() = "unused" and
|
||||
not any(ErrorExpr e).getEnclosingFunction() = f and // unextracted expr may use `v`
|
||||
not exists(
|
||||
Literal l // this case can be removed when the `myFunction2( [obj](){} );` test case doesn't depend on this exclusion
|
||||
|
|
||||
l.getEnclosingFunction() = f and
|
||||
not exists(l.getValue())
|
||||
) and
|
||||
not any(ConditionDeclExpr cde).getEnclosingFunction() = f // this case can be removed when the `if (a = b; a)` test case doesn't depend on this exclusion
|
||||
not any(ErrorExpr e).getEnclosingFunction() = f // unextracted expr likely used `v`
|
||||
select v, "Variable " + v.getName() + " is not used"
|
||||
|
||||
@@ -27,7 +27,7 @@ then removing it will make code more readable. If the static variable is needed
|
||||
<a href="https://www.securecoding.cert.org/confluence/display/c/MSC12-C.+Detect+and+remove+code+that+has+no+effect+or+is+never+executed">Detect and remove code that has no effect</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/DCL19-C.+Minimize+the+scope+of+variables+and+functions">Minimize the scope of variables and functions</a>
|
||||
<a href="https://www.securecoding.cert.org/confluence/display/cplusplus/DCL07-CPP.+Minimize+the+scope+of+variables+and+methods">Minimize the scope of variables and methods</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ this rule.
|
||||
E. W. Dijkstra Archive: <a href="http://www.cs.utexas.edu/users/EWD/transcriptions/EWD02xx/EWD215.html">A Case against the GO TO Statement (EWD-215)</a>.
|
||||
</li>
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/cpp/goto-statement-cpp">goto Statement (C++)</a>.
|
||||
MSDN Library: <a href="http://msdn.microsoft.com/en-gb/library/b34dt9cd%28v=vs.80%29.aspx">The goto Statement</a>.
|
||||
</li>
|
||||
<li>
|
||||
Mats Henricson and Erik Nyquist, <i>Industrial Strength C++</i>, Rule 4.6. Prentice Hall PTR, 1997.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Exclusions
|
||||
|
||||
Stmt getNextRealStmt(BlockStmt b, int i) {
|
||||
Stmt getNextRealStmt(Block b, int i) {
|
||||
result = b.getStmt(i + 1) and
|
||||
not result instanceof EmptyStmt
|
||||
or
|
||||
@@ -20,7 +20,7 @@ Stmt getNextRealStmt(BlockStmt b, int i) {
|
||||
result = getNextRealStmt(b, i + 1)
|
||||
}
|
||||
|
||||
from JumpStmt js, BlockStmt b, int i, Stmt s
|
||||
from JumpStmt js, Block b, int i, Stmt s
|
||||
where
|
||||
b.getStmt(i) = js and
|
||||
s = getNextRealStmt(b, i) and
|
||||
|
||||
@@ -27,6 +27,6 @@ this cannot happen.
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>SEI CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers">EXP34-C. Do not dereference null pointers</a>.</li>
|
||||
<li>SEI CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointerss">EXP34-C. Do not dereference null pointers</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.SSA
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import semmle.code.cpp.models.implementations.Allocation
|
||||
import semmle.code.cpp.models.implementations.Deallocation
|
||||
|
||||
/**
|
||||
* Holds if `alloc` is a use of `malloc` or `new`. `kind` is
|
||||
|
||||
@@ -23,7 +23,10 @@ import semmle.code.cpp.security.TaintTracking
|
||||
* ```
|
||||
*/
|
||||
predicate sourceSized(FunctionCall fc, Expr src) {
|
||||
fc.getTarget().hasGlobalOrStdName(["strncpy", "strncat", "memcpy", "memmove"]) and
|
||||
exists(string name |
|
||||
(name = "strncpy" or name = "strncat" or name = "memcpy" or name = "memmove") and
|
||||
fc.getTarget().hasGlobalOrStdName(name)
|
||||
) and
|
||||
exists(Expr dest, Expr size, Variable v |
|
||||
fc.getArgument(0) = dest and
|
||||
fc.getArgument(1) = src and
|
||||
|
||||
@@ -13,9 +13,30 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.models.Models
|
||||
|
||||
predicate baseType(AllocationExpr alloc, Type base) {
|
||||
class Allocation extends FunctionCall {
|
||||
Allocation() {
|
||||
exists(string name |
|
||||
this.getTarget().hasGlobalOrStdName(name) and
|
||||
(name = "malloc" or name = "calloc" or name = "realloc")
|
||||
)
|
||||
}
|
||||
|
||||
private string getName() { this.getTarget().hasGlobalOrStdName(result) }
|
||||
|
||||
int getSize() {
|
||||
this.getName() = "malloc" and
|
||||
this.getArgument(0).getValue().toInt() = result
|
||||
or
|
||||
this.getName() = "realloc" and
|
||||
this.getArgument(1).getValue().toInt() = result
|
||||
or
|
||||
this.getName() = "calloc" and
|
||||
result = this.getArgument(0).getValue().toInt() * this.getArgument(1).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
predicate baseType(Allocation alloc, Type base) {
|
||||
exists(PointerType pointer |
|
||||
pointer.getBaseType() = base and
|
||||
(
|
||||
@@ -33,12 +54,11 @@ predicate decideOnSize(Type t, int size) {
|
||||
size = min(t.getSize())
|
||||
}
|
||||
|
||||
from AllocationExpr alloc, Type base, int basesize, int allocated
|
||||
from Allocation alloc, Type base, int basesize, int allocated
|
||||
where
|
||||
baseType(alloc, base) and
|
||||
allocated = alloc.getSizeBytes() and
|
||||
allocated = alloc.getSize() and
|
||||
decideOnSize(base, basesize) and
|
||||
alloc.(FunctionCall).getTarget() instanceof AllocationFunction and // exclude `new` and similar
|
||||
basesize > allocated
|
||||
select alloc,
|
||||
"Type '" + base.getName() + "' is " + basesize.toString() + " bytes, but only " +
|
||||
|
||||
@@ -13,9 +13,30 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.models.Models
|
||||
|
||||
predicate baseType(AllocationExpr alloc, Type base) {
|
||||
class Allocation extends FunctionCall {
|
||||
Allocation() {
|
||||
exists(string name |
|
||||
this.getTarget().hasGlobalOrStdName(name) and
|
||||
(name = "malloc" or name = "calloc" or name = "realloc")
|
||||
)
|
||||
}
|
||||
|
||||
private string getName() { this.getTarget().hasGlobalOrStdName(result) }
|
||||
|
||||
int getSize() {
|
||||
this.getName() = "malloc" and
|
||||
this.getArgument(0).getValue().toInt() = result
|
||||
or
|
||||
this.getName() = "realloc" and
|
||||
this.getArgument(1).getValue().toInt() = result
|
||||
or
|
||||
this.getName() = "calloc" and
|
||||
result = this.getArgument(0).getValue().toInt() * this.getArgument(1).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
predicate baseType(Allocation alloc, Type base) {
|
||||
exists(PointerType pointer |
|
||||
pointer.getBaseType() = base and
|
||||
(
|
||||
@@ -28,23 +49,16 @@ predicate baseType(AllocationExpr alloc, Type base) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate decideOnSize(Type t, int size) {
|
||||
// If the codebase has more than one type with the same name, it can have more than one size.
|
||||
size = min(t.getSize())
|
||||
}
|
||||
|
||||
from AllocationExpr alloc, Type base, int basesize, int allocated
|
||||
from Allocation alloc, Type base, int basesize, int allocated
|
||||
where
|
||||
baseType(alloc, base) and
|
||||
allocated = alloc.getSizeBytes() and
|
||||
decideOnSize(base, basesize) and
|
||||
alloc.(FunctionCall).getTarget() instanceof AllocationFunction and // exclude `new` and similar
|
||||
allocated = alloc.getSize() and
|
||||
// If the codebase has more than one type with the same name, check if any matches
|
||||
not exists(int size | base.getSize() = size |
|
||||
size = 0 or
|
||||
(allocated / size) * size = allocated
|
||||
) and
|
||||
not basesize > allocated // covered by SizeCheck.ql
|
||||
basesize = min(base.getSize())
|
||||
select alloc,
|
||||
"Allocated memory (" + allocated.toString() + " bytes) is not a multiple of the size of '" +
|
||||
base.getName() + "' (" + basesize.toString() + " bytes)."
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<warning>
|
||||
This check is an approximation, so some results may not be actual defects in the program.
|
||||
It is not possible in general to compute the exact value of the variable without running the program with all possible input data.
|
||||
</warning>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<warning>
|
||||
This check is an approximation, so some results may not be actual defects in the program.
|
||||
It is not possible in general to compute which function is actually called in a virtual call,
|
||||
or a call through a pointer, without running the program with all possible input data.
|
||||
</warning>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
@@ -1,13 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<warning>
|
||||
This check is an approximation, so some results may not be actual defects in the program.
|
||||
It is not possible in general to compute the actual branch taken in conditional statements such
|
||||
as "if" without running the program with all possible input data. This means that it is not possible
|
||||
to determine if a particular statement is going to be executed.
|
||||
</warning>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
@@ -1,11 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<warning>
|
||||
This check is an approximation, so some results may not be actual defects in the program. It is not possible
|
||||
in general to compute the values of pointers without running the program with all input data.
|
||||
</warning>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
@@ -3,5 +3,5 @@
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="CommentedOutCodeQuery.qhelp" />
|
||||
<include src="../Metrics/Files/CommentedOutCodeReferences.qhelp" />
|
||||
<include src="CommentedOutCodeReferences.qhelp" />
|
||||
</qhelp>
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Commented-out code is distracting and confusing for developers who read the surrounding code,
|
||||
and its significance is often unclear. It will not get compiled or tested when the code around
|
||||
it changes, so it's likely to break over time. For these reasons, commented-out code should be
|
||||
avoided.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
Remove or reinstate the commented-out code. If you want to include a snippet of example code
|
||||
in a comment, consider enclosing it in quotes or marking it up as appropriate for the source
|
||||
language.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
</qhelp>
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Provides shared predicates related to contextual queries in the code viewer.
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
|
||||
/**
|
||||
* Returns the `File` matching the given source file name as encoded by the VS
|
||||
* Code extension.
|
||||
*/
|
||||
cached
|
||||
File getFileBySourceArchiveName(string name) {
|
||||
// The name provided for a file in the source archive by the VS Code extension
|
||||
// has some differences from the absolute path in the database:
|
||||
// 1. colons are replaced by underscores
|
||||
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
|
||||
// "/C_/foo/bar"
|
||||
// 3. double slashes in UNC prefixes are replaced with a single slash
|
||||
// We can handle 2 and 3 together by unconditionally adding a leading slash
|
||||
// before replacing double slashes.
|
||||
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
|
||||
}
|
||||
@@ -13,7 +13,14 @@
|
||||
import cpp
|
||||
|
||||
class ForbiddenFunction extends Function {
|
||||
ForbiddenFunction() { this.getName() = ["setjmp", "longjmp", "sigsetjmp", "siglongjmp"] }
|
||||
ForbiddenFunction() {
|
||||
exists(string name | name = this.getName() |
|
||||
name = "setjmp" or
|
||||
name = "longjmp" or
|
||||
name = "sigsetjmp" or
|
||||
name = "siglongjmp"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from FunctionCall call
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import cpp
|
||||
|
||||
int lineInBlock(File f) {
|
||||
exists(BlockStmt block, Location blockLocation |
|
||||
exists(Block block, Location blockLocation |
|
||||
block.getFile() = f and blockLocation = block.getLocation()
|
||||
|
|
||||
result in [blockLocation.getStartLine() .. blockLocation.getEndLine()]
|
||||
|
||||
@@ -23,7 +23,7 @@ As a result, this check incorrectly considers all negative numbers as even.
|
||||
<references>
|
||||
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/cpp/multiplicative-operators-and-the-modulus-operator">Multiplicative Operators and the Modulus Operator</a>.
|
||||
MSDN Library: <a href="http://msdn.microsoft.com/en-us/library/ty2ax9z9%28v=vs.71%29.aspx">Multiplicative Operators: *, /, and %</a>.
|
||||
</li>
|
||||
<li>
|
||||
Wikipedia: <a href="http://en.wikipedia.org/wiki/Modulo_operation#Common_pitfalls">Modulo Operation - Common pitfalls</a>.
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
Code Project: <a href="http://www.codeproject.com/Articles/2247/An-introduction-to-bitwise-operators">An introduction to bitwise operators</a>
|
||||
</li>
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/c-language/signed-bitwise-operations">Signed Bitwise Operations</a>
|
||||
MSDN Library: <a href="https://msdn.microsoft.com/en-us/library/dxda59dh.aspx">Signed Bitwise Operations</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ It is best to fully parenthesize complex comparison expressions to explicitly de
|
||||
<references>
|
||||
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/cpp/cpp-built-in-operators-precedence-and-associativity">C++ built-in operators, precedence, and associativity</a>
|
||||
<a href="http://msdn.microsoft.com/en-us/library/126fe14k%28v=VS.80%29.aspx">Operator Precedence and Associativity</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.cplusplus.com/doc/tutorial/operators/">Operators</a>
|
||||
|
||||
@@ -24,7 +24,7 @@ as rounding errors will be more prominent when using such values.
|
||||
|
||||
<li>
|
||||
D. Goldberg, <em>What Every Computer Scientist Should Know About Floating-Point Arithmetic</em>,
|
||||
ACM Computing Surveys, Volume 23, Issue 1, March 1991 (<a href="https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html">available online</a>).
|
||||
ACM Computing Surveys, Volume 23, Issue 1, March 1991 (<a href="http://docs.sun.com/source/806-3568/ncg_goldberg.html">available online</a>).
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
@@ -4,5 +4,3 @@ long j = i * i; //Wrong: due to overflow on the multiplication between ints,
|
||||
|
||||
long k = (long) i * i; //Correct: the multiplication is done on longs instead of ints,
|
||||
//and will not overflow
|
||||
|
||||
long l = static_cast<long>(i) * i; //Correct: modern C++
|
||||
|
||||
@@ -23,7 +23,7 @@ the expression would produce a result that would be too large to fit in the smal
|
||||
<references>
|
||||
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/cpp/multiplicative-operators-and-the-modulus-operator">Multiplicative Operators and the Modulus Operator</a>.
|
||||
MSDN Library: <a href="http://msdn.microsoft.com/en-us/library/ty2ax9z9%28v=vs.71%29.aspx">Multiplicative Operators: *, /, and %</a>.
|
||||
</li>
|
||||
<li>
|
||||
Cplusplus.com: <a href="http://www.cplusplus.com/articles/DE18T05o/">Integer overflow</a>.
|
||||
|
||||
@@ -23,7 +23,7 @@ the latter occupies eight bytes on a 64-bit machine.</p>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/cpp/type-conversions-and-type-safety-modern-cpp">Type Conversions and Type Safety</a>.
|
||||
MSDN Library: <a href="http://msdn.microsoft.com/en-us/library/hh279667.aspx">Type Conversions and Type Safety (Modern C++)</a>.
|
||||
</li>
|
||||
<li>
|
||||
Cplusplus.com: <a href="http://www.cplusplus.com/doc/tutorial/typecasting/">Type conversions</a>.
|
||||
|
||||
@@ -23,7 +23,7 @@ the function.
|
||||
<li>CERT C Coding
|
||||
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings">FIO30-C. Exclude user input from format strings</a>.</li>
|
||||
<li>cplusplus.com: <a href="http://www.tutorialspoint.com/cplusplus/cpp_functions.htm">C++ Functions</a>.</li>
|
||||
<li>CRT Alphabetical Function Reference: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l">printf, _printf_l, wprintf, _wprintf_l</a>.</li>
|
||||
<li>MSDN Alphabetical Function Reference: <a href="http://msdn.microsoft.com/en-us/library/wc7014hz%28VS.71%29.aspx">printf, wprintf</a>.</li>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -155,8 +155,7 @@ where
|
||||
not actual.getUnspecifiedType().(IntegralType).getSize() = sizeof_IntType()
|
||||
) and
|
||||
not arg.isAffectedByMacro() and
|
||||
not arg.isFromUninstantiatedTemplate(_) and
|
||||
not actual.getUnspecifiedType() instanceof ErroneousType
|
||||
not arg.isFromUninstantiatedTemplate(_)
|
||||
select arg,
|
||||
"This argument should be of type '" + expected.getName() + "' but is of type '" +
|
||||
actual.getUnspecifiedType().getName() + "'"
|
||||
|
||||
@@ -15,7 +15,7 @@ of days. Alternatively, use an established library routine that already contain
|
||||
</recommendation>
|
||||
|
||||
<references>
|
||||
<li>NASA / Goddard Space Flight Center - <a href="https://eclipse.gsfc.nasa.gov/SEhelp/calendars.html">Calendars</a></li>
|
||||
<li>U.S. Naval Observatory Website - <a href="https://aa.usno.navy.mil/faq/docs/calendars.php"> Introduction to Calendars</a></li>
|
||||
<li>Wikipedia - <a href="https://en.wikipedia.org/wiki/Leap_year_bug"> Leap year bug</a> </li>
|
||||
<li>Microsoft Azure blog - <a href="https://azure.microsoft.com/en-us/blog/is-your-code-ready-for-the-leap-year/"> Is your code ready for the leap year?</a> </li>
|
||||
</references>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>NASA / Goddard Space Flight Center - <a href="https://eclipse.gsfc.nasa.gov/SEhelp/calendars.html">Calendars</a></li>
|
||||
<li>U.S. Naval Observatory Website - <a href="https://aa.usno.navy.mil/faq/docs/calendars.php"> Introduction to Calendars</a></li>
|
||||
<li>Wikipedia - <a href="https://en.wikipedia.org/wiki/Leap_year_bug"> Leap year bug</a> </li>
|
||||
<li>Microsoft Azure blog - <a href="https://azure.microsoft.com/en-us/blog/is-your-code-ready-for-the-leap-year/"> Is your code ready for the leap year?</a> </li>
|
||||
</references>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>NASA / Goddard Space Flight Center - <a href="https://eclipse.gsfc.nasa.gov/SEhelp/calendars.html">Calendars</a></li>
|
||||
<li>U.S. Naval Observatory Website - <a href="https://aa.usno.navy.mil/faq/docs/calendars.php"> Introduction to Calendars</a></li>
|
||||
<li>Wikipedia - <a href="https://en.wikipedia.org/wiki/Leap_year_bug"> Leap year bug</a> </li>
|
||||
<li>Microsoft Azure blog - <a href="https://azure.microsoft.com/en-us/blog/is-your-code-ready-for-the-leap-year/"> Is your code ready for the leap year?</a> </li>
|
||||
</references>
|
||||
|
||||
@@ -40,7 +40,9 @@ class DateStructModifiedFieldAccess extends LeapYearFieldAccess {
|
||||
*/
|
||||
class SafeTimeGatheringFunction extends Function {
|
||||
SafeTimeGatheringFunction() {
|
||||
this.getQualifiedName() = ["GetFileTime", "GetSystemTime", "NtQuerySystemTime"]
|
||||
this.getQualifiedName() = "GetFileTime" or
|
||||
this.getQualifiedName() = "GetSystemTime" or
|
||||
this.getQualifiedName() = "NtQuerySystemTime"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,13 +51,15 @@ class SafeTimeGatheringFunction extends Function {
|
||||
*/
|
||||
class TimeConversionFunction extends Function {
|
||||
TimeConversionFunction() {
|
||||
this.getQualifiedName() =
|
||||
[
|
||||
"FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
|
||||
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
|
||||
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
|
||||
"RtlTimeToSecondsSince1970", "_mkgmtime"
|
||||
]
|
||||
this.getQualifiedName() = "FileTimeToSystemTime" or
|
||||
this.getQualifiedName() = "SystemTimeToFileTime" or
|
||||
this.getQualifiedName() = "SystemTimeToTzSpecificLocalTime" or
|
||||
this.getQualifiedName() = "SystemTimeToTzSpecificLocalTimeEx" or
|
||||
this.getQualifiedName() = "TzSpecificLocalTimeToSystemTime" or
|
||||
this.getQualifiedName() = "TzSpecificLocalTimeToSystemTimeEx" or
|
||||
this.getQualifiedName() = "RtlLocalTimeToSystemTime" or
|
||||
this.getQualifiedName() = "RtlTimeToSecondsSince1970" or
|
||||
this.getQualifiedName() = "_mkgmtime"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>NASA / Goddard Space Flight Center - <a href="https://eclipse.gsfc.nasa.gov/SEhelp/calendars.html">Calendars</a></li>
|
||||
<li>U.S. Naval Observatory Website - <a href="https://aa.usno.navy.mil/faq/docs/calendars.php"> Introduction to Calendars</a></li>
|
||||
<li>Wikipedia - <a href="https://en.wikipedia.org/wiki/Leap_year_bug"> Leap year bug</a> </li>
|
||||
<li>Microsoft Azure blog - <a href="https://azure.microsoft.com/en-us/blog/is-your-code-ready-for-the-leap-year/"> Is your code ready for the leap year?</a> </li>
|
||||
</references>
|
||||
|
||||
@@ -27,11 +27,11 @@ predicate macroUseLocation(File f, int start, int end) {
|
||||
}
|
||||
|
||||
pragma[noopt]
|
||||
predicate emptyIf(IfStmt s, BlockStmt b, File f, int start, int end) {
|
||||
predicate emptyIf(IfStmt s, Block b, File f, int start, int end) {
|
||||
s instanceof IfStmt and
|
||||
not exists(s.getElse()) and
|
||||
b = s.getThen() and
|
||||
b instanceof BlockStmt and
|
||||
b instanceof Block and
|
||||
not exists(b.getAChild()) and
|
||||
f = b.getFile() and
|
||||
exists(Location l |
|
||||
@@ -42,7 +42,7 @@ predicate emptyIf(IfStmt s, BlockStmt b, File f, int start, int end) {
|
||||
}
|
||||
|
||||
pragma[noopt]
|
||||
predicate query(IfStmt s, BlockStmt b) {
|
||||
predicate query(IfStmt s, Block b) {
|
||||
exists(File f, int blockStart, int blockEnd |
|
||||
emptyIf(s, b, f, blockStart, blockEnd) and
|
||||
not exists(int macroStart, int macroEnd |
|
||||
@@ -53,7 +53,7 @@ predicate query(IfStmt s, BlockStmt b) {
|
||||
)
|
||||
}
|
||||
|
||||
from IfStmt s, BlockStmt b
|
||||
from IfStmt s, Block b
|
||||
where
|
||||
query(s, b) and
|
||||
not b.isInMacroExpansion()
|
||||
|
||||
@@ -23,7 +23,7 @@ indication that there may be cases unhandled by the <code>switch</code> statemen
|
||||
Tutorialspoint - The C++ Programming Language: <a href="http://www.tutorialspoint.com/cplusplus/cpp_switch_statement.htm">C++ switch statement</a>
|
||||
</li>
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/cpp/switch-statement-cpp">switch statement (C++)</a>
|
||||
MSDN Library: <a href="http://msdn.microsoft.com/en-us/library/k0t5wee3%28v=VS.80%29.aspx">The switch Statement</a>
|
||||
</li>
|
||||
<li>
|
||||
M. Henricson and E. Nyquist, <i>Industrial Strength C++</i>, Chapter 4: Control Flow, Rec 4.5. Prentice Hall PTR, 1997 (<a href="http://mongers.org/industrial-c++/">available online</a>).
|
||||
|
||||
@@ -88,8 +88,7 @@ where
|
||||
not arg.isAffectedByMacro() and
|
||||
size32 = ilp32.paddedSize(actual) and
|
||||
size64 = lp64.paddedSize(actual) and
|
||||
size64 != size32 and
|
||||
not actual instanceof ErroneousType
|
||||
size64 != size32
|
||||
select arg,
|
||||
"This argument should be of type '" + expected.getName() + "' but is of type '" + actual.getName()
|
||||
+ "' (which changes size from " + size32 + " to " + size64 + " on 64-bit systems)."
|
||||
|
||||
@@ -30,7 +30,7 @@ For an array, the size is the number of elements of the array multiplied by the
|
||||
Cplusplus.comn: <a href="http://www.cplusplus.com/reference/clibrary/cstring/memset/">memset</a>
|
||||
</li>
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/memset-wmemset">memset, wmemset</a>, <a href="https://docs.microsoft.com/en-us/cpp/cpp/sizeof-operator">sizeof Operator</a>
|
||||
MSDN Library: <a href="http://msdn.microsoft.com/en-us/library/aa246471%28v=VS.60%29.aspx">memset</a>, <a href="http://msdn.microsoft.com/en-us/library/4s7x1k91%28v=VS.71%29.aspx">sizeof Operator</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ outer loop. </p>
|
||||
<li>
|
||||
Tutorialspoint - The C++ Programming Language: <a href="http://www.tutorialspoint.com/cplusplus/cpp_nested_loops.htm">C++ nested loops</a>
|
||||
</li>
|
||||
<li>
|
||||
MSDN Library: <a href="http://msdn.microsoft.com/en-us/library/8y82wx12%28v=VS.80%29.aspx">Nested Control Structures</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ object instance).</p>
|
||||
|
||||
</example>
|
||||
<references>
|
||||
<li>R. Chen, <a href="https://devblogs.microsoft.com/oldnewthing/20040507-00/?p=39443">When should your destructor be virtual?</a>.</li>
|
||||
<li>R. Chen, <a href="http://blogs.msdn.com/oldnewthing/archive/2004/05/07/127826.aspx">When should your destructor be virtual?</a>.</li>
|
||||
<li>S. Meyers. <em>Effective C++ 3d ed.</em> pp 40-44. Addison-Wesley Professional, 2005.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
class Base {
|
||||
private:
|
||||
// pure virtual member function used for initialization of derived classes.
|
||||
virtual void construct() = 0;
|
||||
public:
|
||||
Base() {
|
||||
// wrong: the virtual table of `Derived` has not been initialized yet. So this
|
||||
// call will resolve to `Base::construct`, which cannot be called as it is a pure
|
||||
// virtual function.
|
||||
construct();
|
||||
}
|
||||
};
|
||||
|
||||
class Derived : public Base {
|
||||
int field;
|
||||
|
||||
void construct() override {
|
||||
field = 1;
|
||||
}
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
|
||||
<overview>
|
||||
<p>This rule finds calls to pure virtual member functions in constructors and destructors. When executing the body of a constructor of class <code>T</code>, the virtual table of <code>T</code> refers to the virtual table of one of <code>T</code>'s base classes. This can produce unexpected behavior, including program abort that can lead to denial of service attacks. The same problem exists during destruction of an object.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>Do not rely on virtual dispatch in constructors and destructors. Instead, each class should be responsible for acquiring and releasing its resources. If a base class needs to refer to a derived class during initialization, use the Dynamic Binding During Initialization idiom.</p>
|
||||
|
||||
</recommendation>
|
||||
<example><sample src="UnsafeUseOfThis.cpp" />
|
||||
|
||||
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>ISO C++ FAQ: <a href="https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors">When my base class's constructor calls a virtual function on its this object, why doesn't my derived class's override of that virtual function get invoked?</a>
|
||||
</li>
|
||||
<li>SEI CERT C++ Coding Standard <a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP50-CPP.+Do+not+invoke+virtual+functions+from+constructors+or+destructors">OOP50-CPP. Do not invoke virtual functions from constructors or destructors</a>
|
||||
</li>
|
||||
<li>ISO C++ FAQ: <a href="https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctor-idiom">Okay, but is there a way to simulate that behavior as if dynamic binding worked on the this object within my base class's constructor?</a>
|
||||
</li>
|
||||
|
||||
|
||||
</references></qhelp>
|
||||
@@ -1,212 +0,0 @@
|
||||
/**
|
||||
* @name Unsafe use of this in constructor
|
||||
* @description A call to a pure virtual function using a 'this'
|
||||
* pointer of an object that is under construction
|
||||
* may lead to undefined behavior.
|
||||
* @kind path-problem
|
||||
* @id cpp/unsafe-use-of-this
|
||||
* @problem.severity error
|
||||
* @precision very-high
|
||||
* @tags correctness
|
||||
* language-features
|
||||
* security
|
||||
*/
|
||||
|
||||
import cpp
|
||||
// We don't actually use the global value numbering library in this query, but without it we end up
|
||||
// recomputing the IR.
|
||||
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
private import semmle.code.cpp.ir.IR
|
||||
|
||||
bindingset[n, result]
|
||||
int unbind(int n) { result >= n and result <= n }
|
||||
|
||||
/** Holds if `p` is the `n`'th parameter of the non-virtual function `f`. */
|
||||
predicate parameterOf(Parameter p, Function f, int n) {
|
||||
not f.isVirtual() and f.getParameter(n) = p
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is the `n`'th argument to a call to the non-virtual function `f`, and
|
||||
* `init` is the corresponding initiazation instruction that receives the value of `instr` in `f`.
|
||||
*/
|
||||
predicate flowIntoParameter(
|
||||
CallInstruction call, Instruction instr, Function f, int n, InitializeParameterInstruction init
|
||||
) {
|
||||
not f.isVirtual() and
|
||||
call.getPositionalArgument(n) = instr and
|
||||
f = call.getStaticCallTarget() and
|
||||
getEnclosingNonVirtualFunctionInitializeParameter(init, f) and
|
||||
init.getParameter().getIndex() = unbind(n)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is an argument to a call to the function `f`, and `init` is the
|
||||
* corresponding initialization instruction that receives the value of `instr` in `f`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate getPositionalArgumentInitParam(
|
||||
CallInstruction call, Instruction instr, InitializeParameterInstruction init, Function f
|
||||
) {
|
||||
exists(int n |
|
||||
parameterOf(_, f, n) and
|
||||
flowIntoParameter(call, instr, f, unbind(n), init)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is the qualifier to a call to the non-virtual function `f`, and
|
||||
* `init` is the corresponding initiazation instruction that receives the value of
|
||||
* `instr` in `f`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate getThisArgumentInitParam(
|
||||
CallInstruction call, Instruction instr, InitializeParameterInstruction init, Function f
|
||||
) {
|
||||
not f.isVirtual() and
|
||||
call.getStaticCallTarget() = f and
|
||||
getEnclosingNonVirtualFunctionInitializeParameter(init, f) and
|
||||
call.getThisArgument() = instr and
|
||||
init.getIRVariable() instanceof IRThisVariable
|
||||
}
|
||||
|
||||
/** Holds if `instr` is a `this` pointer used by the call instruction `call`. */
|
||||
predicate isSink(Instruction instr, CallInstruction call) {
|
||||
exists(PureVirtualFunction func |
|
||||
call.getStaticCallTarget() = func and
|
||||
call.getThisArgument() = instr and
|
||||
// Weed out implicit calls to destructors of a base class
|
||||
not func instanceof Destructor
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `init` initializes the `this` pointer in class `c`. */
|
||||
predicate isSource(InitializeParameterInstruction init, string msg, Class c) {
|
||||
(
|
||||
exists(Constructor func |
|
||||
not func instanceof CopyConstructor and
|
||||
not func instanceof MoveConstructor and
|
||||
func = init.getEnclosingFunction() and
|
||||
msg = "construction"
|
||||
)
|
||||
or
|
||||
init.getEnclosingFunction() instanceof Destructor and msg = "destruction"
|
||||
) and
|
||||
init.getIRVariable() instanceof IRThisVariable and
|
||||
init.getEnclosingFunction().getDeclaringType() = c
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` flows to a sink (which is a use of the value of `instr` as a `this` pointer).
|
||||
*/
|
||||
predicate flowsToSink(Instruction instr, Instruction sink) {
|
||||
flowsFromSource(instr) and
|
||||
(
|
||||
isSink(instr, _) and instr = sink
|
||||
or
|
||||
exists(Instruction mid |
|
||||
successor(instr, mid) and
|
||||
flowsToSink(mid, sink)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `instr` flows from a source. */
|
||||
predicate flowsFromSource(Instruction instr) {
|
||||
isSource(instr, _, _)
|
||||
or
|
||||
exists(Instruction mid |
|
||||
successor(mid, instr) and
|
||||
flowsFromSource(mid)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `f` is the enclosing non-virtual function of `init`. */
|
||||
predicate getEnclosingNonVirtualFunctionInitializeParameter(
|
||||
InitializeParameterInstruction init, Function f
|
||||
) {
|
||||
not f.isVirtual() and
|
||||
init.getEnclosingFunction() = f
|
||||
}
|
||||
|
||||
/** Holds if `f` is the enclosing non-virtual function of `init`. */
|
||||
predicate getEnclosingNonVirtualFunctionInitializeIndirection(
|
||||
InitializeIndirectionInstruction init, Function f
|
||||
) {
|
||||
not f.isVirtual() and
|
||||
init.getEnclosingFunction() = f
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is an argument (or argument indirection) to a call, and
|
||||
* `succ` is the corresponding initialization instruction in the call target.
|
||||
*/
|
||||
predicate flowThroughCallable(Instruction instr, Instruction succ) {
|
||||
// Flow from an argument to a parameter
|
||||
exists(CallInstruction call, InitializeParameterInstruction init | init = succ |
|
||||
getPositionalArgumentInitParam(call, instr, init, call.getStaticCallTarget())
|
||||
or
|
||||
getThisArgumentInitParam(call, instr, init, call.getStaticCallTarget())
|
||||
)
|
||||
or
|
||||
// Flow from argument indirection to parameter indirection
|
||||
exists(
|
||||
CallInstruction call, ReadSideEffectInstruction read, InitializeIndirectionInstruction init
|
||||
|
|
||||
init = succ and
|
||||
read.getPrimaryInstruction() = call and
|
||||
getEnclosingNonVirtualFunctionInitializeIndirection(init, call.getStaticCallTarget())
|
||||
|
|
||||
exists(int n |
|
||||
read.getSideEffectOperand().getAnyDef() = instr and
|
||||
read.getIndex() = n and
|
||||
init.getParameter().getIndex() = unbind(n)
|
||||
)
|
||||
or
|
||||
call.getThisArgument() = instr and
|
||||
init.getIRVariable() instanceof IRThisVariable
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `instr` flows to `succ`. */
|
||||
predicate successor(Instruction instr, Instruction succ) {
|
||||
succ.(CopyInstruction).getSourceValue() = instr or
|
||||
succ.(CheckedConvertOrNullInstruction).getUnary() = instr or
|
||||
succ.(ChiInstruction).getTotal() = instr or
|
||||
succ.(ConvertInstruction).getUnary() = instr or
|
||||
succ.(InheritanceConversionInstruction).getUnary() = instr or
|
||||
flowThroughCallable(instr, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if:
|
||||
* - `source` is an initialization of a `this` pointer of type `sourceClass`, and
|
||||
* - `sink` is a use of the `this` pointer, and
|
||||
* - `call` invokes a pure virtual function using `sink` as the `this` pointer, and
|
||||
* - `msg` is a string describing whether `source` is from a constructor or destructor.
|
||||
*/
|
||||
predicate flows(
|
||||
Instruction source, string msg, Class sourceClass, Instruction sink, CallInstruction call
|
||||
) {
|
||||
isSource(source, msg, sourceClass) and
|
||||
flowsToSink(source, sink) and
|
||||
isSink(sink, call)
|
||||
}
|
||||
|
||||
query predicate edges(Instruction a, Instruction b) { successor(a, b) and flowsToSink(b, _) }
|
||||
|
||||
query predicate nodes(Instruction n, string key, string val) {
|
||||
flowsToSink(n, _) and
|
||||
key = "semmle.label" and
|
||||
val = n.toString()
|
||||
}
|
||||
|
||||
from Instruction source, Instruction sink, CallInstruction call, string msg, Class sourceClass
|
||||
where
|
||||
flows(source, msg, sourceClass, sink, call) and
|
||||
// Only raise an alert if there is no override of the pure virtual function in any base class.
|
||||
not exists(Class c | c = sourceClass.getABaseClass*() |
|
||||
c.getAMemberFunction().getAnOverriddenFunction() = call.getStaticCallTarget()
|
||||
)
|
||||
select call.getUnconvertedResultExpression(), source, sink,
|
||||
"Call to pure virtual function during " + msg
|
||||
@@ -1,5 +1,4 @@
|
||||
/**
|
||||
* @deprecated
|
||||
* @name External dependencies
|
||||
* @description Count the number of dependencies a C/C++ source file has on external libraries.
|
||||
* @kind treemap
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/**
|
||||
* @deprecated
|
||||
* @name External dependency source links
|
||||
* @kind source-link
|
||||
* @metricType externalDependency
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
This metric counts the number of lines of commented-out code in each file. Large amounts of
|
||||
commented-out code often indicate poorly maintained code.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
</qhelp>
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<references>
|
||||
|
||||
<li>Mark Needham: <a href="http://www.markhneedham.com/blog/2009/01/17/the-danger-of-commenting-out-code/">The danger of commenting out code</a>.</li>
|
||||
<li>Los Techies: <a href="http://lostechies.com/rodpaddock/2010/12/29/commented-code-technical-debt">Commented Code == Technical Debt</a>.</li>
|
||||
<li>High Integrity C++ Coding Standard: <a href="http://www.codingstandard.com/rule/2-3-2-do-not-comment-out-code/">2.3.2 Do not comment out code</a>.</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,16 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Duplicated code increases overall code size, making the code base
|
||||
harder to maintain and harder to understand. It also becomes harder to fix bugs,
|
||||
since a programmer applying a fix to one copy has to always remember to update
|
||||
other copies accordingly. Finally, code duplication is generally an indication of
|
||||
a poorly designed or hastily written code base, which typically suffers from other
|
||||
problems as well.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
</qhelp>
|
||||
@@ -1,5 +1,4 @@
|
||||
/**
|
||||
* @deprecated
|
||||
* @name Duplicated lines in files
|
||||
* @description The number of lines in a file, including code, comment
|
||||
* and whitespace lines, which are duplicated in at least
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
|
||||
<p>
|
||||
This metric measures the number of lines in a file that are contained within a block that is duplicated elsewhere. These lines may include code, comments and whitespace, and the duplicate block may be in this file or in another file.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A file that contains many lines that are duplicated within the code base is problematic
|
||||
for a number of reasons.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<include src="DuplicationProblems.qhelp" />
|
||||
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
Refactor files with lots of duplicated code to extract the common code into
|
||||
a shared library or module.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
<references>
|
||||
|
||||
|
||||
<li>Wikipedia: <a href="http://en.wikipedia.org/wiki/Duplicate_code">Duplicate code</a>.</li>
|
||||
<li>M. Fowler, <em>Refactoring</em>. Addison-Wesley, 1999.</li>
|
||||
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -27,7 +27,7 @@ and IDE support than macros.</p>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/preprocessor/macros-c-cpp">Macros (C/C++)</a>
|
||||
<a href="http://msdn.microsoft.com/en-us/library/503x3e3s%28v=vs.80%29.aspx">Macros</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.stroustrup.com/icsm-2012-demacro.pdf">Rejuvenating C++ Programs through
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<references>
|
||||
|
||||
<li>
|
||||
MSDN Library: <a href="https://docs.microsoft.com/en-us/cpp/preprocessor/hash-include-directive-c-cpp">#include directive (C/C++)</a>
|
||||
<a href="http://msdn.microsoft.com/en-us/library/36k2cdd4%28v=VS.80%29.aspx">The #include Directive</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://gcc.gnu.org/onlinedocs/cpp/Include-Operation.html#Include-Operation">Include operation</a>
|
||||
|
||||
@@ -10,8 +10,13 @@ import cpp
|
||||
*/
|
||||
class SALMacro extends Macro {
|
||||
SALMacro() {
|
||||
this.getFile().getBaseName() =
|
||||
["sal.h", "specstrings_strict.h", "specstrings.h", "w32p.h", "minwindef.h"] and
|
||||
exists(string filename | filename = this.getFile().getBaseName() |
|
||||
filename = "sal.h" or
|
||||
filename = "specstrings_strict.h" or
|
||||
filename = "specstrings.h" or
|
||||
filename = "w32p.h" or
|
||||
filename = "minwindef.h"
|
||||
) and
|
||||
(
|
||||
// Dialect for Windows 8 and above
|
||||
this.getName().matches("\\_%\\_")
|
||||
@@ -53,7 +58,10 @@ class SALAnnotation extends MacroInvocation {
|
||||
*/
|
||||
class SALCheckReturn extends SALAnnotation {
|
||||
SALCheckReturn() {
|
||||
this.getMacro().(SALMacro).getName() = ["_Check_return_", "_Must_inspect_result_"]
|
||||
exists(SALMacro m | m = this.getMacro() |
|
||||
m.getName() = "_Check_return_" or
|
||||
m.getName() = "_Must_inspect_result_"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ int logicalLength(FunctionDeclarationEntry f) {
|
||||
count(Stmt s |
|
||||
s.getEnclosingFunction() = f.getFunction() and
|
||||
s.getFile() = f.getFile() and
|
||||
not s instanceof BlockStmt and
|
||||
not s instanceof Block and
|
||||
not s instanceof EmptyStmt and
|
||||
not exists(ForStmt for | s = for.getInitialization()) and
|
||||
not s.isAffectedByMacro()
|
||||
|
||||
@@ -14,7 +14,7 @@ import cpp
|
||||
class OneLineStmt extends Stmt {
|
||||
OneLineStmt() {
|
||||
this.getLocation().getStartLine() = this.getLocation().getEndLine() and
|
||||
not this instanceof BlockStmt and
|
||||
not this instanceof Block and
|
||||
not exists(ForStmt for | this = for.getInitialization()) and
|
||||
(
|
||||
// Either this statement is not touched by a macro at all...
|
||||
|
||||
@@ -27,7 +27,7 @@ int logicalLength(FunctionDeclarationEntry f) {
|
||||
count(Stmt s |
|
||||
s.getEnclosingFunction() = f.getFunction() and
|
||||
s.getFile() = f.getFile() and
|
||||
not s instanceof BlockStmt and
|
||||
not s instanceof Block and
|
||||
not s instanceof EmptyStmt and
|
||||
not exists(ForStmt for | s = for.getInitialization()) and
|
||||
not s.isAffectedByMacro()
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
|
||||
all external APIs that are used with untrusted data, along with how frequently the API is used, and how many
|
||||
unique sources of untrusted data flow to this API. This query is designed primarily to help identify which APIs
|
||||
may be relevant for security analysis of this application.</p>
|
||||
|
||||
<p>An external API is defined as a call to a function that is not defined in the source code, and is not
|
||||
modeled as a taint step in the default taint library. External APIs may be from the C++ standard library,
|
||||
third party dependencies or from internal dependencies. The query will report the function name, along with
|
||||
either <code>[param x]</code>, where <code>x</code> indicates the position of the parameter receiving the
|
||||
untrusted data or <code>[qualifier]</code> indicating the untrusted data is used as the qualifier to the
|
||||
function call.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>For each result:</p>
|
||||
|
||||
<ul>
|
||||
<li>If the result highlights a known sink, no action is required.</li>
|
||||
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query.</li>
|
||||
<li>If the result represents a call to an external API which transfers taint, add the appropriate modeling, and
|
||||
re-run the query to determine what new results have appeared due to this additional modeling.</li>
|
||||
</ul>
|
||||
|
||||
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIFunction</code>
|
||||
class to exclude known safe external APIs from future analysis.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>If the query were to return the API <code>fputs [param 1]</code>
|
||||
then we should first consider whether this a security relevant sink. In this case, this is writing to a <code>FILE*</code>, so we should
|
||||
consider whether this is an XSS sink. If it is, we should confirm that it is handled by the XSS query.</p>
|
||||
|
||||
<p>If the query were to return the API <code>strcat [param 1]</code>, then this should be
|
||||
reviewed as a possible taint step, because tainted data would flow from the 1st argument to the 0th argument of the call.</p>
|
||||
|
||||
<p>Note that both examples are correctly handled by the standard taint tracking library and XSS query.</p>
|
||||
</example>
|
||||
<references>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* @name Frequency counts for external APIs that are used with untrusted data
|
||||
* @description This reports the external APIs that are used with untrusted data, along with how
|
||||
* frequently the API is called, and how many unique sources of untrusted data flow
|
||||
* to it.
|
||||
* @id cpp/count-untrusted-data-external-api
|
||||
* @kind table
|
||||
* @tags security external/cwe/cwe-20
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import ExternalAPIs
|
||||
|
||||
from ExternalAPIUsedWithUntrustedData externalAPI
|
||||
select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses,
|
||||
externalAPI.getNumberOfUntrustedSources() as numberOfUntrustedSources order by
|
||||
numberOfUntrustedSources desc
|
||||
@@ -1,13 +0,0 @@
|
||||
#include <cstdio>
|
||||
|
||||
void do_get(FILE* request, FILE* response) {
|
||||
char page[1024];
|
||||
fgets(page, 1024, request);
|
||||
|
||||
char buffer[1024];
|
||||
strcat(buffer, "The page \"");
|
||||
strcat(buffer, page);
|
||||
strcat(buffer, "\" was not found.");
|
||||
|
||||
fputs(buffer, response);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#include <cstdio>
|
||||
|
||||
void do_get(FILE* request, FILE* response) {
|
||||
char user_id[1024];
|
||||
fgets(user_id, 1024, request);
|
||||
|
||||
char buffer[1024];
|
||||
strcat(buffer, "SELECT * FROM user WHERE user_id='");
|
||||
strcat(buffer, user_id);
|
||||
strcat(buffer, "'");
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Definitions for reasoning about untrusted data used in APIs defined outside the
|
||||
* database.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import semmle.code.cpp.models.interfaces.DataFlow
|
||||
private import semmle.code.cpp.models.interfaces.Taint
|
||||
import ExternalAPIsSpecific
|
||||
|
||||
/** A node representing untrusted data being passed to an external API. */
|
||||
class UntrustedExternalAPIDataNode extends ExternalAPIDataNode {
|
||||
UntrustedExternalAPIDataNode() { any(UntrustedDataToExternalAPIConfig c).hasFlow(_, this) }
|
||||
|
||||
/** Gets a source of untrusted data which is passed to this external API data node. */
|
||||
DataFlow::Node getAnUntrustedSource() {
|
||||
any(UntrustedDataToExternalAPIConfig c).hasFlow(result, this)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TExternalAPI =
|
||||
TExternalAPIParameter(Function f, int index) {
|
||||
exists(UntrustedExternalAPIDataNode n |
|
||||
f = n.getExternalFunction() and
|
||||
index = n.getIndex()
|
||||
)
|
||||
}
|
||||
|
||||
/** An external API which is used with untrusted data. */
|
||||
class ExternalAPIUsedWithUntrustedData extends TExternalAPI {
|
||||
/** Gets a possibly untrusted use of this external API. */
|
||||
UntrustedExternalAPIDataNode getUntrustedDataNode() {
|
||||
this = TExternalAPIParameter(result.getExternalFunction(), result.getIndex())
|
||||
}
|
||||
|
||||
/** Gets the number of untrusted sources used with this external API. */
|
||||
int getNumberOfUntrustedSources() {
|
||||
result = strictcount(getUntrustedDataNode().getAnUntrustedSource())
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
exists(Function f, int index, string indexString |
|
||||
if index = -1 then indexString = "qualifier" else indexString = "param " + index
|
||||
|
|
||||
this = TExternalAPIParameter(f, index) and
|
||||
result = f.toString() + " [" + indexString + "]"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Provides AST-specific definitions for use in the `ExternalAPI` library.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import SafeExternalAPIFunction
|
||||
|
||||
/** A node representing untrusted data being passed to an external API. */
|
||||
class ExternalAPIDataNode extends DataFlow::Node {
|
||||
Call call;
|
||||
int i;
|
||||
|
||||
ExternalAPIDataNode() {
|
||||
// Argument to call to a function
|
||||
(
|
||||
this.asExpr() = call.getArgument(i)
|
||||
or
|
||||
i = -1 and this.asExpr() = call.getQualifier()
|
||||
) and
|
||||
exists(Function f |
|
||||
f = call.getTarget() and
|
||||
// Defined outside the source archive
|
||||
not f.hasDefinition() and
|
||||
// Not already modeled as a dataflow or taint step
|
||||
not f instanceof DataFlowFunction and
|
||||
not f instanceof TaintFunction and
|
||||
// Not a call to a known safe external API
|
||||
not f instanceof SafeExternalAPIFunction
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the called API `Function`. */
|
||||
Function getExternalFunction() { result = call.getTarget() }
|
||||
|
||||
/** Gets the index which is passed untrusted data (where -1 indicates the qualifier). */
|
||||
int getIndex() { result = i }
|
||||
|
||||
/** Gets the description of the function being called. */
|
||||
string getFunctionDescription() { result = getExternalFunction().toString() }
|
||||
}
|
||||
|
||||
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */
|
||||
class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration {
|
||||
UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(RemoteFlowFunction remoteFlow |
|
||||
remoteFlow = source.asExpr().(Call).getTarget() and
|
||||
remoteFlow.hasRemoteFlowSource(_, _)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalAPIDataNode }
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
|
||||
all external APIs that are used with untrusted data, along with how frequently the API is used, and how many
|
||||
unique sources of untrusted data flow to this API. This query is designed primarily to help identify which APIs
|
||||
may be relevant for security analysis of this application.</p>
|
||||
|
||||
<p>An external API is defined as a call to a function that is not defined in the source code, and is not
|
||||
modeled as a taint step in the default taint library. External APIs may be from the C++ standard library,
|
||||
third party dependencies or from internal dependencies. The query will report the function name, along with
|
||||
either <code>[param x]</code>, where <code>x</code> indicates the position of the parameter receiving the
|
||||
untrusted data or <code>[qualifier]</code> indicating the untrusted data is used as the qualifier to the
|
||||
function call.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>For each result:</p>
|
||||
|
||||
<ul>
|
||||
<li>If the result highlights a known sink, no action is required.</li>
|
||||
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query.</li>
|
||||
<li>If the result represents a call to an external API which transfers taint, add the appropriate modeling, and
|
||||
re-run the query to determine what new results have appeared due to this additional modeling.</li>
|
||||
</ul>
|
||||
|
||||
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIFunction</code>
|
||||
class to exclude known safe external APIs from future analysis.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>If the query were to return the API <code>fputs [param 1]</code>
|
||||
then we should first consider whether this a security relevant sink. In this case, this is writing to a <code>FILE*</code>, so we should
|
||||
consider whether this is an XSS sink. If it is, we should confirm that it is handled by the XSS query.</p>
|
||||
|
||||
<p>If the query were to return the API <code>strcat [param 1]</code>, then this should be
|
||||
reviewed as a possible taint step, because tainted data would flow from the 1st argument to the 0th argument of the call.</p>
|
||||
|
||||
<p>Note that both examples are correctly handled by the standard taint tracking library and XSS query.</p>
|
||||
</example>
|
||||
<references>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* @name Frequency counts for external APIs that are used with untrusted data
|
||||
* @description This reports the external APIs that are used with untrusted data, along with how
|
||||
* frequently the API is called, and how many unique sources of untrusted data flow
|
||||
* to it.
|
||||
* @id cpp/count-untrusted-data-external-api-ir
|
||||
* @kind table
|
||||
* @tags security external/cwe/cwe-20
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import ir.ExternalAPIs
|
||||
|
||||
from ExternalAPIUsedWithUntrustedData externalAPI
|
||||
select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses,
|
||||
externalAPI.getNumberOfUntrustedSources() as numberOfUntrustedSources order by
|
||||
numberOfUntrustedSources desc
|
||||
@@ -1,59 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
|
||||
external APIs that use untrusted data. The results are not filtered, so you can audit all examples.
|
||||
The query provides data for security reviews of the application and you can also use it to identify external APIs
|
||||
that should be modeled as either taint steps, or sinks for specific problems.</p>
|
||||
|
||||
<p>An external API is defined as a call to a function that is not defined in the source code, and is not modeled
|
||||
as a taint step in the default taint library. External APIs may be from the
|
||||
C++ standard library, third-party dependencies or from internal dependencies. The query reports uses of
|
||||
untrusted data in either the qualifier or as one of the arguments of external APIs.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>For each result:</p>
|
||||
|
||||
<ul>
|
||||
<li>If the result highlights a known sink, confirm that the result is reported by the relevant query, or
|
||||
that the result is a false positive because this data is sanitized.</li>
|
||||
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query,
|
||||
and confirm that the result is either found, or is safe due to appropriate sanitization.</li>
|
||||
<li>If the result represents a call to an external API that transfers taint, add the appropriate modeling, and
|
||||
re-run the query to determine what new results have appeared due to this additional modeling.</li>
|
||||
</ul>
|
||||
|
||||
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIFunction</code>
|
||||
class to exclude known safe external APIs from future analysis.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>In this first example, input is read from <code>fgets</code> and then ultimately used in a call to the
|
||||
<code>fputs</code> external API:</p>
|
||||
|
||||
<sample src="ExternalAPISinkExample.cpp" />
|
||||
|
||||
<p>This is an XSS sink. The XSS query should therefore be reviewed to confirm that this sink is appropriately modeled,
|
||||
and if it is, to confirm that the query reports this particular result, or that the result is a false positive due to
|
||||
some existing sanitization.</p>
|
||||
|
||||
<p>In this second example, again a request parameter is read from <code>fgets</code>.</p>
|
||||
|
||||
<sample src="ExternalAPITaintStepExample.cpp" />
|
||||
|
||||
<p>If the query reported the call to <code>strcat</code> on line 9, this would suggest that this external API is
|
||||
not currently modeled as a taint step in the taint tracking library. The next step would be to model this as a taint step, then
|
||||
re-run the query to determine what additional results might be found. In this example, it seems likely that <code>buffer</code>
|
||||
will be executed as an SQL query, potentially leading to an SQL injection vulnerability.</p>
|
||||
|
||||
<p>Note that both examples are correctly handled by the standard taint tracking library and XSS query.</p>
|
||||
</example>
|
||||
<references>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @name Untrusted data passed to external API
|
||||
* @description Data provided remotely is used in this external API without sanitization, which could be a security risk.
|
||||
* @id cpp/untrusted-data-to-external-api-ir
|
||||
* @kind path-problem
|
||||
* @precision low
|
||||
* @problem.severity error
|
||||
* @tags security external/cwe/cwe-20
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import ir.ExternalAPIs
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from UntrustedDataToExternalAPIConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"Call to " + sink.getNode().(ExternalAPIDataNode).getExternalFunction().toString() +
|
||||
" with untrusted data from $@.", source, source.getNode().(RemoteFlowSource).getSourceType()
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Provides a class for modeling external functions that are "safe" from a security perspective.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* A `Function` that is considered a "safe" external API from a security perspective.
|
||||
*/
|
||||
abstract class SafeExternalAPIFunction extends Function { }
|
||||
|
||||
/** The default set of "safe" external APIs. */
|
||||
private class DefaultSafeExternalAPIFunction extends SafeExternalAPIFunction {
|
||||
DefaultSafeExternalAPIFunction() {
|
||||
// If a function does not write to any of its arguments, we consider it safe to
|
||||
// pass untrusted data to it. This means that string functions such as `strcmp`
|
||||
// and `strlen`, as well as memory functions such as `memcmp`, are considered safe.
|
||||
exists(SideEffectFunction model | model = this |
|
||||
model.hasOnlySpecificWriteSideEffects() and
|
||||
not model.hasSpecificWriteSideEffect(_, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
|
||||
external APIs that use untrusted data. The results are not filtered, so you can audit all examples.
|
||||
The query provides data for security reviews of the application and you can also use it to identify external APIs
|
||||
that should be modeled as either taint steps, or sinks for specific problems.</p>
|
||||
|
||||
<p>An external API is defined as a call to a function that is not defined in the source code, and is not modeled
|
||||
as a taint step in the default taint library. External APIs may be from the
|
||||
C++ standard library, third-party dependencies or from internal dependencies. The query reports uses of
|
||||
untrusted data in either the qualifier or as one of the arguments of external APIs.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>For each result:</p>
|
||||
|
||||
<ul>
|
||||
<li>If the result highlights a known sink, confirm that the result is reported by the relevant query, or
|
||||
that the result is a false positive because this data is sanitized.</li>
|
||||
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query,
|
||||
and confirm that the result is either found, or is safe due to appropriate sanitization.</li>
|
||||
<li>If the result represents a call to an external API that transfers taint, add the appropriate modeling, and
|
||||
re-run the query to determine what new results have appeared due to this additional modeling.</li>
|
||||
</ul>
|
||||
|
||||
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIFunction</code>
|
||||
class to exclude known safe external APIs from future analysis.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>In this first example, input is read from <code>fgets</code> and then ultimately used in a call to the
|
||||
<code>fputs</code> external API:</p>
|
||||
|
||||
<sample src="ExternalAPISinkExample.cpp" />
|
||||
|
||||
<p>This is an XSS sink. The XSS query should therefore be reviewed to confirm that this sink is appropriately modeled,
|
||||
and if it is, to confirm that the query reports this particular result, or that the result is a false positive due to
|
||||
some existing sanitization.</p>
|
||||
|
||||
<p>In this second example, again a request parameter is read from <code>fgets</code>.</p>
|
||||
|
||||
<sample src="ExternalAPITaintStepExample.cpp" />
|
||||
|
||||
<p>If the query reported the call to <code>strcat</code> on line 9, this would suggest that this external API is
|
||||
not currently modeled as a taint step in the taint tracking library. The next step would be to model this as a taint step, then
|
||||
re-run the query to determine what additional results might be found. In this example, it seems likely that <code>buffer</code>
|
||||
will be executed as an SQL query, potentially leading to an SQL injection vulnerability.</p>
|
||||
|
||||
<p>Note that both examples are correctly handled by the standard taint tracking library and XSS query.</p>
|
||||
</example>
|
||||
<references>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @name Untrusted data passed to external API
|
||||
* @description Data provided remotely is used in this external API without sanitization, which could be a security risk.
|
||||
* @id cpp/untrusted-data-to-external-api
|
||||
* @kind path-problem
|
||||
* @precision low
|
||||
* @problem.severity error
|
||||
* @tags security external/cwe/cwe-20
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.TaintTracking
|
||||
import ExternalAPIs
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from UntrustedDataToExternalAPIConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"Call to " + sink.getNode().(ExternalAPIDataNode).getExternalFunction().toString() +
|
||||
" with untrusted data from $@.", source, source.toString()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user