Compare commits

..

24 Commits

Author SHA1 Message Date
Max Schaefer
eb3d0f5b0e Add merlyn.md which explains the changes on this branch. 2021-04-19 15:04:21 +01:00
Max Schaefer
09cf8e8b01 Remove RequestHeaderAccess. 2021-04-19 15:04:21 +01:00
Max Schaefer
bd8212c090 Remove RequestInputAccess. 2021-04-19 15:04:21 +01:00
Max Schaefer
f106d186e4 Remove MultipartyRemoteFlow. 2021-04-19 15:04:21 +01:00
Max Schaefer
e2c84407b4 Revert changes to Express::RequestInputAccess in c45d84f8f3 and 9cacfab7c6. 2021-04-19 15:04:21 +01:00
Max Schaefer
67b15125c7 Revert changes to Express::RequestInputAccess in d84f1b47c2. 2021-04-19 15:04:21 +01:00
Max Schaefer
caf763a969 Revert changes to Express::RequestInputAccess in ed48efe5b4. 2021-04-19 15:04:21 +01:00
Max Schaefer
4f8f5048f3 Revert changes to Express::RequestInputAccess in 83f0514475. 2021-04-19 15:04:21 +01:00
Max Schaefer
2366679d9b Revert changes to Express::RequestInputAccess in e2fbf8a68c. 2021-04-19 15:04:21 +01:00
Max Schaefer
66399c055e Remove MicroBodyParserCall. 2021-04-19 15:04:21 +01:00
Max Schaefer
85c02a430e Remove ServerRequestDataEvent. 2021-04-19 15:04:20 +01:00
Max Schaefer
29945b8ed0 Remove VueRouterFlowSource. 2021-04-19 15:04:20 +01:00
Max Schaefer
a8ef1bc32a Remove ServerlessHandlerEventAsRemoteFlow. 2021-04-19 15:04:20 +01:00
Max Schaefer
0781a138af Remove ReceivedItemAsRemoteFlow. 2021-04-19 15:04:20 +01:00
Max Schaefer
6fd67c4d8e Remove ReactRouterSource. 2021-04-19 15:04:19 +01:00
Max Schaefer
89747ecf83 Revert changes to `PostMessageEventHandler in cb7de27. 2021-04-19 15:03:51 +01:00
Max Schaefer
c013e3f9c3 Remove NodeJSNetServerItemAsRemoteFlow. 2021-04-19 15:03:51 +01:00
Max Schaefer
3b14b27635 Remove NextParams. 2021-04-19 15:03:51 +01:00
Max Schaefer
2ae32be934 Revert changes to ClientRequestData from 0b55aed626. 2021-04-19 15:03:51 +01:00
Max Schaefer
6647f6b9c4 Remove FormidableRemoteFlow. 2021-04-19 15:03:51 +01:00
Max Schaefer
41ceb291de Remove BusBoyRemoteFlow. 2021-04-19 15:03:51 +01:00
Max Schaefer
615418d2e3 Remove AngularSource. 2021-04-19 15:03:49 +01:00
Max Schaefer
0ba76f7d0e Revert "JS: Move $() sink into separate dataflow config"
This reverts commit 50a015c73e.
2021-04-19 15:03:11 +01:00
Max Schaefer
d97a10ef8a Revert "JS: Address review comments"
This reverts commit c91cdb5194.
2021-04-19 14:57:18 +01:00
652 changed files with 5060 additions and 10136 deletions

View File

@@ -1,30 +0,0 @@
name: Mark stale issues
on:
workflow_dispatch:
schedule:
- cron: "30 1 * * *"
jobs:
stale:
if: github.repository == 'github/codeql'
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Comment or remove the `Stale` label in order to avoid having this issue closed in 7 days.'
close-issue-message: 'This issue was closed because it has been inactive for 7 days.'
days-before-stale: 14
days-before-close: 7
only-labels: awaiting-response
# do not mark PRs as stale
days-before-pr-stale: -1
days-before-pr-close: -1
# Uncomment for dry-run
# debug-only: true
# operations-per-run: 1000

View File

@@ -70,4 +70,3 @@
## Changes to libraries ## Changes to libraries
* The predicate `TypeAnnotation.hasQualifiedName` now works in more cases when the imported library was not present during extraction. * 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.

View File

@@ -56,10 +56,6 @@
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll", "csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
"python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll" "python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll"
], ],
"DataFlow Java/C# Flow Summaries": [
"java/ql/src/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll"
],
"SsaReadPosition Java/C#": [ "SsaReadPosition Java/C#": [
"java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll", "java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll" "csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"

View File

@@ -1,2 +0,0 @@
lgtm
* The queries cpp/tainted-arithmetic, cpp/uncontrolled-arithmetic, and cpp/arithmetic-with-extreme-values have been improved to produce fewer false positives.

View File

@@ -10,7 +10,6 @@
* security * security
* external/cwe/cwe-120 * external/cwe/cwe-120
* external/cwe/cwe-125 * external/cwe/cwe-125
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -7,7 +7,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-476 * external/cwe/cwe-476
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -7,7 +7,6 @@
* @tags efficiency * @tags efficiency
* security * security
* external/cwe/cwe-401 * external/cwe/cwe-401
* security-severity/7.5
*/ */
import MemoryFreed import MemoryFreed

View File

@@ -7,7 +7,6 @@
* @tags efficiency * @tags efficiency
* security * security
* external/cwe/cwe-401 * external/cwe/cwe-401
* security-severity/7.5
*/ */
import MemoryFreed import MemoryFreed

View File

@@ -7,7 +7,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-476 * external/cwe/cwe-476
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -8,7 +8,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-401 * external/cwe/cwe-401
* security-severity/7.5
*/ */
import NewDelete import NewDelete

View File

@@ -8,7 +8,6 @@
* security * security
* external/cwe/cwe-131 * external/cwe/cwe-131
* external/cwe/cwe-120 * external/cwe/cwe-120
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* security * security
* external/cwe/cwe-119 * external/cwe/cwe-119
* external/cwe/cwe-131 * external/cwe/cwe-131
* security-severity/8.8
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* security * security
* external/cwe/cwe-119 * external/cwe/cwe-119
* external/cwe/cwe-131 * external/cwe/cwe-131
* security-severity/8.8
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* security * security
* external/cwe/cwe-131 * external/cwe/cwe-131
* external/cwe/cwe-122 * external/cwe/cwe-122
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* security * security
* external/cwe/cwe-131 * external/cwe/cwe-131
* external/cwe/cwe-122 * external/cwe/cwe-122
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -7,7 +7,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-416 * external/cwe/cwe-416
* security-severity/8.8
*/ */
import cpp import cpp

View File

@@ -13,7 +13,6 @@
* security * security
* external/cwe/cwe-190 * external/cwe/cwe-190
* external/cwe/cwe-192 * external/cwe/cwe-192
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -14,7 +14,6 @@
* external/cwe/cwe-192 * external/cwe/cwe-192
* external/cwe/cwe-197 * external/cwe/cwe-197
* external/cwe/cwe-681 * external/cwe/cwe-681
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -12,7 +12,6 @@
* security * security
* external/cwe/cwe-119 * external/cwe/cwe-119
* external/cwe/cwe-843 * external/cwe/cwe-843
* security-severity/8.8
* @id cpp/upcast-array-pointer-arithmetic * @id cpp/upcast-array-pointer-arithmetic
*/ */

View File

@@ -12,7 +12,6 @@
* correctness * correctness
* security * security
* external/cwe/cwe-134 * external/cwe/cwe-134
* security-severity/9.8
*/ */
import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.dataflow.TaintTracking

View File

@@ -9,7 +9,6 @@
* correctness * correctness
* security * security
* external/cwe/cwe-770 * external/cwe/cwe-770
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -8,7 +8,6 @@
* @tags security * @tags security
* external/cwe/cwe-170 * external/cwe/cwe-170
* external/cwe/cwe-665 * external/cwe/cwe-665
* security-severity/7.8
*/ */
import cpp import cpp

View File

@@ -13,7 +13,6 @@
import cpp import cpp
import semmle.code.cpp.dataflow.EscapesTree import semmle.code.cpp.dataflow.EscapesTree
import semmle.code.cpp.models.interfaces.PointerWrapper
import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.dataflow.DataFlow
/** /**
@@ -40,10 +39,6 @@ predicate hasNontrivialConversion(Expr e) {
e instanceof ParenthesisExpr e instanceof ParenthesisExpr
) )
or or
// A smart pointer can be stack-allocated while the data it points to is heap-allocated.
// So we exclude such "conversions" from this predicate.
e = any(PointerWrapper wrapper).getAnUnwrapperFunction().getACallToThisFunction()
or
hasNontrivialConversion(e.getConversion()) hasNontrivialConversion(e.getConversion())
} }

View File

@@ -12,7 +12,6 @@
* external/cwe/cwe-676 * external/cwe/cwe-676
* external/cwe/cwe-119 * external/cwe/cwe-119
* external/cwe/cwe-251 * external/cwe/cwe-251
* security-severity/8.8
*/ */
import cpp import cpp

View File

@@ -12,7 +12,6 @@
* external/cwe/cwe-676 * external/cwe/cwe-676
* external/cwe/cwe-119 * external/cwe/cwe-119
* external/cwe/cwe-251 * external/cwe/cwe-251
* security-severity/8.8
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @tags security * @tags security
* external/cwe/cwe-665 * external/cwe/cwe-665
* external/cwe/cwe-457 * external/cwe/cwe-457
* security-severity/7.8
*/ */
import cpp import cpp

View File

@@ -12,7 +12,6 @@
* external/cwe/cwe-676 * external/cwe/cwe-676
* external/cwe/cwe-120 * external/cwe/cwe-120
* external/cwe/cwe-251 * external/cwe/cwe-251
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -6,7 +6,6 @@
* @id cpp/count-untrusted-data-external-api * @id cpp/count-untrusted-data-external-api
* @kind table * @kind table
* @tags security external/cwe/cwe-20 * @tags security external/cwe/cwe-20
* security-severity/8.6
*/ */
import cpp import cpp

View File

@@ -6,7 +6,6 @@
* @id cpp/count-untrusted-data-external-api-ir * @id cpp/count-untrusted-data-external-api-ir
* @kind table * @kind table
* @tags security external/cwe/cwe-20 * @tags security external/cwe/cwe-20
* security-severity/8.6
*/ */
import cpp import cpp

View File

@@ -6,7 +6,6 @@
* @precision low * @precision low
* @problem.severity error * @problem.severity error
* @tags security external/cwe/cwe-20 * @tags security external/cwe/cwe-20
* security-severity/8.6
*/ */
import cpp import cpp

View File

@@ -6,7 +6,6 @@
* @precision low * @precision low
* @problem.severity error * @problem.severity error
* @tags security external/cwe/cwe-20 * @tags security external/cwe/cwe-20
* security-severity/8.6
*/ */
import cpp import cpp

View File

@@ -11,7 +11,6 @@
* external/cwe/cwe-023 * external/cwe/cwe-023
* external/cwe/cwe-036 * external/cwe/cwe-036
* external/cwe/cwe-073 * external/cwe/cwe-073
* security-severity/8.8
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* @tags security * @tags security
* external/cwe/cwe-078 * external/cwe/cwe-078
* external/cwe/cwe-088 * external/cwe/cwe-088
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -8,7 +8,6 @@
* @id cpp/cgi-xss * @id cpp/cgi-xss
* @tags security * @tags security
* external/cwe/cwe-079 * external/cwe/cwe-079
* security-severity/6.1
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @id cpp/sql-injection * @id cpp/sql-injection
* @tags security * @tags security
* external/cwe/cwe-089 * external/cwe/cwe-089
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @id cpp/uncontrolled-process-operation * @id cpp/uncontrolled-process-operation
* @tags security * @tags security
* external/cwe/cwe-114 * external/cwe/cwe-114
* security-severity/8.2
*/ */
import cpp import cpp

View File

@@ -11,7 +11,6 @@
* external/cwe/cwe-121 * external/cwe/cwe-121
* external/cwe/cwe-122 * external/cwe/cwe-122
* external/cwe/cwe-126 * external/cwe/cwe-126
* security-severity/8.8
*/ */
import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.BufferWrite

View File

@@ -12,7 +12,6 @@
* external/cwe/cwe-120 * external/cwe/cwe-120
* external/cwe/cwe-787 * external/cwe/cwe-787
* external/cwe/cwe-805 * external/cwe/cwe-805
* security-severity/9.1
*/ */
import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.BufferWrite

View File

@@ -11,7 +11,6 @@
* external/cwe/cwe-120 * external/cwe/cwe-120
* external/cwe/cwe-787 * external/cwe/cwe-787
* external/cwe/cwe-805 * external/cwe/cwe-805
* security-severity/9.1
*/ */
import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.BufferWrite

View File

@@ -12,7 +12,6 @@
* external/cwe/cwe-120 * external/cwe/cwe-120
* external/cwe/cwe-787 * external/cwe/cwe-787
* external/cwe/cwe-805 * external/cwe/cwe-805
* security-severity/9.1
*/ */
import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.BufferWrite

View File

@@ -11,7 +11,6 @@
* external/cwe/cwe-120 * external/cwe/cwe-120
* external/cwe/cwe-787 * external/cwe/cwe-787
* external/cwe/cwe-805 * external/cwe/cwe-805
* security-severity/9.1
*/ */
import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.BufferWrite

View File

@@ -10,7 +10,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-121 * external/cwe/cwe-121
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -8,7 +8,6 @@
* @problem.severity warning * @problem.severity warning
* @tags security * @tags security
* external/cwe/cwe-129 * external/cwe/cwe-129
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -12,7 +12,6 @@
* external/cwe/cwe-131 * external/cwe/cwe-131
* external/cwe/cwe-120 * external/cwe/cwe-120
* external/cwe/cwe-122 * external/cwe/cwe-122
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-134 * external/cwe/cwe-134
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-134 * external/cwe/cwe-134
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -7,7 +7,6 @@
* @problem.severity warning * @problem.severity warning
* @tags security * @tags security
* external/cwe/cwe-170 * external/cwe/cwe-170
* security-severity/5.5
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @tags security * @tags security
* external/cwe/cwe-190 * external/cwe/cwe-190
* external/cwe/cwe-191 * external/cwe/cwe-191
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @tags security * @tags security
* external/cwe/cwe-190 * external/cwe/cwe-190
* external/cwe/cwe-191 * external/cwe/cwe-191
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -11,7 +11,6 @@
* reliability * reliability
* external/cwe/cwe-190 * external/cwe/cwe-190
* external/cwe/cwe-191 * external/cwe/cwe-191
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -11,7 +11,6 @@
* external/cwe/cwe-190 * external/cwe/cwe-190
* external/cwe/cwe-197 * external/cwe/cwe-197
* external/cwe/cwe-835 * external/cwe/cwe-835
* security-severity/7.8
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* external/cwe/cwe-190 * external/cwe/cwe-190
* external/cwe/cwe-197 * external/cwe/cwe-197
* external/cwe/cwe-681 * external/cwe/cwe-681
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-190 * external/cwe/cwe-190
* security-severity/8.1
*/ */
import cpp import cpp

View File

@@ -8,7 +8,6 @@
* @tags security * @tags security
* correctness * correctness
* external/cwe/cwe-191 * external/cwe/cwe-191
* security-severity/8.2
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @id cpp/user-controlled-bypass * @id cpp/user-controlled-bypass
* @tags security * @tags security
* external/cwe/cwe-290 * external/cwe/cwe-290
* security-severity/7.7
*/ */
import semmle.code.cpp.security.TaintTracking import semmle.code.cpp.security.TaintTracking

View File

@@ -8,7 +8,6 @@
* @id cpp/cleartext-storage-buffer * @id cpp/cleartext-storage-buffer
* @tags security * @tags security
* external/cwe/cwe-312 * external/cwe/cwe-312
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -8,7 +8,6 @@
* @id cpp/weak-cryptographic-algorithm * @id cpp/weak-cryptographic-algorithm
* @tags security * @tags security
* external/cwe/cwe-327 * external/cwe/cwe-327
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @tags security * @tags security
* external/cwe/cwe-327 * external/cwe/cwe-327
* external/cwe/cwe-788 * external/cwe/cwe-788
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @id cpp/toctou-race-condition * @id cpp/toctou-race-condition
* @tags security * @tags security
* external/cwe/cwe-367 * external/cwe/cwe-367
* security-severity/7.0
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @tags security * @tags security
* external/cwe/cwe-428 * external/cwe/cwe-428
* external/microsoft/C6277 * external/microsoft/C6277
* security-severity/7.8
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* @tags security * @tags security
* external/cwe/cwe-704 * external/cwe/cwe-704
* external/microsoft/c/c6276 * external/microsoft/c/c6276
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -7,7 +7,6 @@
* @id cpp/world-writable-file-creation * @id cpp/world-writable-file-creation
* @tags security * @tags security
* external/cwe/cwe-732 * external/cwe/cwe-732
* security-severity/7.8
*/ */
import cpp import cpp

View File

@@ -11,7 +11,6 @@
* @tags security * @tags security
* external/cwe/cwe-732 * external/cwe/cwe-732
* external/microsoft/C6248 * external/microsoft/C6248
* security-severity/7.8
*/ */
import cpp import cpp

View File

@@ -8,7 +8,6 @@
* @problem.severity warning * @problem.severity warning
* @tags security * @tags security
* external/cwe/cwe-835 * external/cwe/cwe-835
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -9,7 +9,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-476 * external/cwe/cwe-476
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -10,7 +10,6 @@
* @tags correctness * @tags correctness
* security * security
* external/cwe/cwe-20 * external/cwe/cwe-20
* security-severity/8.6
*/ */
import cpp import cpp

View File

@@ -7,7 +7,6 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-120 * external/cwe/cwe-120
* security-severity/9.8
*/ */
import cpp import cpp

View File

@@ -8,7 +8,6 @@
* correctness * correctness
* external/cwe/cwe-190 * external/cwe/cwe-190
* external/cwe/cwe-128 * external/cwe/cwe-128
* security-severity/8.1
* @id cpp/multiplication-overflow-in-alloc * @id cpp/multiplication-overflow-in-alloc
*/ */

View File

@@ -9,7 +9,6 @@
* @id cpp/drop-linux-privileges-outoforder * @id cpp/drop-linux-privileges-outoforder
* @tags security * @tags security
* external/cwe/cwe-273 * external/cwe/cwe-273
* security-severity/9.8
* @precision medium * @precision medium
*/ */

View File

@@ -9,7 +9,6 @@
* @tags correctness * @tags correctness
* security * security
* external/cwe/cwe-401 * external/cwe/cwe-401
* security-severity/7.5
*/ */
import cpp import cpp

View File

@@ -1,4 +0,0 @@
if(len>0 & memset(buf,0,len)) return 1; // BAD: `memset` will be called regardless of the value of the `len` variable. moreover, one cannot be sure that it will happen after verification
...
if(len>0 && memset(buf,0,len)) return 1; // GOOD: `memset` will be called after the `len` variable has been checked.
...

View File

@@ -1,28 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Using bitwise operations can be a mistake in some situations. For example, if parameters are evaluated in an expression and the function should be called only upon certain test results. These bitwise operations look suspicious and require developer attention.</p>
</overview>
<recommendation>
<p>We recommend that you evaluate the correctness of using the specified bit operations.</p>
</recommendation>
<example>
<p>The following example demonstrates the erroneous and fixed use of bit and logical operations.</p>
<sample src="InsufficientControlFlowManagementWhenUsingBitOperations.c" />
</example>
<references>
<li>
CWE Common Weakness Enumeration:
<a href="https://cwe.mitre.org/data/definitions/691.html"> CWE-691: Insufficient Control Flow Management</a>.
</li>
</references>
</qhelp>

View File

@@ -1,78 +0,0 @@
/**
* @name Errors When Using Bit Operations
* @description Unlike the binary operations `||` and `&&`, there is no sequence point after evaluating an
* operand of a bitwise operation like `|` or `&`. If left-to-right evaluation is expected this may be confusing.
* @kind problem
* @id cpp/errors-when-using-bit-operations
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-691
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* Dangerous uses of bit operations.
* For example: `if(intA>0 & intA<10 & charBuf&myFunc(charBuf[intA]))`.
* In this case, the function will be called in any case, and even the sequence of the call is not guaranteed.
*/
class DangerousBitOperations extends BinaryBitwiseOperation {
FunctionCall bfc;
/**
* The assignment indicates the conscious use of the bit operator.
* Use in comparison, conversion, or return value indicates conscious use of the bit operator.
* The use of shifts and bitwise operations on any element of an expression indicates a conscious use of the bitwise operator.
*/
DangerousBitOperations() {
bfc = this.getRightOperand() and
not this.getParent*() instanceof Assignment and
not this.getParent*() instanceof Initializer and
not this.getParent*() instanceof ReturnStmt and
not this.getParent*() instanceof EqualityOperation and
not this.getParent*() instanceof UnaryLogicalOperation and
not this.getParent*() instanceof BinaryLogicalOperation and
not this.getAChild*() instanceof BitwiseXorExpr and
not this.getAChild*() instanceof LShiftExpr and
not this.getAChild*() instanceof RShiftExpr
}
/** Holds when part of a bit expression is used in a logical operation. */
predicate useInLogicalOperations() {
exists(BinaryLogicalOperation blop, Expr exp |
blop.getAChild*() = exp and
exp.(FunctionCall).getTarget() = bfc.getTarget() and
not exp.getParent() instanceof ComparisonOperation and
not exp.getParent() instanceof BinaryBitwiseOperation
)
}
/** Holds when part of a bit expression is used as part of another supply. For example, as an argument to another function. */
predicate useInOtherCalls() {
bfc.hasQualifier() or
bfc.getTarget() instanceof Operator or
exists(FunctionCall fc | fc.getAnArgument().getAChild*() = this) or
bfc.getTarget() instanceof BuiltInFunction
}
/** Holds when the bit expression contains both arguments and a function call. */
predicate dangerousArgumentChecking() {
not this.getLeftOperand() instanceof Call and
globalValueNumber(this.getLeftOperand().getAChild*()) = globalValueNumber(bfc.getAnArgument())
}
/** Holds when function calls are present in the bit expression. */
predicate functionCallsInBitsExpression() {
this.getLeftOperand().getAChild*() instanceof FunctionCall
}
}
from DangerousBitOperations dbo
where
not dbo.useInOtherCalls() and
dbo.useInLogicalOperations() and
(not dbo.functionCallsInBitsExpression() or dbo.dangerousArgumentChecking())
select dbo, "This bitwise operation appears in a context where a Boolean operation is expected."

View File

@@ -1,11 +0,0 @@
if(len=funcReadData()==0) return 1; // BAD: variable `len` will not equal the value returned by function `funcReadData()`
...
if((len=funcReadData())==0) return 1; // GOOD: variable `len` equal the value returned by function `funcReadData()`
...
bool a=true;
a++;// BAD: variable `a` does not change its meaning
bool b;
b=-a;// BAD: variable `b` equal `true`
...
a=false;// GOOD: variable `a` equal `false`
b=!a;// GOOD: variable `b` equal `false`

View File

@@ -1,28 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Finding places of confusing use of boolean type. For example, a unary minus does not work before a boolean type and an increment always gives true.</p>
</overview>
<recommendation>
<p>we recommend making the code simpler.</p>
</recommendation>
<example>
<p>The following example demonstrates erroneous and fixed methods for using a boolean data type.</p>
<sample src="OperatorPrecedenceLogicErrorWhenUseBoolType.c" />
</example>
<references>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP00-C.+Use+parentheses+for+precedence+of+operation">EXP00-C. Use parentheses for precedence of operation</a>.
</li>
</references>
</qhelp>

View File

@@ -1,54 +0,0 @@
/**
* @name Operator Precedence Logic Error When Use Bool Type
* @description --Finding places of confusing use of boolean type.
* --For example, a unary minus does not work before a boolean type and an increment always gives true.
* @kind problem
* @id cpp/operator-precedence-logic-error-when-use-bool-type
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-783
* external/cwe/cwe-480
*/
import cpp
import semmle.code.cpp.valuenumbering.HashCons
/** Holds if `exp` increments a boolean value. */
predicate incrementBoolType(IncrementOperation exp) {
exp.getOperand().getType() instanceof BoolType
}
/** Holds if `exp` applies the unary minus operator to a boolean type. */
predicate revertSignBoolType(UnaryMinusExpr exp) {
exp.getAnOperand().getType() instanceof BoolType and
exp.getFullyConverted().getType() instanceof BoolType
}
/** Holds, if this is an expression, uses comparison and assignment outside of execution precedence. */
predicate assignBoolType(Expr exp) {
exists(ComparisonOperation co |
exp.(AssignExpr).getRValue() = co and
exp.isCondition() and
not co.isParenthesised() and
not exp.(AssignExpr).getLValue().getType() instanceof BoolType and
not exists(Expr exbl |
hashCons(exbl.(AssignExpr).getLValue()) = hashCons(exp.(AssignExpr).getLValue()) and
not exbl.isCondition() and
exbl.(AssignExpr).getRValue().getType() instanceof BoolType and
exbl.(AssignExpr).getLValue().getType() = exp.(AssignExpr).getLValue().getType()
) and
co.getLeftOperand() instanceof FunctionCall and
not co.getRightOperand().getType() instanceof BoolType and
not co.getRightOperand().getValue() = "0" and
not co.getRightOperand().getValue() = "1"
)
}
from Expr exp
where
incrementBoolType(exp) or
revertSignBoolType(exp) or
assignBoolType(exp)
select exp, "this expression needs attention"

View File

@@ -3,7 +3,7 @@
* @description The expression `buffer [strlen (buffer)] = 0` is potentially dangerous, if the variable `buffer` does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior. * @description The expression `buffer [strlen (buffer)] = 0` is potentially dangerous, if the variable `buffer` does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior.
* If terminal zero is present, then the specified expression is meaningless. * If terminal zero is present, then the specified expression is meaningless.
* @kind problem * @kind problem
* @id cpp/access-memory-location-after-end-buffer-strlen * @id cpp/access-memory-location-after-end-buffer
* @problem.severity warning * @problem.severity warning
* @precision medium * @precision medium
* @tags correctness * @tags correctness

View File

@@ -2,7 +2,7 @@
* @name Access Of Memory Location After The End Of A Buffer Using Strncat * @name Access Of Memory Location After The End Of A Buffer Using Strncat
* @description Calls of the form `strncat(dest, source, sizeof (dest) - strlen (dest))` set the third argument to one more than possible. So when `dest` is full, the expression `sizeof(dest) - strlen (dest)` will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the `dest` buffer. * @description Calls of the form `strncat(dest, source, sizeof (dest) - strlen (dest))` set the third argument to one more than possible. So when `dest` is full, the expression `sizeof(dest) - strlen (dest)` will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the `dest` buffer.
* @kind problem * @kind problem
* @id cpp/access-memory-location-after-end-buffer-strncat * @id cpp/access-memory-location-after-end-buffer
* @problem.severity warning * @problem.severity warning
* @precision medium * @precision medium
* @tags correctness * @tags correctness
@@ -11,32 +11,54 @@
*/ */
import cpp import cpp
import semmle.code.cpp.models.implementations.Strcat
import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/** /**
* Holds if `call` is a call to `strncat` such that `sizeArg` and `destArg` are the size and * A call to `strncat` of the form `strncat(buff, str, someExpr - strlen(buf))`, for some expression `someExpr` equal to `sizeof(buff)`.
* destination arguments, respectively.
*/ */
predicate interestringCallWithArgs(Call call, Expr sizeArg, Expr destArg) { class WrongCallStrncat extends FunctionCall {
exists(StrcatFunction strcat | Expr leftsomeExpr;
strcat = call.getTarget() and
sizeArg = call.getArgument(strcat.getParamSize()) and WrongCallStrncat() {
destArg = call.getArgument(strcat.getParamDest()) this.getTarget().hasGlobalOrStdName("strncat") and
) // the expression of the first argument in `strncat` and `strnlen` is identical
globalValueNumber(this.getArgument(0)) =
globalValueNumber(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and
// using a string constant often speaks of manually calculating the length of the required buffer.
(
not this.getArgument(1) instanceof StringLiteral and
not this.getArgument(1) instanceof CharLiteral
) and
// for use in predicates
leftsomeExpr = this.getArgument(2).(SubExpr).getLeftOperand()
}
/**
* Holds if the left side of the expression `someExpr` equal to `sizeof(buf)`.
*/
predicate isExpressionEqualSizeof() {
// the left side of the expression `someExpr` is `sizeof(buf)`.
globalValueNumber(this.getArgument(0)) =
globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand())
or
// value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array.
leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize()
}
/**
* Holds if the left side of the expression `someExpr` equal to variable containing the length of the memory allocated for the buffer.
*/
predicate isVariableEqualValueSizegBuffer() {
// the left side of expression `someExpr` is the variable that was used in the function of allocating memory for the buffer`.
exists(AllocationExpr alc |
leftsomeExpr.(VariableAccess).getTarget() =
alc.(FunctionCall).getArgument(0).(VariableAccess).getTarget()
)
}
} }
from FunctionCall call, Expr sizeArg, Expr destArg, SubExpr sub, int n from WrongCallStrncat sc
where where
interestringCallWithArgs(call, sizeArg, destArg) and sc.isExpressionEqualSizeof() or
// The destination buffer is an array of size n sc.isVariableEqualValueSizegBuffer()
destArg.getUnspecifiedType().(ArrayType).getSize() = n and select sc, "if the used buffer is full, writing out of the buffer is possible"
// The size argument is equivalent to a subtraction
globalValueNumber(sizeArg).getAnExpr() = sub and
// ... where the left side of the subtraction is the constant n
globalValueNumber(sub.getLeftOperand()).getAnExpr().getValue().toInt() = n and
// ... and the right side of the subtraction is a call to `strlen` where the argument is the
// destination buffer.
globalValueNumber(sub.getRightOperand()).getAnExpr().(StrlenCall).getStringExpr() =
globalValueNumber(destArg).getAnExpr()
select call, "Possible out-of-bounds write due to incorrect size argument."

View File

@@ -15,7 +15,6 @@
*/ */
private import cpp private import cpp
private import semmle.code.cpp.models.interfaces.PointerWrapper
/** /**
* Holds if `f` is an instantiation of the `std::move` or `std::forward` * Holds if `f` is an instantiation of the `std::move` or `std::forward`
@@ -95,12 +94,6 @@ private predicate pointerToPointerStep(Expr pointerIn, Expr pointerOut) {
private predicate lvalueToReferenceStep(Expr lvalueIn, Expr referenceOut) { private predicate lvalueToReferenceStep(Expr lvalueIn, Expr referenceOut) {
lvalueIn.getConversion() = referenceOut.(ReferenceToExpr) lvalueIn.getConversion() = referenceOut.(ReferenceToExpr)
or
exists(PointerWrapper wrapper, Call call | call = referenceOut |
referenceOut.getUnspecifiedType() instanceof ReferenceType and
call = wrapper.getAnUnwrapperFunction().getACallToThisFunction() and
lvalueIn = call.getQualifier().getFullyConverted()
)
} }
private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) { private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) {
@@ -113,13 +106,6 @@ private predicate referenceToPointerStep(Expr referenceIn, Expr pointerOut) {
stdAddressOf(call.getTarget()) and stdAddressOf(call.getTarget()) and
referenceIn = call.getArgument(0).getFullyConverted() referenceIn = call.getArgument(0).getFullyConverted()
) )
or
exists(CopyConstructor copy, Call call | call = pointerOut |
copy.getDeclaringType() instanceof PointerWrapper and
call.getTarget() = copy and
// The 0'th argument is the value being copied.
referenceIn = call.getArgument(0).getFullyConverted()
)
} }
private predicate referenceToReferenceStep(Expr referenceIn, Expr referenceOut) { private predicate referenceToReferenceStep(Expr referenceIn, Expr referenceOut) {
@@ -204,19 +190,6 @@ private predicate pointerToUpdate(Expr pointer, Expr outer, ControlFlowNode node
// See the `lvalueToUpdate` case for an explanation of this conjunct. // See the `lvalueToUpdate` case for an explanation of this conjunct.
call.getType().isDeeplyConstBelow() call.getType().isDeeplyConstBelow()
) )
or
// Pointer wrappers behave as raw pointers for dataflow purposes.
outer = call.getAnArgument().getFullyConverted() and
exists(PointerWrapper wrapper | wrapper = outer.getType().stripTopLevelSpecifiers() |
not wrapper.pointsToConst()
)
or
outer = call.getQualifier().getFullyConverted() and
outer.getUnspecifiedType() instanceof PointerWrapper and
not (
call.getTarget().hasSpecifier("const") and
call.getType().isDeeplyConstBelow()
)
) )
or or
exists(PointerFieldAccess fa | exists(PointerFieldAccess fa |
@@ -245,9 +218,7 @@ private predicate referenceToUpdate(Expr reference, Expr outer, ControlFlowNode
not stdIdentityFunction(call.getTarget()) and not stdIdentityFunction(call.getTarget()) and
not stdAddressOf(call.getTarget()) and not stdAddressOf(call.getTarget()) and
exists(ReferenceType rt | rt = outer.getType().stripTopLevelSpecifiers() | exists(ReferenceType rt | rt = outer.getType().stripTopLevelSpecifiers() |
not rt.getBaseType().isConst() or not rt.getBaseType().isConst()
rt.getBaseType().getUnspecifiedType() =
any(PointerWrapper wrapper | not wrapper.pointsToConst())
) )
) and ) and
reference = outer reference = outer

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -46,7 +46,7 @@ class Node extends TNode {
/** /**
* INTERNAL: Do not use. Alternative name for `getFunction`. * INTERNAL: Do not use. Alternative name for `getFunction`.
*/ */
final Function getEnclosingCallable() { result = this.getFunction() } final Function getEnclosingCallable() { result = unique(Function f | f = this.getFunction() | f) }
/** Gets the type of this node. */ /** Gets the type of this node. */
Type getType() { none() } // overridden in subclasses Type getType() { none() } // overridden in subclasses
@@ -324,7 +324,7 @@ private class VariablePartialDefinitionNode extends PartialDefinitionNode {
* A synthetic data flow node used for flow into a collection when an iterator * A synthetic data flow node used for flow into a collection when an iterator
* write occurs in a callee. * write occurs in a callee.
*/ */
private class IteratorPartialDefinitionNode extends PartialDefinitionNode { class IteratorPartialDefinitionNode extends PartialDefinitionNode {
override IteratorPartialDefinition pd; override IteratorPartialDefinition pd;
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) } override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
@@ -715,7 +715,6 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) {
} }
private module FieldFlow { private module FieldFlow {
private import DataFlowImplCommon
private import DataFlowImplLocal private import DataFlowImplLocal
private import DataFlowPrivate private import DataFlowPrivate
@@ -748,7 +747,7 @@ private module FieldFlow {
exists(FieldConfiguration cfg | cfg.hasFlow(node1, node2)) and exists(FieldConfiguration cfg | cfg.hasFlow(node1, node2)) and
// This configuration should not be able to cross function boundaries, but // This configuration should not be able to cross function boundaries, but
// we double-check here just to be sure. // we double-check here just to be sure.
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) node1.getEnclosingCallable() = node2.getEnclosingCallable()
} }
} }

View File

@@ -7,7 +7,6 @@ private import semmle.code.cpp.controlflow.SSA
private import semmle.code.cpp.dataflow.internal.SubBasicBlocks private import semmle.code.cpp.dataflow.internal.SubBasicBlocks
private import semmle.code.cpp.dataflow.internal.AddressFlow private import semmle.code.cpp.dataflow.internal.AddressFlow
private import semmle.code.cpp.models.implementations.Iterator private import semmle.code.cpp.models.implementations.Iterator
private import semmle.code.cpp.models.interfaces.PointerWrapper
/** /**
* A conceptual variable that is assigned only once, like an SSA variable. This * A conceptual variable that is assigned only once, like an SSA variable. This
@@ -159,14 +158,18 @@ private module PartialDefinitions {
Expr innerDefinedExpr; Expr innerDefinedExpr;
IteratorPartialDefinition() { IteratorPartialDefinition() {
innerDefinedExpr = getInnerDefinedExpr(this, node) and exists(Expr convertedInner |
( not this instanceof Conversion and
innerDefinedExpr.(Call).getQualifier() = getAnIteratorAccess(collection) valueToUpdate(convertedInner, this.getFullyConverted(), node) and
or innerDefinedExpr = convertedInner.getUnconverted() and
innerDefinedExpr.(Call).getQualifier() = collection.getAnAccess() and (
collection instanceof IteratorParameter innerDefinedExpr.(Call).getQualifier() = getAnIteratorAccess(collection)
) and or
innerDefinedExpr.(Call).getTarget() instanceof IteratorPointerDereferenceMemberOperator innerDefinedExpr.(Call).getQualifier() = collection.getAnAccess() and
collection instanceof IteratorParameter
) and
innerDefinedExpr.(Call).getTarget() instanceof IteratorPointerDereferenceMemberOperator
)
or or
// iterators passed by value without a copy constructor // iterators passed by value without a copy constructor
exists(Call call | exists(Call call |
@@ -204,18 +207,16 @@ private module PartialDefinitions {
} }
} }
private Expr getInnerDefinedExpr(Expr e, ControlFlowNode node) {
not e instanceof Conversion and
exists(Expr convertedInner |
valueToUpdate(convertedInner, e.getFullyConverted(), node) and
result = convertedInner.getUnconverted()
)
}
class VariablePartialDefinition extends PartialDefinition { class VariablePartialDefinition extends PartialDefinition {
Expr innerDefinedExpr; Expr innerDefinedExpr;
VariablePartialDefinition() { innerDefinedExpr = getInnerDefinedExpr(this, node) } VariablePartialDefinition() {
not this instanceof Conversion and
exists(Expr convertedInner |
valueToUpdate(convertedInner, this.getFullyConverted(), node) and
innerDefinedExpr = convertedInner.getUnconverted()
)
}
deprecated override predicate partiallyDefines(Variable v) { deprecated override predicate partiallyDefines(Variable v) {
innerDefinedExpr = v.getAnAccess() innerDefinedExpr = v.getAnAccess()
@@ -295,8 +296,7 @@ module FlowVar_internal {
// treating them as immutable, but for data flow it gives better results in // treating them as immutable, but for data flow it gives better results in
// practice to make the variable synonymous with its contents. // practice to make the variable synonymous with its contents.
not v.getUnspecifiedType() instanceof ReferenceType and not v.getUnspecifiedType() instanceof ReferenceType and
not v instanceof IteratorParameter and not v instanceof IteratorParameter
not v instanceof PointerWrapperParameter
} }
/** /**
@@ -644,19 +644,10 @@ module FlowVar_internal {
predicate parameterIsNonConstReference(Parameter p) { predicate parameterIsNonConstReference(Parameter p) {
exists(ReferenceType refType | exists(ReferenceType refType |
refType = p.getUnderlyingType() and refType = p.getUnderlyingType() and
( not refType.getBaseType().isConst()
not refType.getBaseType().isConst()
or
// A field of a parameter of type `const std::shared_ptr<A>& p` can still be changed even though
// the base type of the reference is `const`.
refType.getBaseType().getUnspecifiedType() =
any(PointerWrapper wrapper | not wrapper.pointsToConst())
)
) )
or or
p instanceof IteratorParameter p instanceof IteratorParameter
or
p instanceof PointerWrapperParameter
} }
/** /**
@@ -845,10 +836,6 @@ module FlowVar_internal {
IteratorParameter() { this.getUnspecifiedType() instanceof Iterator } IteratorParameter() { this.getUnspecifiedType() instanceof Iterator }
} }
class PointerWrapperParameter extends Parameter {
PointerWrapperParameter() { this.getUnspecifiedType() instanceof PointerWrapper }
}
/** /**
* Holds if `v` is initialized to have value `assignedExpr`. * Holds if `v` is initialized to have value `assignedExpr`.
*/ */

View File

@@ -11,7 +11,6 @@
private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.models.interfaces.DataFlow
private import semmle.code.cpp.models.interfaces.Taint private import semmle.code.cpp.models.interfaces.Taint
private import semmle.code.cpp.models.interfaces.Iterator private import semmle.code.cpp.models.interfaces.Iterator
private import semmle.code.cpp.models.interfaces.PointerWrapper
private module DataFlow { private module DataFlow {
import semmle.code.cpp.dataflow.internal.DataFlowUtil import semmle.code.cpp.dataflow.internal.DataFlowUtil
@@ -142,10 +141,7 @@ private predicate noFlowFromChildExpr(Expr e) {
or or
e instanceof LogicalOrExpr e instanceof LogicalOrExpr
or or
// Allow taint from `operator*` on smart pointers. e instanceof Call
exists(Call call | e = call |
not call.getTarget() = any(PointerWrapper wrapper).getAnUnwrapperFunction()
)
or or
e instanceof SizeofOperator e instanceof SizeofOperator
or or

View File

@@ -314,7 +314,6 @@ class OverloadedPointerDereferenceFunction extends Function {
* T1 operator*(const T2 &); * T1 operator*(const T2 &);
* T1 a; T2 b; * T1 a; T2 b;
* a = *b; * a = *b;
* ```
*/ */
class OverloadedPointerDereferenceExpr extends FunctionCall { class OverloadedPointerDereferenceExpr extends FunctionCall {
OverloadedPointerDereferenceExpr() { OverloadedPointerDereferenceExpr() {

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -2133,8 +2133,11 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) { private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
localFlowEntry(node, config) and exists(Cc cc0 |
result = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(node)) cc = pragma[only_bind_into](cc0) and
localFlowEntry(node, config) and
result = getLocalCallContext(cc0, getNodeEnclosingCallable(node))
)
} }
private predicate localStep( private predicate localStep(
@@ -3129,7 +3132,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
conf = mid.getConfiguration() and conf = mid.getConfiguration() and
cc = mid.getCallContext() and cc = mid.getCallContext() and
sc = mid.getSummaryCtx() and sc = mid.getSummaryCtx() and
localCC = getLocalCallContext(pragma[only_bind_out](cc), getNodeEnclosingCallable(midnode)) and localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
ap0 = mid.getAp() ap0 = mid.getAp()
| |
localFlowBigStep(midnode, node, true, _, conf, localCC) and localFlowBigStep(midnode, node, true, _, conf, localCC) and

View File

@@ -362,22 +362,15 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
/** /**
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to. * Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
* For instance, an update to a field of a struct containing only one field. Even if the store does * For instance, an update to a field of a struct containing only one field. For these cases we
* have a chi instruction, a subsequent use of the result of the store may be linked directly to the * attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case
* result of the store as an inexact definition if the store totally overlaps the use. For these * (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`.
* cases we attach the PostUpdateNode to the store instruction. There's no obvious pre update node
* for this case (as the entire memory is updated), so `getPreUpdateNode` is implemented as
* `none()`.
*/ */
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode { private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
override StoreInstruction instr; override StoreInstruction instr;
ExplicitSingleFieldStoreQualifierNode() { ExplicitSingleFieldStoreQualifierNode() {
( not exists(ChiInstruction chi | chi.getPartial() = instr) and
instr.getAUse().isDefinitionInexact()
or
not exists(ChiInstruction chi | chi.getPartial() = instr)
) and
// Without this condition any store would create a `PostUpdateNode`. // Without this condition any store would create a `PostUpdateNode`.
instr.getDestinationAddress() instanceof FieldAddressInstruction instr.getDestinationAddress() instanceof FieldAddressInstruction
} }

View File

@@ -6,7 +6,34 @@ private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import PrintIRUtilities
/**
* Gets a short ID for an IR dataflow node.
* - For `Instruction`s, this is just the result ID of the instruction (e.g. `m128`).
* - For `Operand`s, this is the label of the operand, prefixed with the result ID of the
* instruction and a dot (e.g. `m128.left`).
* - For `Variable`s, this is the qualified name of the variable.
*/
private string nodeId(DataFlow::Node node, int order1, int order2) {
exists(Instruction instruction | instruction = node.asInstruction() |
result = instruction.getResultId() and
order1 = instruction.getBlock().getDisplayIndex() and
order2 = instruction.getDisplayIndexInBlock()
)
or
exists(Operand operand, Instruction instruction |
operand = node.asOperand() and
instruction = operand.getUse()
|
result = instruction.getResultId() + "." + operand.getDumpId() and
order1 = instruction.getBlock().getDisplayIndex() and
order2 = instruction.getDisplayIndexInBlock()
)
or
result = "var(" + node.asVariable().getQualifiedName() + ")" and
order1 = 1000000 and
order2 = 0
}
/** /**
* Gets the local dataflow from other nodes in the same function to this node. * Gets the local dataflow from other nodes in the same function to this node.

View File

@@ -1,33 +0,0 @@
/**
* Print the dataflow local store steps in IR dumps.
*/
private import cpp
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
// that the cached IR gets the same checksum here as it does in queries that use
// `ValueNumbering` without `DataFlow`.
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import PrintIRUtilities
/**
* Property provider for local IR dataflow store steps.
*/
class LocalFlowPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instruction, string key) {
exists(DataFlow::Node objectNode, Content content |
key = "content[" + content.toString() + "]" and
instruction = objectNode.asInstruction() and
result =
strictconcat(string element, DataFlow::Node fieldNode |
storeStep(fieldNode, content, objectNode) and
element = nodeId(fieldNode, _, _)
|
element, ", "
)
)
}
}

View File

@@ -1,39 +0,0 @@
/**
* Shared utilities used when printing dataflow annotations in IR dumps.
*/
private import cpp
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
// that the cached IR gets the same checksum here as it does in queries that use
// `ValueNumbering` without `DataFlow`.
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
/**
* Gets a short ID for an IR dataflow node.
* - For `Instruction`s, this is just the result ID of the instruction (e.g. `m128`).
* - For `Operand`s, this is the label of the operand, prefixed with the result ID of the
* instruction and a dot (e.g. `m128.left`).
* - For `Variable`s, this is the qualified name of the variable.
*/
string nodeId(DataFlow::Node node, int order1, int order2) {
exists(Instruction instruction | instruction = node.asInstruction() |
result = instruction.getResultId() and
order1 = instruction.getBlock().getDisplayIndex() and
order2 = instruction.getDisplayIndexInBlock()
)
or
exists(Operand operand, Instruction instruction |
operand = node.asOperand() and
instruction = operand.getUse()
|
result = instruction.getResultId() + "." + operand.getDumpId() and
order1 = instruction.getBlock().getDisplayIndex() and
order2 = instruction.getDisplayIndexInBlock()
)
or
result = "var(" + node.asVariable().getQualifiedName() + ")" and
order1 = 1000000 and
order2 = 0
}

View File

@@ -1,109 +0,0 @@
/**
* Predicates to compute the modeled side effects of calls during IR construction.
*
* These are used in `TranslatedElement.qll` to generate the `TTranslatedSideEffect` instances, and
* also in `TranslatedCall.qll` to inject the actual side effect instructions.
*/
private import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.models.interfaces.SideEffect
/**
* Holds if the specified call has a side effect that does not come from a `SideEffectFunction`
* model.
*/
private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buffer, boolean isWrite) {
not call.getTarget() instanceof SideEffectFunction and
(
exists(MemberFunction mfunc |
// A non-static member function, including a constructor or destructor, may write to `*this`,
// and may also read from `*this` if it is not a constructor.
i = -1 and
mfunc = call.getTarget() and
not mfunc.isStatic() and
buffer = false and
(
isWrite = false and not mfunc instanceof Constructor
or
isWrite = true and not mfunc instanceof ConstMemberFunction
)
)
or
exists(Expr expr |
// A pointer-like argument is assumed to read from the pointed-to buffer, and may write to the
// buffer as well unless the pointer points to a `const` value.
i >= 0 and
buffer = true and
expr = call.getArgument(i).getFullyConverted() and
exists(Type t | t = expr.getUnspecifiedType() |
t instanceof ArrayType or
t instanceof PointerType or
t instanceof ReferenceType
) and
(
isWrite = true and
not call.getTarget().getParameter(i).getType().isDeeplyConstBelow()
or
isWrite = false
)
)
)
}
/**
* Returns a side effect opcode for parameter index `i` of the specified call.
*
* This predicate will return at most two results: one read side effect, and one write side effect.
*/
Opcode getASideEffectOpcode(Call call, ParameterIndex i) {
exists(boolean buffer |
(
call.getTarget().(SideEffectFunction).hasSpecificReadSideEffect(i, buffer)
or
not call.getTarget() instanceof SideEffectFunction and
hasDefaultSideEffect(call, i, buffer, false)
) and
if exists(call.getTarget().(SideEffectFunction).getParameterSizeIndex(i))
then (
buffer = true and
result instanceof Opcode::SizedBufferReadSideEffect
) else (
buffer = false and result instanceof Opcode::IndirectReadSideEffect
or
buffer = true and result instanceof Opcode::BufferReadSideEffect
)
)
or
exists(boolean buffer, boolean mustWrite |
(
call.getTarget().(SideEffectFunction).hasSpecificWriteSideEffect(i, buffer, mustWrite)
or
not call.getTarget() instanceof SideEffectFunction and
hasDefaultSideEffect(call, i, buffer, true) and
mustWrite = false
) and
if exists(call.getTarget().(SideEffectFunction).getParameterSizeIndex(i))
then (
buffer = true and
mustWrite = false and
result instanceof Opcode::SizedBufferMayWriteSideEffect
or
buffer = true and
mustWrite = true and
result instanceof Opcode::SizedBufferMustWriteSideEffect
) else (
buffer = false and
mustWrite = false and
result instanceof Opcode::IndirectMayWriteSideEffect
or
buffer = false and
mustWrite = true and
result instanceof Opcode::IndirectMustWriteSideEffect
or
buffer = true and mustWrite = false and result instanceof Opcode::BufferMayWriteSideEffect
or
buffer = true and mustWrite = true and result instanceof Opcode::BufferMustWriteSideEffect
)
)
}

View File

@@ -4,7 +4,6 @@ private import semmle.code.cpp.ir.implementation.internal.OperandTag
private import semmle.code.cpp.ir.internal.CppType private import semmle.code.cpp.ir.internal.CppType
private import semmle.code.cpp.models.interfaces.SideEffect private import semmle.code.cpp.models.interfaces.SideEffect
private import InstructionTag private import InstructionTag
private import SideEffects
private import TranslatedElement private import TranslatedElement
private import TranslatedExpr private import TranslatedExpr
private import TranslatedFunction private import TranslatedFunction
@@ -425,15 +424,12 @@ class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSi
} }
class TranslatedStructorCallSideEffects extends TranslatedCallSideEffects { class TranslatedStructorCallSideEffects extends TranslatedCallSideEffects {
TranslatedStructorCallSideEffects() { TranslatedStructorCallSideEffects() { getParent().(TranslatedStructorCall).hasQualifier() }
getParent().(TranslatedStructorCall).hasQualifier() and
getASideEffectOpcode(expr, -1) instanceof WriteSideEffectOpcode
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType t) { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType t) {
opcode instanceof Opcode::IndirectMayWriteSideEffect and
tag instanceof OnlyInstructionTag and tag instanceof OnlyInstructionTag and
t = getTypeForPRValue(expr.getTarget().getDeclaringType()) and t = getTypeForPRValue(expr.getTarget().getDeclaringType())
opcode = getASideEffectOpcode(expr, -1).(WriteSideEffectOpcode)
} }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
@@ -464,11 +460,9 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
Call call; Call call;
Expr arg; Expr arg;
int index; int index;
SideEffectOpcode sideEffectOpcode; boolean write;
TranslatedSideEffect() { TranslatedSideEffect() { this = TTranslatedArgumentSideEffect(call, arg, index, write) }
this = TTranslatedArgumentSideEffect(call, arg, index, sideEffectOpcode)
}
override Locatable getAST() { result = arg } override Locatable getAST() { result = arg }
@@ -478,13 +472,13 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
int getArgumentIndex() { result = index } int getArgumentIndex() { result = index }
predicate isWrite() { sideEffectOpcode instanceof WriteSideEffectOpcode } predicate isWrite() { write = true }
override string toString() { override string toString() {
isWrite() and write = true and
result = "(write side effect for " + arg.toString() + ")" result = "(write side effect for " + arg.toString() + ")"
or or
not isWrite() and write = false and
result = "(read side effect for " + arg.toString() + ")" result = "(read side effect for " + arg.toString() + ")"
} }
@@ -495,29 +489,29 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
isWrite() and
hasSpecificWriteSideEffect(opcode) and
tag = OnlyInstructionTag() and tag = OnlyInstructionTag() and
opcode = sideEffectOpcode and
( (
isWrite() and opcode instanceof BufferAccessOpcode and
( type = getUnknownType()
opcode instanceof BufferAccessOpcode and or
type = getUnknownType() not opcode instanceof BufferAccessOpcode and
or exists(Type baseType | baseType = arg.getUnspecifiedType().(DerivedType).getBaseType() |
not opcode instanceof BufferAccessOpcode and if baseType instanceof VoidType
exists(Type baseType | baseType = arg.getUnspecifiedType().(DerivedType).getBaseType() | then type = getUnknownType()
if baseType instanceof VoidType else type = getTypeForPRValueOrUnknown(baseType)
then type = getUnknownType()
else type = getTypeForPRValueOrUnknown(baseType)
)
or
index = -1 and
not arg.getUnspecifiedType() instanceof DerivedType and
type = getTypeForPRValueOrUnknown(arg.getUnspecifiedType())
) )
or or
not isWrite() and index = -1 and
type = getVoidType() not arg.getUnspecifiedType() instanceof DerivedType and
type = getTypeForPRValueOrUnknown(arg.getUnspecifiedType())
) )
or
not isWrite() and
hasSpecificReadSideEffect(opcode) and
tag = OnlyInstructionTag() and
type = getVoidType()
} }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
@@ -541,7 +535,7 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
override CppType getInstructionMemoryOperandType(InstructionTag tag, TypedOperandTag operandTag) { override CppType getInstructionMemoryOperandType(InstructionTag tag, TypedOperandTag operandTag) {
not isWrite() and not isWrite() and
if sideEffectOpcode instanceof BufferAccessOpcode if hasSpecificReadSideEffect(any(BufferAccessOpcode op))
then then
result = getUnknownType() and result = getUnknownType() and
tag instanceof OnlyInstructionTag and tag instanceof OnlyInstructionTag and
@@ -563,6 +557,56 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff
) )
} }
predicate hasSpecificWriteSideEffect(Opcode op) {
exists(boolean buffer, boolean mustWrite |
if exists(call.getTarget().(SideEffectFunction).getParameterSizeIndex(index))
then
call.getTarget().(SideEffectFunction).hasSpecificWriteSideEffect(index, true, mustWrite) and
buffer = true and
(
mustWrite = false and op instanceof Opcode::SizedBufferMayWriteSideEffect
or
mustWrite = true and op instanceof Opcode::SizedBufferMustWriteSideEffect
)
else (
call.getTarget().(SideEffectFunction).hasSpecificWriteSideEffect(index, buffer, mustWrite) and
(
buffer = true and mustWrite = false and op instanceof Opcode::BufferMayWriteSideEffect
or
buffer = false and mustWrite = false and op instanceof Opcode::IndirectMayWriteSideEffect
or
buffer = true and mustWrite = true and op instanceof Opcode::BufferMustWriteSideEffect
or
buffer = false and mustWrite = true and op instanceof Opcode::IndirectMustWriteSideEffect
)
)
)
or
not call.getTarget() instanceof SideEffectFunction and
getArgumentIndex() != -1 and
op instanceof Opcode::BufferMayWriteSideEffect
or
not call.getTarget() instanceof SideEffectFunction and
getArgumentIndex() = -1 and
op instanceof Opcode::IndirectMayWriteSideEffect
}
predicate hasSpecificReadSideEffect(Opcode op) {
exists(boolean buffer |
call.getTarget().(SideEffectFunction).hasSpecificReadSideEffect(index, buffer) and
if exists(call.getTarget().(SideEffectFunction).getParameterSizeIndex(index))
then buffer = true and op instanceof Opcode::SizedBufferReadSideEffect
else (
buffer = true and op instanceof Opcode::BufferReadSideEffect
or
buffer = false and op instanceof Opcode::IndirectReadSideEffect
)
)
or
not call.getTarget() instanceof SideEffectFunction and
op instanceof Opcode::BufferReadSideEffect
}
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
tag = OnlyInstructionTag() and tag = OnlyInstructionTag() and
result = getTranslatedCallInstruction(call) result = getTranslatedCallInstruction(call)

View File

@@ -12,7 +12,6 @@ private import TranslatedStmt
private import TranslatedExpr private import TranslatedExpr
private import IRConstruction private import IRConstruction
private import semmle.code.cpp.models.interfaces.SideEffect private import semmle.code.cpp.models.interfaces.SideEffect
private import SideEffects
/** /**
* Gets the "real" parent of `expr`. This predicate treats conversions as if * Gets the "real" parent of `expr`. This predicate treats conversions as if
@@ -636,15 +635,46 @@ newtype TTranslatedElement =
// The side effects of an allocation, i.e. `new`, `new[]` or `malloc` // The side effects of an allocation, i.e. `new`, `new[]` or `malloc`
TTranslatedAllocationSideEffects(AllocationExpr expr) { not ignoreExpr(expr) } or TTranslatedAllocationSideEffects(AllocationExpr expr) { not ignoreExpr(expr) } or
// A precise side effect of an argument to a `Call` // A precise side effect of an argument to a `Call`
TTranslatedArgumentSideEffect(Call call, Expr expr, int n, SideEffectOpcode opcode) { TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) {
not ignoreExpr(expr) and
not ignoreExpr(call) and
( (
n >= 0 and expr = call.getArgument(n).getFullyConverted() expr = call.getArgument(n).getFullyConverted()
or or
n = -1 and expr = call.getQualifier().getFullyConverted() expr = call.getQualifier().getFullyConverted() and
n = -1 and
// Exclude calls to static member functions. They don't modify the qualifier
not exists(MemberFunction func | func = call.getTarget() and func.isStatic())
) and ) and
opcode = getASideEffectOpcode(call, n) (
call.getTarget().(SideEffectFunction).hasSpecificReadSideEffect(n, _) and
isWrite = false
or
call.getTarget().(SideEffectFunction).hasSpecificWriteSideEffect(n, _, _) and
isWrite = true
or
not call.getTarget() instanceof SideEffectFunction and
exists(Type t | t = expr.getUnspecifiedType() |
t instanceof ArrayType or
t instanceof PointerType or
t instanceof ReferenceType
) and
(
isWrite = true and
not call.getTarget().getParameter(n).getType().isDeeplyConstBelow()
or
isWrite = false
)
or
not call.getTarget() instanceof SideEffectFunction and
n = -1 and
(
isWrite = true and
not call.getTarget() instanceof ConstMemberFunction
or
isWrite = false
)
) and
not ignoreExpr(expr) and
not ignoreExpr(call)
} }
/** /**

View File

@@ -13,25 +13,23 @@ private class UniqueOrSharedPtr extends Class, PointerWrapper {
or or
result.getClassAndName(["operator->", "get"]) = this result.getClassAndName(["operator->", "get"]) = this
} }
override predicate pointsToConst() { this.getTemplateArgument(0).(Type).isConst() }
} }
/** Any function that unwraps a pointer wrapper class to reveal the underlying pointer. */ /** Any function that unwraps a pointer wrapper class to reveal the underlying pointer. */
private class PointerWrapperFlow extends TaintFunction, DataFlowFunction { private class PointerWrapperDataFlow extends DataFlowFunction {
PointerWrapperFlow() { PointerWrapperDataFlow() {
this = any(PointerWrapper wrapper).getAnUnwrapperFunction() and this = any(PointerWrapper wrapper).getAnUnwrapperFunction() and
not this.getUnspecifiedType() instanceof ReferenceType not this.getUnspecifiedType() instanceof ReferenceType
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and output.isReturnValue()
or
input.isQualifierObject() and output.isReturnValueDeref()
or
input.isReturnValueDeref() and input.isReturnValueDeref() and
output.isQualifierObject() output.isQualifierObject()
} }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and output.isReturnValue()
}
} }
/** /**

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