mirror of
https://github.com/github/codeql.git
synced 2026-05-26 17:11:24 +02:00
Compare commits
231 Commits
z80coder/q
...
lgtm/v1.30
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
413c0a8f4f | ||
|
|
67e3f5edbc | ||
|
|
ccc6291844 | ||
|
|
ab218421da | ||
|
|
e178626226 | ||
|
|
a1cdf256ad | ||
|
|
4ce8ccc52b | ||
|
|
51e8b4c7ed | ||
|
|
c3ed74d63c | ||
|
|
e0110bd25e | ||
|
|
e7dde79d50 | ||
|
|
fdf77ad2b9 | ||
|
|
9e51908b02 | ||
|
|
2a02ce137a | ||
|
|
f2d6bcd767 | ||
|
|
fd60c6e1ad | ||
|
|
1dfcf427aa | ||
|
|
bfb573c86a | ||
|
|
6b4eaf674f | ||
|
|
b9964799f3 | ||
|
|
6457f42497 | ||
|
|
344e380fa3 | ||
|
|
a2c1995b9b | ||
|
|
f8380dabe0 | ||
|
|
23fb3455c0 | ||
|
|
1f8a291d6f | ||
|
|
5ba70ff3b6 | ||
|
|
c3007ff713 | ||
|
|
de1697ab39 | ||
|
|
5f5af4a29e | ||
|
|
ded3c52a34 | ||
|
|
1334d207fa | ||
|
|
ec533c8465 | ||
|
|
8845529548 | ||
|
|
421bd1b970 | ||
|
|
882caf4011 | ||
|
|
0cbf136e21 | ||
|
|
69f1c18a39 | ||
|
|
3da98ecb73 | ||
|
|
a2104de8a0 | ||
|
|
f16d77615d | ||
|
|
df0da980ea | ||
|
|
27a40fb5cf | ||
|
|
97c75de771 | ||
|
|
e6bc45ee3b | ||
|
|
d3af687767 | ||
|
|
bdb2d8ba16 | ||
|
|
0303c279e2 | ||
|
|
1156581b52 | ||
|
|
accfd482d4 | ||
|
|
6acb87d542 | ||
|
|
f21398ce84 | ||
|
|
445c420a3d | ||
|
|
07c7de5cfd | ||
|
|
7c032f6cb4 | ||
|
|
f35e866799 | ||
|
|
0c698996aa | ||
|
|
3df7793803 | ||
|
|
8e46eeb88c | ||
|
|
55492ef348 | ||
|
|
118d0d9ff5 | ||
|
|
3a30f58f74 | ||
|
|
400802c5ce | ||
|
|
748b2d2507 | ||
|
|
fef6770a21 | ||
|
|
51e3c582de | ||
|
|
8c18aaae74 | ||
|
|
27f786b41e | ||
|
|
4133eb15d5 | ||
|
|
d196c77b3d | ||
|
|
f5471e34f8 | ||
|
|
43b5d502b8 | ||
|
|
ba7a10de68 | ||
|
|
9e259b67bb | ||
|
|
a7aff11140 | ||
|
|
5765f3684c | ||
|
|
5db80dac51 | ||
|
|
c138a2796f | ||
|
|
8250fb4cf7 | ||
|
|
a86ba3b14e | ||
|
|
dae5af6be8 | ||
|
|
f66a08155b | ||
|
|
29cd346702 | ||
|
|
6c7114804e | ||
|
|
7644d60dae | ||
|
|
8019b52838 | ||
|
|
4c1089fcf1 | ||
|
|
66c6a4d899 | ||
|
|
d17879e1f9 | ||
|
|
aa92fe8c90 | ||
|
|
06b77eb4af | ||
|
|
06575efce9 | ||
|
|
d3f2894a8e | ||
|
|
0aefb1551e | ||
|
|
e9d4e38364 | ||
|
|
44c1e3f28d | ||
|
|
aedfc428c2 | ||
|
|
b78ec4c693 | ||
|
|
20637555b5 | ||
|
|
ac5b2bfa41 | ||
|
|
f93c63aa60 | ||
|
|
ec4d43fed2 | ||
|
|
2f559696e4 | ||
|
|
aa9444b16c | ||
|
|
f18492e39b | ||
|
|
9ffdfb263f | ||
|
|
313e0c63fd | ||
|
|
8b53cca3e8 | ||
|
|
ed006d7283 | ||
|
|
af47cba09a | ||
|
|
30f8894854 | ||
|
|
571995c929 | ||
|
|
31c8e4ed2a | ||
|
|
7a9e41c97d | ||
|
|
f44f33788f | ||
|
|
380d238c31 | ||
|
|
8fbd056b4e | ||
|
|
d612687ae7 | ||
|
|
f7f9b4d3f4 | ||
|
|
ea1ee68fe1 | ||
|
|
5717a216d3 | ||
|
|
4d12d8dd5e | ||
|
|
bebf4ca8fc | ||
|
|
d058d36b1f | ||
|
|
055432530f | ||
|
|
c1864531cd | ||
|
|
383437c571 | ||
|
|
dd12eab29b | ||
|
|
c03f189dec | ||
|
|
e6c60ebd41 | ||
|
|
28912c508f | ||
|
|
5054d5b555 | ||
|
|
1e27ddf7c7 | ||
|
|
9ad9b81327 | ||
|
|
83f87f0272 | ||
|
|
de4b655ddb | ||
|
|
45753e519f | ||
|
|
626009ea60 | ||
|
|
9866214ebe | ||
|
|
46144fe0a3 | ||
|
|
974ad070d1 | ||
|
|
560413f94a | ||
|
|
77fcb8a18f | ||
|
|
e4d9f5f29e | ||
|
|
a0311609d0 | ||
|
|
e47e824e16 | ||
|
|
4a331814a2 | ||
|
|
f5a47126b1 | ||
|
|
5bdfcc8436 | ||
|
|
c13d83ce40 | ||
|
|
0c9ca4546c | ||
|
|
7af9d75abc | ||
|
|
ab2e0fdb18 | ||
|
|
40043f13c6 | ||
|
|
c1af8b93c2 | ||
|
|
83a8a60676 | ||
|
|
ba89653dff | ||
|
|
db4b781fef | ||
|
|
cff63fa7d7 | ||
|
|
a9286e897b | ||
|
|
f49605569b | ||
|
|
a4ea7129c2 | ||
|
|
83f1b2ca5d | ||
|
|
89775428b4 | ||
|
|
3e6389cad6 | ||
|
|
95a93fe033 | ||
|
|
e2c6dd7d56 | ||
|
|
61cc84ba69 | ||
|
|
ce68a6d1c5 | ||
|
|
e7abe43e3e | ||
|
|
e309d8227c | ||
|
|
d840796494 | ||
|
|
1d00730753 | ||
|
|
8d9a797b75 | ||
|
|
6f297f4e9c | ||
|
|
4b5599fe17 | ||
|
|
cb934e17b1 | ||
|
|
b1bca85162 | ||
|
|
5a7efd0fee | ||
|
|
dba26a92e9 | ||
|
|
6ce1524192 | ||
|
|
1cc5e54357 | ||
|
|
579de0c3f0 | ||
|
|
f8fc583af3 | ||
|
|
6f81685f48 | ||
|
|
a5bae30d81 | ||
|
|
b142a79a35 | ||
|
|
f82683cdf4 | ||
|
|
4891a649a2 | ||
|
|
8208f92f59 | ||
|
|
712d71856b | ||
|
|
59da2cdf69 | ||
|
|
6664a3814a | ||
|
|
5fa6ecc5f1 | ||
|
|
fa40d59332 | ||
|
|
a62f181d42 | ||
|
|
dd6085f0a6 | ||
|
|
3da1c2bde1 | ||
|
|
041c2c77b3 | ||
|
|
0f0bd34958 | ||
|
|
cf2ee0672f | ||
|
|
35cba17642 | ||
|
|
b68d280129 | ||
|
|
1ff56d5143 | ||
|
|
7bf285a52e | ||
|
|
08f6d1ab80 | ||
|
|
5de79b4ffe | ||
|
|
1e45fa9ed4 | ||
|
|
a4da528812 | ||
|
|
23d4d035e5 | ||
|
|
65f4ccce28 | ||
|
|
0031ed39ec | ||
|
|
5ee9684435 | ||
|
|
122f6385e6 | ||
|
|
6896b20dcd | ||
|
|
511bee7a1a | ||
|
|
b82425a35c | ||
|
|
2d4a2e0d44 | ||
|
|
88634b81bf | ||
|
|
6e8d56f044 | ||
|
|
21ab8b0f63 | ||
|
|
6168b15bbc | ||
|
|
7f0a7bbec9 | ||
|
|
7832e8572b | ||
|
|
0359c381e1 | ||
|
|
f102fa1d33 | ||
|
|
e383e44d36 | ||
|
|
ea1d18ed60 | ||
|
|
41e15cd497 | ||
|
|
a33c076f5f | ||
|
|
6173b11274 |
3
.github/labeler.yml
vendored
3
.github/labeler.yml
vendored
@@ -26,3 +26,6 @@ documentation:
|
||||
- "**/*.qhelp"
|
||||
- "**/*.md"
|
||||
- docs/**/*
|
||||
|
||||
"QL-for-QL":
|
||||
- ql/**/*
|
||||
1
.github/workflows/check-change-note.yml
vendored
1
.github/workflows/check-change-note.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
- "*/ql/src/**/*.ql"
|
||||
- "*/ql/src/**/*.qll"
|
||||
- "!**/experimental/**"
|
||||
- "!ql/**"
|
||||
|
||||
jobs:
|
||||
check-change-note:
|
||||
|
||||
60
.github/workflows/ql-for-ql-build.yml
vendored
60
.github/workflows/ql-for-ql-build.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- name: Get CodeQL version
|
||||
@@ -56,27 +56,46 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
- name: Cache entire extractor
|
||||
id: cache-extractor
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
ql/target/release/ql-autobuilder
|
||||
ql/target/release/ql-autobuilder.exe
|
||||
ql/target/release/ql-extractor
|
||||
ql/target/release/ql-extractor.exe
|
||||
key: ${{ runner.os }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
|
||||
- name: Cache cargo
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
ql/target
|
||||
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
|
||||
- name: Check formatting
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd ql; cargo fmt --all -- --check
|
||||
- name: Build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd ql; cargo build --verbose
|
||||
- name: Run tests
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd ql; cargo test --verbose
|
||||
- name: Release build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd ql; cargo build --release
|
||||
- name: Generate dbscheme
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: ql/target/release/ql-generator --dbscheme ql/ql/src/ql.dbscheme --library ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: extractor-ubuntu-latest
|
||||
path: |
|
||||
ql/target/release/ql-autobuilder
|
||||
ql/target/release/ql-autobuilder.exe
|
||||
ql/target/release/ql-extractor
|
||||
ql/target/release/ql-extractor.exe
|
||||
retention-days: 1
|
||||
@@ -101,6 +120,10 @@ jobs:
|
||||
unzip query-pack-zip/*.zip -d pack
|
||||
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats pack/
|
||||
mkdir -p pack/tools/linux64
|
||||
if [[ -f linux64/ql-autobuilder ]]; then
|
||||
cp linux64/ql-autobuilder pack/tools/linux64/autobuilder
|
||||
chmod +x pack/tools/linux64/autobuilder
|
||||
fi
|
||||
if [[ -f linux64/ql-extractor ]]; then
|
||||
cp linux64/ql-extractor pack/tools/linux64/extractor
|
||||
chmod +x pack/tools/linux64/extractor
|
||||
@@ -112,13 +135,16 @@ jobs:
|
||||
name: codeql-ql-pack
|
||||
path: codeql-ql.zip
|
||||
retention-days: 1
|
||||
analyze:
|
||||
analyze:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
strategy:
|
||||
matrix:
|
||||
folder: [cpp, csharp, java, javascript, python, ql, ruby]
|
||||
|
||||
needs:
|
||||
- package
|
||||
|
||||
steps:
|
||||
|
||||
steps:
|
||||
- name: Download pack
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
@@ -140,13 +166,27 @@ jobs:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Create CodeQL config file
|
||||
run: |
|
||||
echo "paths:" > ${CONF}
|
||||
echo " - ${FOLDER}" >> ${CONF}
|
||||
echo "paths-ignore:" >> ${CONF}
|
||||
echo " - ql/ql/test" >> ${CONF}
|
||||
echo "Config file: "
|
||||
cat ${CONF}
|
||||
env:
|
||||
CONF: ./ql-for-ql-config.yml
|
||||
FOLDER: ${{ matrix.folder }}
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
with:
|
||||
languages: ql
|
||||
db-location: ${{ runner.temp }}/db
|
||||
config-file: ./ql-for-ql-config.yml
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@esbena/ql
|
||||
uses: github/codeql-action/analyze@erik-krogh/ql
|
||||
with:
|
||||
category: "ql-for-ql-${{ matrix.folder }}"
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: actions/cache@v2
|
||||
|
||||
6
.github/workflows/ql-for-ql-tests.yml
vendored
6
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -4,11 +4,11 @@ on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- ql/*
|
||||
- "ql/**"
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- ql/*
|
||||
- "ql/**"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: actions/cache@v2
|
||||
|
||||
@@ -452,9 +452,15 @@
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImplCommon.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll"
|
||||
],
|
||||
"CryptoAlgorithms Python/JS": [
|
||||
"CryptoAlgorithms Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
|
||||
"python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll"
|
||||
"python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll"
|
||||
],
|
||||
"CryptoAlgorithmNames Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll",
|
||||
"python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll"
|
||||
],
|
||||
"SensitiveDataHeuristics Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
|
||||
`isFromSystemMacroDefinition` for identifying code that originates from a
|
||||
macro outside the project being analyzed.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* A new query `cpp/non-https-url` has been added for C/C++. The query flags uses of `http` URLs that might be better replaced with `https`.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* A new query `cpp/certificate-not-checked` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* A new query `cpp/certificate-result-conflation` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved, reducing the number of false positive results when encryption is present.
|
||||
@@ -1,3 +1,9 @@
|
||||
## 0.0.7
|
||||
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -73,7 +73,7 @@ class Options extends string {
|
||||
* __assume(0);
|
||||
* ```
|
||||
* (note that in this case if the hint is wrong and the expression is reached at
|
||||
* runtime, the program's behaviour is undefined)
|
||||
* runtime, the program's behavior is undefined)
|
||||
*/
|
||||
predicate exprExits(Expr e) {
|
||||
e.(AssumeExpr).getChild(0).(CompileTimeConstantInt).getIntValue() = 0 or
|
||||
|
||||
@@ -50,7 +50,7 @@ class CustomOptions extends Options {
|
||||
* __assume(0);
|
||||
* ```
|
||||
* (note that in this case if the hint is wrong and the expression is reached at
|
||||
* runtime, the program's behaviour is undefined)
|
||||
* runtime, the program's behavior is undefined)
|
||||
*/
|
||||
override predicate exprExits(Expr e) { Options.super.exprExits(e) }
|
||||
|
||||
|
||||
1
cpp/ql/lib/change-notes/released/0.0.5.md
Normal file
1
cpp/ql/lib/change-notes/released/0.0.5.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.5
|
||||
1
cpp/ql/lib/change-notes/released/0.0.6.md
Normal file
1
cpp/ql/lib/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
1
cpp/ql/lib/change-notes/released/0.0.7.md
Normal file
1
cpp/ql/lib/change-notes/released/0.0.7.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.7
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.4
|
||||
lastReleaseVersion: 0.0.7
|
||||
|
||||
@@ -37,7 +37,7 @@ abstract class SimpleRangeAnalysisDefinition extends RangeSsaDefinition {
|
||||
* dependencies. Without this information, range analysis might work for
|
||||
* simple cases but will go into infinite loops on complex code.
|
||||
*
|
||||
* For example, when modelling the definition by reference in a call to an
|
||||
* For example, when modeling the definition by reference in a call to an
|
||||
* overloaded `operator=`, written as `v = e`, the definition of `(this, v)`
|
||||
* depends on `e`.
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* `Instruction` level), and then using the array length analysis and the range
|
||||
* analysis together to prove that some of these pointer dereferences are safe.
|
||||
*
|
||||
* The analysis is soundy, i.e. it is sound if no undefined behaviour is present
|
||||
* The analysis is soundy, i.e. it is sound if no undefined behavior is present
|
||||
* in the program.
|
||||
* Furthermore, it crucially depends on the soundiness of the range analysis and
|
||||
* the array length analysis.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.0.5-dev
|
||||
version: 0.0.8-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -153,9 +153,11 @@ library class SSAHelper extends int {
|
||||
* Modern Compiler Implementation by Andrew Appel.
|
||||
*/
|
||||
private predicate frontier_phi_node(StackVariable v, BasicBlock b) {
|
||||
exists(BasicBlock x | dominanceFrontier(x, b) and ssa_defn_rec(v, x)) and
|
||||
exists(BasicBlock x |
|
||||
dominanceFrontier(x, b) and ssa_defn_rec(pragma[only_bind_into](v), pragma[only_bind_into](x))
|
||||
) and
|
||||
/* We can also eliminate those nodes where the variable is not live on any incoming edge */
|
||||
live_at_start_of_bb(v, b)
|
||||
live_at_start_of_bb(pragma[only_bind_into](v), b)
|
||||
}
|
||||
|
||||
private predicate ssa_defn_rec(StackVariable v, BasicBlock b) {
|
||||
|
||||
@@ -15,11 +15,23 @@ module Consistency {
|
||||
class ConsistencyConfiguration extends TConsistencyConfiguration {
|
||||
string toString() { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `missingLocation`. */
|
||||
predicate missingLocationExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
|
||||
predicate postWithInFlowExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
|
||||
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `reverseRead`. */
|
||||
predicate reverseReadExclude(Node n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
@@ -46,6 +58,7 @@ module Consistency {
|
||||
n instanceof RelevantNode and
|
||||
c = count(nodeGetEnclosingCallable(n)) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and
|
||||
msg = "Node should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
@@ -66,6 +79,7 @@ module Consistency {
|
||||
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and
|
||||
msg = "Node should have one location but has " + c + "."
|
||||
)
|
||||
}
|
||||
@@ -76,7 +90,8 @@ module Consistency {
|
||||
strictcount(Node n |
|
||||
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
|
||||
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
)
|
||||
) and
|
||||
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
|
||||
) and
|
||||
msg = "Nodes without location: " + c
|
||||
)
|
||||
@@ -172,6 +187,7 @@ module Consistency {
|
||||
|
||||
query predicate reverseRead(Node n, string msg) {
|
||||
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
|
||||
not any(ConsistencyConfiguration conf).reverseReadExclude(n) and
|
||||
msg = "Origin of readStep is missing a PostUpdateNode."
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ class LambdaCapture extends Locatable, @lambdacapture {
|
||||
* An identifier is captured by reference if:
|
||||
* - It is explicitly captured by reference.
|
||||
* - It is implicitly captured, and the lambda's default capture mode is by-reference.
|
||||
* - The identifier is "this". [Said behaviour is dictated by the C++11 standard, but it
|
||||
* - The identifier is "this". [Said behavior is dictated by the C++11 standard, but it
|
||||
* is actually "*this" being captured rather than "this".]
|
||||
*/
|
||||
predicate isCapturedByReference() { lambda_capture(this, _, _, _, true, _, _) }
|
||||
|
||||
@@ -15,11 +15,23 @@ module Consistency {
|
||||
class ConsistencyConfiguration extends TConsistencyConfiguration {
|
||||
string toString() { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `missingLocation`. */
|
||||
predicate missingLocationExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
|
||||
predicate postWithInFlowExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
|
||||
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `reverseRead`. */
|
||||
predicate reverseReadExclude(Node n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
@@ -46,6 +58,7 @@ module Consistency {
|
||||
n instanceof RelevantNode and
|
||||
c = count(nodeGetEnclosingCallable(n)) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and
|
||||
msg = "Node should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
@@ -66,6 +79,7 @@ module Consistency {
|
||||
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and
|
||||
msg = "Node should have one location but has " + c + "."
|
||||
)
|
||||
}
|
||||
@@ -76,7 +90,8 @@ module Consistency {
|
||||
strictcount(Node n |
|
||||
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
|
||||
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
)
|
||||
) and
|
||||
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
|
||||
) and
|
||||
msg = "Nodes without location: " + c
|
||||
)
|
||||
@@ -172,6 +187,7 @@ module Consistency {
|
||||
|
||||
query predicate reverseRead(Node n, string msg) {
|
||||
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
|
||||
not any(ConsistencyConfiguration conf).reverseReadExclude(n) and
|
||||
msg = "Origin of readStep is missing a PostUpdateNode."
|
||||
}
|
||||
|
||||
|
||||
@@ -266,6 +266,20 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
|
||||
bitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate initializeParameterInstructionHasVariable(
|
||||
IRVariable var, InitializeParameterInstruction init
|
||||
) {
|
||||
init.getIRVariable() = var
|
||||
}
|
||||
|
||||
private predicate instructionInitializesThisInFunction(
|
||||
Language::Function f, InitializeParameterInstruction init
|
||||
) {
|
||||
initializeParameterInstructionHasVariable(any(IRThisVariable var), pragma[only_bind_into](init)) and
|
||||
init.getEnclosingFunction() = f
|
||||
}
|
||||
|
||||
private predicate isArgumentForParameter(
|
||||
CallInstruction ci, Operand operand, InitializeParameterInstruction init
|
||||
) {
|
||||
@@ -275,8 +289,7 @@ private predicate isArgumentForParameter(
|
||||
(
|
||||
init.getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex())
|
||||
or
|
||||
init.getIRVariable() instanceof IRThisVariable and
|
||||
unique( | | init.getEnclosingFunction()) = f and
|
||||
instructionInitializesThisInFunction(f, init) and
|
||||
operand instanceof ThisArgumentOperand
|
||||
) and
|
||||
not Language::isFunctionVirtual(f) and
|
||||
|
||||
@@ -266,6 +266,20 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
|
||||
bitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate initializeParameterInstructionHasVariable(
|
||||
IRVariable var, InitializeParameterInstruction init
|
||||
) {
|
||||
init.getIRVariable() = var
|
||||
}
|
||||
|
||||
private predicate instructionInitializesThisInFunction(
|
||||
Language::Function f, InitializeParameterInstruction init
|
||||
) {
|
||||
initializeParameterInstructionHasVariable(any(IRThisVariable var), pragma[only_bind_into](init)) and
|
||||
init.getEnclosingFunction() = f
|
||||
}
|
||||
|
||||
private predicate isArgumentForParameter(
|
||||
CallInstruction ci, Operand operand, InitializeParameterInstruction init
|
||||
) {
|
||||
@@ -275,8 +289,7 @@ private predicate isArgumentForParameter(
|
||||
(
|
||||
init.getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex())
|
||||
or
|
||||
init.getIRVariable() instanceof IRThisVariable and
|
||||
unique( | | init.getEnclosingFunction()) = f and
|
||||
instructionInitializesThisInFunction(f, init) and
|
||||
operand instanceof ThisArgumentOperand
|
||||
) and
|
||||
not Language::isFunctionVirtual(f) and
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
## 0.0.7
|
||||
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### New Queries
|
||||
|
||||
* A new query `cpp/certificate-not-checked` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
* A new query `cpp/certificate-result-conflation` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### New Queries
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The return value of a call to <code>snprintf</code> is the number of characters that <i>would have</i> been written to the buffer assuming there was sufficient space. In the event that the operation reaches the end of the buffer and more than one character is discarded, the return value will be greater than the buffer size. This can cause incorrect behaviour, for example:
|
||||
<p>The return value of a call to <code>snprintf</code> is the number of characters that <i>would have</i> been written to the buffer assuming there was sufficient space. In the event that the operation reaches the end of the buffer and more than one character is discarded, the return value will be greater than the buffer size. This can cause incorrect behavior, for example:
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
|
||||
@@ -22,11 +22,13 @@ import semmle.code.cpp.dataflow.DataFlow
|
||||
* Holds if `sub` is guarded by a condition which ensures that
|
||||
* `left >= right`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
pragma[nomagic]
|
||||
predicate isGuarded(SubExpr sub, Expr left, Expr right) {
|
||||
exists(GuardCondition guard, int k |
|
||||
guard.controls(sub.getBasicBlock(), _) and
|
||||
guard.ensuresLt(left, right, k, sub.getBasicBlock(), false) and
|
||||
exprIsSubLeftOrLess(pragma[only_bind_into](sub), _) and // Manual magic
|
||||
exists(GuardCondition guard, int k, BasicBlock bb |
|
||||
pragma[only_bind_into](bb) = sub.getBasicBlock() and
|
||||
guard.controls(pragma[only_bind_into](bb), _) and
|
||||
guard.ensuresLt(left, right, k, bb, false) and
|
||||
k >= 0
|
||||
)
|
||||
}
|
||||
@@ -36,47 +38,56 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
|
||||
* `sub.getLeftOperand()`.
|
||||
*/
|
||||
predicate exprIsSubLeftOrLess(SubExpr sub, DataFlow::Node n) {
|
||||
n.asExpr() = sub.getLeftOperand()
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// dataflow
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
(
|
||||
DataFlow::localFlowStep(n, other) or
|
||||
DataFlow::localFlowStep(other, n)
|
||||
interestingSubExpr(sub, _) and // Manual magic
|
||||
(
|
||||
n.asExpr() = sub.getLeftOperand()
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// dataflow
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
(
|
||||
DataFlow::localFlowStep(n, other) or
|
||||
DataFlow::localFlowStep(other, n)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// guard constraining `sub`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `other`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
|
||||
p <= 1 and
|
||||
q <= 0
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `n`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
|
||||
p >= 1 and
|
||||
q >= 0
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// guard constraining `sub`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `other`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
|
||||
p <= 1 and
|
||||
q <= 0
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `n`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
|
||||
p >= 1 and
|
||||
q >= 0
|
||||
)
|
||||
}
|
||||
|
||||
from RelationalOperation ro, SubExpr sub
|
||||
where
|
||||
not isFromMacroDefinition(ro) and
|
||||
predicate interestingSubExpr(SubExpr sub, RelationalOperation ro) {
|
||||
not isFromMacroDefinition(sub) and
|
||||
ro.getLesserOperand().getValue().toInt() = 0 and
|
||||
ro.getGreaterOperand() = sub and
|
||||
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned() and
|
||||
exprMightOverflowNegatively(sub.getFullyConverted()) and // generally catches false positives involving constants
|
||||
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand())) // generally catches false positives where there's a relation between the left and right operands
|
||||
// generally catches false positives involving constants
|
||||
exprMightOverflowNegatively(sub.getFullyConverted())
|
||||
}
|
||||
|
||||
from RelationalOperation ro, SubExpr sub
|
||||
where
|
||||
interestingSubExpr(sub, ro) and
|
||||
not isFromMacroDefinition(ro) and
|
||||
// generally catches false positives where there's a relation between the left and right operands
|
||||
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand()))
|
||||
select ro, "Unsigned subtraction can never be negative."
|
||||
|
||||
@@ -14,105 +14,188 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.security.SensitiveExprs
|
||||
import semmle.code.cpp.dataflow.TaintTracking
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A function call that sends or receives data over a network.
|
||||
* A DataFlow node corresponding to a variable or function call that
|
||||
* might contain or return a password or other sensitive information.
|
||||
*/
|
||||
abstract class NetworkSendRecv extends FunctionCall {
|
||||
class SensitiveNode extends DataFlow::Node {
|
||||
SensitiveNode() {
|
||||
this.asExpr() = any(SensitiveVariable sv).getInitializer().getExpr() or
|
||||
this.asExpr().(VariableAccess).getTarget() =
|
||||
any(SensitiveVariable sv).(GlobalOrNamespaceVariable) or
|
||||
this.asUninitialized() instanceof SensitiveVariable or
|
||||
this.asParameter() instanceof SensitiveVariable or
|
||||
this.asExpr().(FunctionCall).getTarget() instanceof SensitiveFunction
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that sends or receives data over a network.
|
||||
*/
|
||||
abstract class SendRecv extends Function {
|
||||
/**
|
||||
* Gets the expression for the socket or similar object used for sending or
|
||||
* receiving data (if any).
|
||||
* receiving data through the function call `call` (if any).
|
||||
*/
|
||||
abstract Expr getSocketExpr();
|
||||
abstract Expr getSocketExpr(Call call);
|
||||
|
||||
/**
|
||||
* Gets the expression for the buffer to be sent from / received into.
|
||||
* Gets the expression for the buffer to be sent from / received into through
|
||||
* the function call `call`.
|
||||
*/
|
||||
abstract Expr getDataExpr();
|
||||
abstract Expr getDataExpr(Call call);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that sends data over a network.
|
||||
*/
|
||||
class Send extends SendRecv instanceof RemoteFlowSinkFunction {
|
||||
override Expr getSocketExpr(Call call) {
|
||||
call.getTarget() = this and
|
||||
exists(FunctionInput input, int arg |
|
||||
super.hasSocketInput(input) and
|
||||
input.isParameter(arg) and
|
||||
result = call.getArgument(arg)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getDataExpr(Call call) {
|
||||
call.getTarget() = this and
|
||||
exists(FunctionInput input, int arg |
|
||||
super.hasRemoteFlowSink(input, _) and
|
||||
input.isParameterDeref(arg) and
|
||||
result = call.getArgument(arg)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that receives data over a network.
|
||||
*/
|
||||
class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
|
||||
override Expr getSocketExpr(Call call) {
|
||||
call.getTarget() = this and
|
||||
exists(FunctionInput input, int arg |
|
||||
super.hasSocketInput(input) and
|
||||
input.isParameter(arg) and
|
||||
result = call.getArgument(arg)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getDataExpr(Call call) {
|
||||
call.getTarget() = this and
|
||||
exists(FunctionOutput output, int arg |
|
||||
super.hasRemoteFlowSource(output, _) and
|
||||
output.isParameterDeref(arg) and
|
||||
result = call.getArgument(arg)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function call that sends or receives data over a network.
|
||||
*
|
||||
* note: function calls such as `write` may be writing to a network source
|
||||
* or a file. We could attempt to determine which, and sort results into
|
||||
* `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In
|
||||
* practice it usually isn't very important which query reports a result as
|
||||
* long as its reported exactly once.
|
||||
*
|
||||
* We do exclude function calls that specify a constant socket, which is
|
||||
* likely to mean standard input, standard output or a similar channel.
|
||||
*/
|
||||
abstract class NetworkSendRecv extends FunctionCall {
|
||||
SendRecv target;
|
||||
|
||||
NetworkSendRecv() {
|
||||
this.getTarget() = target and
|
||||
// exclude calls based on the socket...
|
||||
not exists(GVN g |
|
||||
g = globalValueNumber(target.getSocketExpr(this)) and
|
||||
(
|
||||
// literal constant
|
||||
globalValueNumber(any(Literal l)) = g
|
||||
or
|
||||
// variable (such as a global) initialized to a literal constant
|
||||
exists(Variable v |
|
||||
v.getInitializer().getExpr() instanceof Literal and
|
||||
g = globalValueNumber(v.getAnAccess())
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final Expr getDataExpr() { result = target.getDataExpr(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A function call that sends data over a network.
|
||||
*
|
||||
* note: functions such as `write` may be writing to a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it usually isn't very important which query reports a result as long as its reported exactly once.
|
||||
*/
|
||||
class NetworkSend extends NetworkSendRecv {
|
||||
RemoteFlowSinkFunction target;
|
||||
|
||||
NetworkSend() { target = this.getTarget() }
|
||||
|
||||
override Expr getSocketExpr() {
|
||||
exists(FunctionInput input, int arg |
|
||||
target.hasSocketInput(input) and
|
||||
input.isParameter(arg) and
|
||||
result = this.getArgument(arg)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getDataExpr() {
|
||||
exists(FunctionInput input, int arg |
|
||||
target.hasRemoteFlowSink(input, _) and
|
||||
input.isParameterDeref(arg) and
|
||||
result = this.getArgument(arg)
|
||||
)
|
||||
}
|
||||
override Send target;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function call that receives data over a network.
|
||||
*/
|
||||
class NetworkRecv extends NetworkSendRecv {
|
||||
RemoteFlowSourceFunction target;
|
||||
|
||||
NetworkRecv() { target = this.getTarget() }
|
||||
|
||||
override Expr getSocketExpr() {
|
||||
exists(FunctionInput input, int arg |
|
||||
target.hasSocketInput(input) and
|
||||
input.isParameter(arg) and
|
||||
result = this.getArgument(arg)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getDataExpr() {
|
||||
exists(FunctionOutput output, int arg |
|
||||
target.hasRemoteFlowSource(output, _) and
|
||||
output.isParameterDeref(arg) and
|
||||
result = this.getArgument(arg)
|
||||
)
|
||||
}
|
||||
override Recv target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint flow from a sensitive expression to a network operation with data
|
||||
* tainted by that expression.
|
||||
* An expression that is an argument or return value from an encryption or
|
||||
* decryption call.
|
||||
*/
|
||||
class SensitiveSendRecvConfiguration extends TaintTracking::Configuration {
|
||||
SensitiveSendRecvConfiguration() { this = "SensitiveSendRecvConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(NetworkSendRecv transmission |
|
||||
sink.asExpr() = transmission.getDataExpr() and
|
||||
// a zero socket descriptor is standard input, which is not interesting for this query.
|
||||
not exists(Zero zero |
|
||||
DataFlow::localFlow(DataFlow::exprNode(zero),
|
||||
DataFlow::exprNode(transmission.getSocketExpr()))
|
||||
class Encrypted extends Expr {
|
||||
Encrypted() {
|
||||
exists(FunctionCall fc |
|
||||
fc.getTarget().getName().toLowerCase().regexpMatch(".*(crypt|encode|decode).*") and
|
||||
(
|
||||
this = fc or
|
||||
this = fc.getAnArgument()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint flow from a sensitive expression.
|
||||
*/
|
||||
class FromSensitiveConfiguration extends TaintTracking::Configuration {
|
||||
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof SensitiveNode }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink.asExpr() = any(NetworkSendRecv nsr).getDataExpr()
|
||||
or
|
||||
sink.asExpr() instanceof Encrypted
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// flow through encryption functions to the return value (in case we can reach other sinks)
|
||||
node2.asExpr().(Encrypted).(FunctionCall).getAnArgument() = node1.asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
SensitiveSendRecvConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
|
||||
NetworkSendRecv transmission, string msg
|
||||
FromSensitiveConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
|
||||
NetworkSendRecv networkSendRecv, string msg
|
||||
where
|
||||
// flow from sensitive -> network data
|
||||
config.hasFlowPath(source, sink) and
|
||||
sink.getNode().asExpr() = transmission.getDataExpr() and
|
||||
if transmission instanceof NetworkSend
|
||||
sink.getNode().asExpr() = networkSendRecv.getDataExpr() and
|
||||
// no flow from sensitive -> evidence of encryption
|
||||
not exists(DataFlow::Node encrypted |
|
||||
config.hasFlow(source.getNode(), encrypted) and
|
||||
encrypted.asExpr() instanceof Encrypted
|
||||
) and
|
||||
// construct result
|
||||
if networkSendRecv instanceof NetworkSend
|
||||
then
|
||||
msg =
|
||||
"This operation transmits '" + sink.toString() +
|
||||
@@ -121,4 +204,4 @@ where
|
||||
msg =
|
||||
"This operation receives into '" + sink.toString() +
|
||||
"', which may put unencrypted sensitive data into $@"
|
||||
select transmission, source, sink, msg, source, source.getNode().asExpr().toString()
|
||||
select networkSendRecv, source, sink, msg, source, source.getNode().toString()
|
||||
|
||||
6
cpp/ql/src/change-notes/released/0.0.5.md
Normal file
6
cpp/ql/src/change-notes/released/0.0.5.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## 0.0.5
|
||||
|
||||
### New Queries
|
||||
|
||||
* A new query `cpp/certificate-not-checked` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
* A new query `cpp/certificate-result-conflation` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
1
cpp/ql/src/change-notes/released/0.0.6.md
Normal file
1
cpp/ql/src/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
1
cpp/ql/src/change-notes/released/0.0.7.md
Normal file
1
cpp/ql/src/change-notes/released/0.0.7.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.7
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.4
|
||||
lastReleaseVersion: 0.0.7
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
...
|
||||
umask(0); // BAD
|
||||
...
|
||||
maskOut = S_IRWXG | S_IRWXO;
|
||||
umask(maskOut); // GOOD
|
||||
...
|
||||
fchmod(fileno(fp), 0555 - maskOut); // BAD
|
||||
...
|
||||
fchmod(fileno(fp), 0555 & ~maskOut); // GOOD
|
||||
...
|
||||
umask(0666);
|
||||
chmod(pathname, 0666); // BAD
|
||||
...
|
||||
umask(0022);
|
||||
chmod(pathname, 0666); // GOOD
|
||||
...
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Finding for function calls that set file permissions that may have errors in use. Incorrect arithmetic for calculating the resolution mask, using the same mask in opposite functions, using a mask that is too wide.</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<example>
|
||||
<p>The following example demonstrates erroneous and fixed ways to use functions.</p>
|
||||
<sample src="IncorrectPrivilegeAssignment.cpp" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CERT C Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO06-C.+Create+files+with+appropriate+access+permissions">FIO06-C. Create files with appropriate access permissions</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @name Find the wrong use of the umask function.
|
||||
* @description Incorrectly evaluated argument to the umask function may have security implications.
|
||||
* @kind problem
|
||||
* @id cpp/wrong-use-of-the-umask
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags correctness
|
||||
* maintainability
|
||||
* security
|
||||
* external/cwe/cwe-266
|
||||
* external/cwe/cwe-264
|
||||
* external/cwe/cwe-200
|
||||
* external/cwe/cwe-560
|
||||
* external/cwe/cwe-687
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.exprs.BitwiseOperation
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
/**
|
||||
* An expression that is either a `BinaryArithmeticOperation` or the result of one or more `BinaryBitwiseOperation`s on a `BinaryArithmeticOperation`. For example `1 | (2 + 3)`.
|
||||
*/
|
||||
class ContainsArithmetic extends Expr {
|
||||
ContainsArithmetic() {
|
||||
this instanceof BinaryArithmeticOperation
|
||||
or
|
||||
// recursive search into `Operation`s
|
||||
this.(BinaryBitwiseOperation).getAnOperand() instanceof ContainsArithmetic
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds for a function `f` that has an argument at index `apos` used to set file permissions. */
|
||||
predicate numberArgumentModFunctions(Function f, int apos) {
|
||||
f.hasGlobalOrStdName("umask") and apos = 0
|
||||
or
|
||||
f.hasGlobalOrStdName("fchmod") and apos = 1
|
||||
or
|
||||
f.hasGlobalOrStdName("chmod") and apos = 1
|
||||
}
|
||||
|
||||
from FunctionCall fc, string msg, FunctionCall fcsnd
|
||||
where
|
||||
fc.getTarget().hasGlobalOrStdName("umask") and
|
||||
fc.getArgument(0).getValue() = "0" and
|
||||
not exists(FunctionCall fctmp |
|
||||
fctmp.getTarget().hasGlobalOrStdName("umask") and
|
||||
not fctmp.getArgument(0).getValue() = "0"
|
||||
) and
|
||||
exists(FunctionCall fctmp |
|
||||
(
|
||||
fctmp.getTarget().hasGlobalOrStdName("fopen") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("open")
|
||||
) and
|
||||
not fctmp.getArgument(1).getValue().matches("r%") and
|
||||
fctmp.getNumberOfArguments() = 2 and
|
||||
not fctmp.getArgument(0).getValue() = "/dev/null" and
|
||||
fcsnd = fctmp
|
||||
) and
|
||||
not exists(FunctionCall fctmp |
|
||||
fctmp.getTarget().hasGlobalOrStdName("chmod") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("fchmod")
|
||||
) and
|
||||
msg = "Using umask(0) may not be safe with call $@."
|
||||
or
|
||||
fc.getTarget().hasGlobalOrStdName("umask") and
|
||||
exists(FunctionCall fctmp |
|
||||
(
|
||||
fctmp.getTarget().hasGlobalOrStdName("chmod") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("fchmod")
|
||||
) and
|
||||
(
|
||||
globalValueNumber(fc.getArgument(0)) = globalValueNumber(fctmp.getArgument(1)) and
|
||||
fc.getArgument(0).getValue() != "0"
|
||||
) and
|
||||
msg = "Not use equal argument in umask and $@ functions." and
|
||||
fcsnd = fctmp
|
||||
)
|
||||
or
|
||||
exists(ContainsArithmetic exptmp, int i |
|
||||
numberArgumentModFunctions(fc.getTarget(), i) and
|
||||
globalValueNumber(exptmp) = globalValueNumber(fc.getArgument(i)) and
|
||||
msg = "Using arithmetic to compute the mask in $@ may not be safe." and
|
||||
fcsnd = fc
|
||||
)
|
||||
select fc, msg, fcsnd, fcsnd.getTarget().getName()
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.0.5-dev
|
||||
version: 0.0.8-dev
|
||||
groups: cpp
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| test.cpp:9:3:9:7 | call to umask | Not use equal argument in umask and $@ functions. | test.cpp:13:3:13:7 | call to chmod | chmod |
|
||||
| test.cpp:30:3:30:7 | call to chmod | Using arithmetic to compute the mask in $@ may not be safe. | test.cpp:30:3:30:7 | call to chmod | chmod |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
|
||||
@@ -0,0 +1,49 @@
|
||||
typedef int FILE;
|
||||
FILE *fopen(const char *filename, const char *mode);
|
||||
int umask(int pmode);
|
||||
int chmod(char * filename,int pmode);
|
||||
int fclose(FILE *stream);
|
||||
|
||||
void funcTest1()
|
||||
{
|
||||
umask(0666); // BAD
|
||||
FILE *fe;
|
||||
fe = fopen("myFile.txt", "wt");
|
||||
fclose(fe);
|
||||
chmod("myFile.txt",0666);
|
||||
}
|
||||
void funcTest1g()
|
||||
{
|
||||
umask(0022);
|
||||
FILE *fe;
|
||||
fe = fopen("myFile.txt", "wt");
|
||||
fclose(fe);
|
||||
chmod("myFile.txt",0666); // GOOD
|
||||
}
|
||||
|
||||
void funcTest2(int mode)
|
||||
{
|
||||
umask(mode);
|
||||
FILE *fe;
|
||||
fe = fopen("myFile.txt", "wt");
|
||||
fclose(fe);
|
||||
chmod("myFile.txt",0555-mode); // BAD
|
||||
}
|
||||
|
||||
void funcTest2g(int mode)
|
||||
{
|
||||
umask(mode);
|
||||
FILE *fe;
|
||||
fe = fopen("myFile.txt", "wt");
|
||||
fclose(fe);
|
||||
chmod("myFile.txt",0555&~mode); // GOOD
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
funcTest1();
|
||||
funcTest2(27);
|
||||
funcTest1g();
|
||||
funcTest2g(27);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,49 +1,228 @@
|
||||
edges
|
||||
| test3.cpp:68:21:68:29 | password1 | test3.cpp:70:15:70:17 | ptr |
|
||||
| test3.cpp:75:15:75:22 | password | test3.cpp:77:15:77:17 | ptr |
|
||||
| test3.cpp:106:20:106:25 | buffer | test3.cpp:108:14:108:19 | buffer |
|
||||
| test3.cpp:111:28:111:33 | buffer | test3.cpp:113:9:113:14 | buffer |
|
||||
| test3.cpp:120:9:120:23 | global_password | test3.cpp:138:16:138:29 | call to get_global_str |
|
||||
| test3.cpp:128:11:128:18 | password | test3.cpp:106:20:106:25 | buffer |
|
||||
| test3.cpp:132:21:132:22 | call to id | test3.cpp:134:15:134:17 | ptr |
|
||||
| test3.cpp:132:24:132:32 | password1 | test3.cpp:111:28:111:33 | buffer |
|
||||
| test3.cpp:132:24:132:32 | password1 | test3.cpp:132:21:132:22 | call to id |
|
||||
| test3.cpp:138:16:138:29 | call to get_global_str | test3.cpp:140:15:140:18 | data |
|
||||
| test3.cpp:151:19:151:26 | password | test3.cpp:153:15:153:20 | buffer |
|
||||
| test3.cpp:17:28:17:36 | password1 | test3.cpp:22:15:22:23 | password1 |
|
||||
| test3.cpp:17:51:17:59 | password2 | test3.cpp:26:15:26:23 | password2 |
|
||||
| test3.cpp:45:8:45:15 | password | test3.cpp:47:15:47:22 | password |
|
||||
| test3.cpp:53:8:53:15 | password | test3.cpp:55:15:55:22 | password |
|
||||
| test3.cpp:71:32:71:40 | password1 | test3.cpp:76:15:76:17 | ptr |
|
||||
| test3.cpp:80:8:80:15 | password | test3.cpp:83:15:83:17 | ptr |
|
||||
| test3.cpp:98:8:98:15 | password | test3.cpp:101:12:101:19 | password |
|
||||
| test3.cpp:112:20:112:25 | buffer | test3.cpp:114:14:114:19 | buffer |
|
||||
| test3.cpp:117:28:117:33 | buffer | test3.cpp:119:9:119:14 | buffer |
|
||||
| test3.cpp:126:9:126:23 | global_password | test3.cpp:144:16:144:29 | call to get_global_str |
|
||||
| test3.cpp:129:39:129:47 | password1 | test3.cpp:138:24:138:32 | password1 |
|
||||
| test3.cpp:132:8:132:15 | password | test3.cpp:134:11:134:18 | password |
|
||||
| test3.cpp:134:11:134:18 | password | test3.cpp:112:20:112:25 | buffer |
|
||||
| test3.cpp:138:21:138:22 | call to id | test3.cpp:140:15:140:17 | ptr |
|
||||
| test3.cpp:138:24:138:32 | password1 | test3.cpp:117:28:117:33 | buffer |
|
||||
| test3.cpp:138:24:138:32 | password1 | test3.cpp:138:21:138:22 | call to id |
|
||||
| test3.cpp:144:16:144:29 | call to get_global_str | test3.cpp:146:15:146:18 | data |
|
||||
| test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer |
|
||||
| test3.cpp:171:8:171:15 | password | test3.cpp:173:15:173:22 | password |
|
||||
| test3.cpp:171:8:171:15 | password | test3.cpp:175:3:175:17 | call to decrypt_inplace |
|
||||
| test3.cpp:171:8:171:15 | password | test3.cpp:175:19:175:26 | password |
|
||||
| test3.cpp:179:8:179:15 | password | test3.cpp:181:15:181:22 | password |
|
||||
| test3.cpp:179:8:179:15 | password | test3.cpp:184:3:184:17 | call to decrypt_inplace |
|
||||
| test3.cpp:179:8:179:15 | password | test3.cpp:184:19:184:26 | password |
|
||||
| test3.cpp:188:8:188:15 | password | test3.cpp:191:15:191:22 | password |
|
||||
| test3.cpp:188:8:188:15 | password | test3.cpp:193:18:193:28 | call to rtn_decrypt |
|
||||
| test3.cpp:188:8:188:15 | password | test3.cpp:193:30:193:37 | password |
|
||||
| test3.cpp:197:8:197:15 | password | test3.cpp:199:3:199:17 | call to encrypt_inplace |
|
||||
| test3.cpp:197:8:197:15 | password | test3.cpp:199:19:199:26 | password |
|
||||
| test3.cpp:197:8:197:15 | password | test3.cpp:201:15:201:22 | password |
|
||||
| test3.cpp:205:8:205:15 | password | test3.cpp:207:3:207:17 | call to encrypt_inplace |
|
||||
| test3.cpp:205:8:205:15 | password | test3.cpp:207:19:207:26 | password |
|
||||
| test3.cpp:205:8:205:15 | password | test3.cpp:210:15:210:22 | password |
|
||||
| test3.cpp:214:8:214:15 | password | test3.cpp:217:18:217:28 | call to rtn_encrypt |
|
||||
| test3.cpp:214:8:214:15 | password | test3.cpp:217:18:217:28 | call to rtn_encrypt |
|
||||
| test3.cpp:214:8:214:15 | password | test3.cpp:217:30:217:37 | password |
|
||||
| test3.cpp:214:8:214:15 | password | test3.cpp:219:15:219:26 | password_ptr |
|
||||
| test3.cpp:217:18:217:28 | call to rtn_encrypt | test3.cpp:219:15:219:26 | password_ptr |
|
||||
| test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password |
|
||||
| test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password |
|
||||
| test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password |
|
||||
| test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password |
|
||||
| test3.cpp:252:8:252:16 | password1 | test3.cpp:254:15:254:23 | password1 |
|
||||
| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer |
|
||||
| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:21:256:29 | password1 |
|
||||
| test3.cpp:252:24:252:32 | password2 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer |
|
||||
| test3.cpp:252:24:252:32 | password2 | test3.cpp:256:32:256:40 | password2 |
|
||||
| test3.cpp:260:8:260:16 | password1 | test3.cpp:262:3:262:19 | call to encrypt_to_buffer |
|
||||
| test3.cpp:260:8:260:16 | password1 | test3.cpp:262:21:262:29 | password1 |
|
||||
| test3.cpp:260:24:260:32 | password2 | test3.cpp:262:3:262:19 | call to encrypt_to_buffer |
|
||||
| test3.cpp:260:24:260:32 | password2 | test3.cpp:262:32:262:40 | password2 |
|
||||
| test3.cpp:260:24:260:32 | password2 | test3.cpp:264:15:264:23 | password2 |
|
||||
| test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data |
|
||||
| test3.cpp:278:20:278:23 | data | test3.cpp:278:20:278:23 | data |
|
||||
| test3.cpp:278:20:278:23 | data | test3.cpp:280:14:280:17 | data |
|
||||
| test3.cpp:283:20:283:23 | data | test3.cpp:283:20:283:23 | data |
|
||||
| test3.cpp:283:20:283:23 | data | test3.cpp:285:14:285:17 | data |
|
||||
| test3.cpp:288:20:288:23 | data | test3.cpp:290:14:290:17 | data |
|
||||
| test3.cpp:293:20:293:23 | data | test3.cpp:293:20:293:23 | data |
|
||||
| test3.cpp:293:20:293:23 | data | test3.cpp:295:14:295:17 | data |
|
||||
| test3.cpp:298:20:298:23 | data | test3.cpp:300:14:300:17 | data |
|
||||
| test3.cpp:308:41:308:49 | password1 | test3.cpp:312:3:312:17 | call to encrypt_inplace |
|
||||
| test3.cpp:308:41:308:49 | password1 | test3.cpp:312:19:312:27 | password1 |
|
||||
| test3.cpp:308:41:308:49 | password1 | test3.cpp:313:11:313:19 | password1 |
|
||||
| test3.cpp:308:41:308:49 | password1 | test3.cpp:314:11:314:19 | password1 |
|
||||
| test3.cpp:308:41:308:49 | password1 | test3.cpp:316:11:316:19 | password1 |
|
||||
| test3.cpp:308:41:308:49 | password1 | test3.cpp:317:11:317:19 | password1 |
|
||||
| test3.cpp:308:58:308:66 | password2 | test3.cpp:324:11:324:14 | data |
|
||||
| test3.cpp:308:58:308:66 | password2 | test3.cpp:325:11:325:14 | data |
|
||||
| test3.cpp:313:11:313:19 | password1 | test3.cpp:278:20:278:23 | data |
|
||||
| test3.cpp:313:11:313:19 | password1 | test3.cpp:313:11:313:19 | ref arg password1 |
|
||||
| test3.cpp:313:11:313:19 | ref arg password1 | test3.cpp:314:11:314:19 | password1 |
|
||||
| test3.cpp:314:11:314:19 | password1 | test3.cpp:283:20:283:23 | data |
|
||||
| test3.cpp:316:11:316:19 | password1 | test3.cpp:283:20:283:23 | data |
|
||||
| test3.cpp:316:11:316:19 | password1 | test3.cpp:316:11:316:19 | ref arg password1 |
|
||||
| test3.cpp:316:11:316:19 | ref arg password1 | test3.cpp:317:11:317:19 | password1 |
|
||||
| test3.cpp:317:11:317:19 | password1 | test3.cpp:288:20:288:23 | data |
|
||||
| test3.cpp:324:11:324:14 | data | test3.cpp:293:20:293:23 | data |
|
||||
| test3.cpp:324:11:324:14 | data | test3.cpp:324:11:324:14 | ref arg data |
|
||||
| test3.cpp:324:11:324:14 | ref arg data | test3.cpp:325:11:325:14 | data |
|
||||
| test3.cpp:325:11:325:14 | data | test3.cpp:298:20:298:23 | data |
|
||||
| test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password |
|
||||
| test3.cpp:350:9:350:16 | password | test3.cpp:352:16:352:23 | password |
|
||||
| test3.cpp:350:9:350:16 | password | test3.cpp:353:4:353:18 | call to decrypt_inplace |
|
||||
| test3.cpp:350:9:350:16 | password | test3.cpp:353:20:353:27 | password |
|
||||
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt |
|
||||
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword |
|
||||
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt |
|
||||
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:29:76:39 | thePassword |
|
||||
nodes
|
||||
| test3.cpp:20:15:20:23 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:24:15:24:23 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:41:15:41:22 | password | semmle.label | password |
|
||||
| test3.cpp:49:15:49:22 | password | semmle.label | password |
|
||||
| test3.cpp:68:21:68:29 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:70:15:70:17 | ptr | semmle.label | ptr |
|
||||
| test3.cpp:75:15:75:22 | password | semmle.label | password |
|
||||
| test3.cpp:77:15:77:17 | ptr | semmle.label | ptr |
|
||||
| test3.cpp:95:12:95:19 | password | semmle.label | password |
|
||||
| test3.cpp:106:20:106:25 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:108:14:108:19 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:111:28:111:33 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:113:9:113:14 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:120:9:120:23 | global_password | semmle.label | global_password |
|
||||
| test3.cpp:128:11:128:18 | password | semmle.label | password |
|
||||
| test3.cpp:132:21:132:22 | call to id | semmle.label | call to id |
|
||||
| test3.cpp:132:24:132:32 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:134:15:134:17 | ptr | semmle.label | ptr |
|
||||
| test3.cpp:138:16:138:29 | call to get_global_str | semmle.label | call to get_global_str |
|
||||
| test3.cpp:140:15:140:18 | data | semmle.label | data |
|
||||
| test3.cpp:151:19:151:26 | password | semmle.label | password |
|
||||
| test3.cpp:153:15:153:20 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:17:28:17:36 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:17:51:17:59 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:22:15:22:23 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:26:15:26:23 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:45:8:45:15 | password | semmle.label | password |
|
||||
| test3.cpp:47:15:47:22 | password | semmle.label | password |
|
||||
| test3.cpp:53:8:53:15 | password | semmle.label | password |
|
||||
| test3.cpp:55:15:55:22 | password | semmle.label | password |
|
||||
| test3.cpp:71:32:71:40 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:76:15:76:17 | ptr | semmle.label | ptr |
|
||||
| test3.cpp:80:8:80:15 | password | semmle.label | password |
|
||||
| test3.cpp:83:15:83:17 | ptr | semmle.label | ptr |
|
||||
| test3.cpp:98:8:98:15 | password | semmle.label | password |
|
||||
| test3.cpp:101:12:101:19 | password | semmle.label | password |
|
||||
| test3.cpp:112:20:112:25 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:114:14:114:19 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:117:28:117:33 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:119:9:119:14 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:126:9:126:23 | global_password | semmle.label | global_password |
|
||||
| test3.cpp:129:39:129:47 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:132:8:132:15 | password | semmle.label | password |
|
||||
| test3.cpp:134:11:134:18 | password | semmle.label | password |
|
||||
| test3.cpp:138:21:138:22 | call to id | semmle.label | call to id |
|
||||
| test3.cpp:138:24:138:32 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:140:15:140:17 | ptr | semmle.label | ptr |
|
||||
| test3.cpp:144:16:144:29 | call to get_global_str | semmle.label | call to get_global_str |
|
||||
| test3.cpp:146:15:146:18 | data | semmle.label | data |
|
||||
| test3.cpp:152:29:152:36 | password | semmle.label | password |
|
||||
| test3.cpp:159:15:159:20 | buffer | semmle.label | buffer |
|
||||
| test3.cpp:171:8:171:15 | password | semmle.label | password |
|
||||
| test3.cpp:173:15:173:22 | password | semmle.label | password |
|
||||
| test3.cpp:175:3:175:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
|
||||
| test3.cpp:175:19:175:26 | password | semmle.label | password |
|
||||
| test3.cpp:179:8:179:15 | password | semmle.label | password |
|
||||
| test3.cpp:181:15:181:22 | password | semmle.label | password |
|
||||
| test3.cpp:184:3:184:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
|
||||
| test3.cpp:184:19:184:26 | password | semmle.label | password |
|
||||
| test3.cpp:188:8:188:15 | password | semmle.label | password |
|
||||
| test3.cpp:191:15:191:22 | password | semmle.label | password |
|
||||
| test3.cpp:193:18:193:28 | call to rtn_decrypt | semmle.label | call to rtn_decrypt |
|
||||
| test3.cpp:193:30:193:37 | password | semmle.label | password |
|
||||
| test3.cpp:197:8:197:15 | password | semmle.label | password |
|
||||
| test3.cpp:199:3:199:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace |
|
||||
| test3.cpp:199:19:199:26 | password | semmle.label | password |
|
||||
| test3.cpp:201:15:201:22 | password | semmle.label | password |
|
||||
| test3.cpp:205:8:205:15 | password | semmle.label | password |
|
||||
| test3.cpp:207:3:207:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace |
|
||||
| test3.cpp:207:19:207:26 | password | semmle.label | password |
|
||||
| test3.cpp:210:15:210:22 | password | semmle.label | password |
|
||||
| test3.cpp:214:8:214:15 | password | semmle.label | password |
|
||||
| test3.cpp:217:18:217:28 | call to rtn_encrypt | semmle.label | call to rtn_encrypt |
|
||||
| test3.cpp:217:18:217:28 | call to rtn_encrypt | semmle.label | call to rtn_encrypt |
|
||||
| test3.cpp:217:30:217:37 | password | semmle.label | password |
|
||||
| test3.cpp:219:15:219:26 | password_ptr | semmle.label | password_ptr |
|
||||
| test3.cpp:225:34:225:41 | password | semmle.label | password |
|
||||
| test3.cpp:227:22:227:29 | password | semmle.label | password |
|
||||
| test3.cpp:228:26:228:33 | password | semmle.label | password |
|
||||
| test3.cpp:239:7:239:14 | password | semmle.label | password |
|
||||
| test3.cpp:241:8:241:15 | password | semmle.label | password |
|
||||
| test3.cpp:242:8:242:15 | password | semmle.label | password |
|
||||
| test3.cpp:252:8:252:16 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:252:24:252:32 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:254:15:254:23 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:256:3:256:19 | call to decrypt_to_buffer | semmle.label | call to decrypt_to_buffer |
|
||||
| test3.cpp:256:21:256:29 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:256:32:256:40 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:260:8:260:16 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:260:24:260:32 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:262:3:262:19 | call to encrypt_to_buffer | semmle.label | call to encrypt_to_buffer |
|
||||
| test3.cpp:262:21:262:29 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:262:32:262:40 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:264:15:264:23 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:268:19:268:26 | password | semmle.label | password |
|
||||
| test3.cpp:272:15:272:18 | data | semmle.label | data |
|
||||
| test3.cpp:278:20:278:23 | data | semmle.label | data |
|
||||
| test3.cpp:278:20:278:23 | data | semmle.label | data |
|
||||
| test3.cpp:280:14:280:17 | data | semmle.label | data |
|
||||
| test3.cpp:283:20:283:23 | data | semmle.label | data |
|
||||
| test3.cpp:283:20:283:23 | data | semmle.label | data |
|
||||
| test3.cpp:285:14:285:17 | data | semmle.label | data |
|
||||
| test3.cpp:288:20:288:23 | data | semmle.label | data |
|
||||
| test3.cpp:290:14:290:17 | data | semmle.label | data |
|
||||
| test3.cpp:293:20:293:23 | data | semmle.label | data |
|
||||
| test3.cpp:293:20:293:23 | data | semmle.label | data |
|
||||
| test3.cpp:295:14:295:17 | data | semmle.label | data |
|
||||
| test3.cpp:298:20:298:23 | data | semmle.label | data |
|
||||
| test3.cpp:300:14:300:17 | data | semmle.label | data |
|
||||
| test3.cpp:308:41:308:49 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:308:58:308:66 | password2 | semmle.label | password2 |
|
||||
| test3.cpp:312:3:312:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace |
|
||||
| test3.cpp:312:19:312:27 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:313:11:313:19 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:313:11:313:19 | ref arg password1 | semmle.label | ref arg password1 |
|
||||
| test3.cpp:314:11:314:19 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:316:11:316:19 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:316:11:316:19 | ref arg password1 | semmle.label | ref arg password1 |
|
||||
| test3.cpp:317:11:317:19 | password1 | semmle.label | password1 |
|
||||
| test3.cpp:324:11:324:14 | data | semmle.label | data |
|
||||
| test3.cpp:324:11:324:14 | ref arg data | semmle.label | ref arg data |
|
||||
| test3.cpp:325:11:325:14 | data | semmle.label | data |
|
||||
| test3.cpp:339:9:339:16 | password | semmle.label | password |
|
||||
| test3.cpp:341:16:341:23 | password | semmle.label | password |
|
||||
| test3.cpp:350:9:350:16 | password | semmle.label | password |
|
||||
| test3.cpp:352:16:352:23 | password | semmle.label | password |
|
||||
| test3.cpp:353:4:353:18 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
|
||||
| test3.cpp:353:20:353:27 | password | semmle.label | password |
|
||||
| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! |
|
||||
| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt |
|
||||
| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword |
|
||||
| test.cpp:66:23:66:43 | cleartext password! | semmle.label | cleartext password! |
|
||||
| test.cpp:76:21:76:27 | call to encrypt | semmle.label | call to encrypt |
|
||||
| test.cpp:76:29:76:39 | thePassword | semmle.label | thePassword |
|
||||
subpaths
|
||||
| test3.cpp:132:24:132:32 | password1 | test3.cpp:111:28:111:33 | buffer | test3.cpp:113:9:113:14 | buffer | test3.cpp:132:21:132:22 | call to id |
|
||||
| test3.cpp:138:24:138:32 | password1 | test3.cpp:117:28:117:33 | buffer | test3.cpp:119:9:119:14 | buffer | test3.cpp:138:21:138:22 | call to id |
|
||||
| test3.cpp:313:11:313:19 | password1 | test3.cpp:278:20:278:23 | data | test3.cpp:278:20:278:23 | data | test3.cpp:313:11:313:19 | ref arg password1 |
|
||||
| test3.cpp:316:11:316:19 | password1 | test3.cpp:283:20:283:23 | data | test3.cpp:283:20:283:23 | data | test3.cpp:316:11:316:19 | ref arg password1 |
|
||||
| test3.cpp:324:11:324:14 | data | test3.cpp:293:20:293:23 | data | test3.cpp:293:20:293:23 | data | test3.cpp:324:11:324:14 | ref arg data |
|
||||
#select
|
||||
| test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@ | test3.cpp:20:15:20:23 | password1 | password1 |
|
||||
| test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@ | test3.cpp:24:15:24:23 | password2 | password2 |
|
||||
| test3.cpp:41:3:41:6 | call to recv | test3.cpp:41:15:41:22 | password | test3.cpp:41:15:41:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:41:15:41:22 | password | password |
|
||||
| test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password | test3.cpp:49:15:49:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:49:15:49:22 | password | password |
|
||||
| test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 | test3.cpp:70:15:70:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:68:21:68:29 | password1 | password1 |
|
||||
| test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password | test3.cpp:77:15:77:17 | ptr | This operation receives into 'ptr', which may put unencrypted sensitive data into $@ | test3.cpp:75:15:75:22 | password | password |
|
||||
| test3.cpp:95:3:95:6 | call to read | test3.cpp:95:12:95:19 | password | test3.cpp:95:12:95:19 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:95:12:95:19 | password | password |
|
||||
| test3.cpp:108:2:108:5 | call to recv | test3.cpp:128:11:128:18 | password | test3.cpp:108:14:108:19 | buffer | This operation receives into 'buffer', which may put unencrypted sensitive data into $@ | test3.cpp:128:11:128:18 | password | password |
|
||||
| test3.cpp:134:3:134:6 | call to send | test3.cpp:132:24:132:32 | password1 | test3.cpp:134:15:134:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:132:24:132:32 | password1 | password1 |
|
||||
| test3.cpp:140:3:140:6 | call to send | test3.cpp:120:9:120:23 | global_password | test3.cpp:140:15:140:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:120:9:120:23 | global_password | global_password |
|
||||
| test3.cpp:153:3:153:6 | call to send | test3.cpp:151:19:151:26 | password | test3.cpp:153:15:153:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:151:19:151:26 | password | password |
|
||||
| test3.cpp:22:3:22:6 | call to send | test3.cpp:17:28:17:36 | password1 | test3.cpp:22:15:22:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@ | test3.cpp:17:28:17:36 | password1 | password1 |
|
||||
| test3.cpp:26:3:26:6 | call to send | test3.cpp:17:51:17:59 | password2 | test3.cpp:26:15:26:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@ | test3.cpp:17:51:17:59 | password2 | password2 |
|
||||
| test3.cpp:47:3:47:6 | call to recv | test3.cpp:45:8:45:15 | password | test3.cpp:47:15:47:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:45:8:45:15 | password | password |
|
||||
| test3.cpp:55:3:55:6 | call to recv | test3.cpp:53:8:53:15 | password | test3.cpp:55:15:55:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:53:8:53:15 | password | password |
|
||||
| test3.cpp:76:3:76:6 | call to send | test3.cpp:71:32:71:40 | password1 | test3.cpp:76:15:76:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:71:32:71:40 | password1 | password1 |
|
||||
| test3.cpp:83:3:83:6 | call to recv | test3.cpp:80:8:80:15 | password | test3.cpp:83:15:83:17 | ptr | This operation receives into 'ptr', which may put unencrypted sensitive data into $@ | test3.cpp:80:8:80:15 | password | password |
|
||||
| test3.cpp:101:3:101:6 | call to read | test3.cpp:98:8:98:15 | password | test3.cpp:101:12:101:19 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:98:8:98:15 | password | password |
|
||||
| test3.cpp:114:2:114:5 | call to recv | test3.cpp:132:8:132:15 | password | test3.cpp:114:14:114:19 | buffer | This operation receives into 'buffer', which may put unencrypted sensitive data into $@ | test3.cpp:132:8:132:15 | password | password |
|
||||
| test3.cpp:140:3:140:6 | call to send | test3.cpp:129:39:129:47 | password1 | test3.cpp:140:15:140:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:129:39:129:47 | password1 | password1 |
|
||||
| test3.cpp:146:3:146:6 | call to send | test3.cpp:126:9:126:23 | global_password | test3.cpp:146:15:146:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:126:9:126:23 | global_password | global_password |
|
||||
| test3.cpp:159:3:159:6 | call to send | test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:152:29:152:36 | password | password |
|
||||
| test3.cpp:227:2:227:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
|
||||
| test3.cpp:228:2:228:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
|
||||
| test3.cpp:241:2:241:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
|
||||
| test3.cpp:242:2:242:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
|
||||
| test3.cpp:272:3:272:6 | call to send | test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:268:19:268:26 | password | password |
|
||||
| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
|
||||
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
|
||||
| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password |
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
#define STDIN_FILENO (0)
|
||||
#define STDOUT_FILENO (1)
|
||||
int stdout_fileno = STDOUT_FILENO;
|
||||
|
||||
size_t strlen(const char *s);
|
||||
|
||||
@@ -31,6 +33,10 @@ void test_send(const char *password1, const char *password2, const char *passwor
|
||||
{
|
||||
send(val(), message, strlen(message), val()); // GOOD: `message` is not a password
|
||||
}
|
||||
|
||||
{
|
||||
send(stdout_fileno, password2, strlen(password2), val()); // GOOD: `password2` is sent to stdout, not a network socket (this may be an issue but is not within the scope of the `cpp/cleartext-transmission` query)
|
||||
}
|
||||
}
|
||||
|
||||
void test_receive()
|
||||
@@ -125,7 +131,7 @@ void test_interprocedural(const char *password1)
|
||||
{
|
||||
char password[256];
|
||||
|
||||
my_recv(password, 256); // BAD: `password` is received plaintext [detected on line 108]
|
||||
my_recv(password, 256); // BAD: `password` is received plaintext [detected in `my_recv`]
|
||||
}
|
||||
|
||||
{
|
||||
@@ -153,3 +159,200 @@ void test_taint(const char *password)
|
||||
send(val(), buffer, 16, val()); // BAD: `password` is (partially) sent plaintext
|
||||
}
|
||||
}
|
||||
|
||||
void encrypt_inplace(char *buffer);
|
||||
void decrypt_inplace(char *buffer);
|
||||
char *rtn_encrypt(const char *buffer);
|
||||
char *rtn_decrypt(const char *buffer);
|
||||
|
||||
void test_decrypt()
|
||||
{
|
||||
{
|
||||
char password[256];
|
||||
|
||||
recv(val(), password, 256, val()); // GOOD: password is encrypted
|
||||
|
||||
decrypt_inplace(password); // proof that `password` was in fact encrypted
|
||||
}
|
||||
|
||||
{
|
||||
char password[256];
|
||||
|
||||
recv(val(), password, 256, val()); // GOOD: password is encrypted
|
||||
password[255] = 0;
|
||||
|
||||
decrypt_inplace(password); // proof that `password` was in fact encrypted
|
||||
}
|
||||
|
||||
{
|
||||
char password[256];
|
||||
char *password_ptr;
|
||||
|
||||
recv(val(), password, 256, val()); // GOOD: password is encrypted
|
||||
|
||||
password_ptr = rtn_decrypt(password); // proof that `password` was in fact encrypted
|
||||
}
|
||||
|
||||
{
|
||||
char password[256];
|
||||
|
||||
encrypt_inplace(password); // proof that `password` is in fact encrypted
|
||||
|
||||
send(val(), password, strlen(password), val()); // GOOD: password is encrypted
|
||||
}
|
||||
|
||||
{
|
||||
char password[256];
|
||||
|
||||
encrypt_inplace(password); // proof that `password` is in fact encrypted
|
||||
password[255] = 0;
|
||||
|
||||
send(val(), password, strlen(password), val()); // GOOD: password is encrypted
|
||||
}
|
||||
|
||||
{
|
||||
char password[256];
|
||||
char *password_ptr;
|
||||
|
||||
password_ptr = rtn_encrypt(password); // proof that `password` is in fact encrypted
|
||||
|
||||
send(val(), password_ptr, strlen(password_ptr), val()); // GOOD: password is encrypted
|
||||
}
|
||||
}
|
||||
|
||||
int get_socket(int from);
|
||||
|
||||
void test_more_stdio(const char *password)
|
||||
{
|
||||
send(get_socket(1), password, 128, val()); // GOOD: `getsocket(1)` is probably standard output [FALSE POSITIVE]
|
||||
send(get_socket(val()), password, 128, val()); // BAD
|
||||
}
|
||||
|
||||
typedef struct {} FILE;
|
||||
char *fgets(char *s, int n, FILE *stream);
|
||||
|
||||
FILE *get_stdstream(int index);
|
||||
#define STDIN_STREAM (get_stdstream(0))
|
||||
|
||||
void test_fgets(FILE *stream)
|
||||
{
|
||||
char password[128];
|
||||
|
||||
fgets(password, 128, stream); // BAD
|
||||
fgets(password, 128, STDIN_STREAM); // GOOD: `STDIN_STREAM` is probably standard input [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void encrypt_to_buffer(const char *input, char* output);
|
||||
void decrypt_to_buffer(const char *input, char* output);
|
||||
char *strcpy(char *s1, const char *s2);
|
||||
|
||||
void test_crypt_more()
|
||||
{
|
||||
{
|
||||
char password1[256], password2[256];
|
||||
|
||||
recv(val(), password1, 256, val()); // GOOD: password is encrypted
|
||||
|
||||
decrypt_to_buffer(password1, password2); // proof that `password1` was in fact encrypted
|
||||
}
|
||||
|
||||
{
|
||||
char password1[256], password2[256];
|
||||
|
||||
encrypt_to_buffer(password1, password2); // proof that `password2` is in fact encrypted
|
||||
|
||||
send(val(), password2, strlen(password2), val()); // GOOD: password is encrypted
|
||||
}
|
||||
|
||||
{
|
||||
char data[256], password[256];
|
||||
|
||||
strcpy(data, password); // not proof of anything
|
||||
|
||||
send(val(), data, strlen(data), val()); // BAD: password is sent plaintext
|
||||
}
|
||||
}
|
||||
|
||||
bool cond();
|
||||
|
||||
void target1(char *data)
|
||||
{
|
||||
send(val(), data, strlen(data), val()); // GOOD: encrypted
|
||||
}
|
||||
|
||||
void target2(char *data)
|
||||
{
|
||||
send(val(), data, strlen(data), val()); // BAD: from one source this is a plaintext password [NOT DETECTED]
|
||||
}
|
||||
|
||||
void target3(char *data)
|
||||
{
|
||||
send(val(), data, strlen(data), val()); // BAD: data is a plaintext password [NOT DETECTED]
|
||||
}
|
||||
|
||||
void target4(char *data)
|
||||
{
|
||||
send(val(), data, strlen(data), val()); // BAD: data is a plaintext password
|
||||
}
|
||||
|
||||
void target5(char *data)
|
||||
{
|
||||
send(val(), data, strlen(data), val()); // BAD: from one source this is a plaintext password
|
||||
}
|
||||
|
||||
void target6(char *data)
|
||||
{
|
||||
send(val(), data, strlen(data), val()); // GOOD: not a password
|
||||
}
|
||||
|
||||
void test_multiple_sources_source(char *password1, char *password2)
|
||||
{
|
||||
if (cond())
|
||||
{
|
||||
encrypt_inplace(password1);
|
||||
target1(password1);
|
||||
target2(password1);
|
||||
} else {
|
||||
target2(password1);
|
||||
target3(password1);
|
||||
}
|
||||
|
||||
if (cond())
|
||||
{
|
||||
char *data = password2;
|
||||
|
||||
target4(data);
|
||||
target5(data);
|
||||
} else {
|
||||
char *data = "harmless";
|
||||
|
||||
target5(data);
|
||||
target6(data);
|
||||
}
|
||||
}
|
||||
|
||||
void test_loops()
|
||||
{
|
||||
{
|
||||
while (cond())
|
||||
{
|
||||
char password[256];
|
||||
|
||||
recv(val(), password, 256, val()); // BAD: not encrypted
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
while (cond())
|
||||
{
|
||||
char password[256];
|
||||
|
||||
recv(val(), password, 256, val()); // GOOD: password is encrypted
|
||||
decrypt_inplace(password); // proof that `password` was in fact encrypted
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
## 0.0.7
|
||||
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
## 0.0.4
|
||||
|
||||
1
cpp/upgrades/change-notes/released/0.0.5.md
Normal file
1
cpp/upgrades/change-notes/released/0.0.5.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.5
|
||||
1
cpp/upgrades/change-notes/released/0.0.6.md
Normal file
1
cpp/upgrades/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
1
cpp/upgrades/change-notes/released/0.0.7.md
Normal file
1
cpp/upgrades/change-notes/released/0.0.7.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.7
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.4
|
||||
lastReleaseVersion: 0.0.7
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-upgrades
|
||||
groups: cpp
|
||||
upgrades: .
|
||||
version: 0.0.5-dev
|
||||
version: 0.0.8-dev
|
||||
library: true
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package,sink,source,summary,sink:code,sink:html,sink:remote,sink:sql,sink:xss,source:local,summary:taint,summary:value
|
||||
Dapper,55,,,,,,55,,,,
|
||||
Microsoft.ApplicationBlocks.Data,28,,,,,,28,,,,
|
||||
Microsoft.VisualBasic,,,4,,,,,,,,4
|
||||
MySql.Data.MySqlClient,48,,,,,,48,,,,
|
||||
Newtonsoft.Json,,,73,,,,,,,73,
|
||||
Newtonsoft.Json,,,91,,,,,,,73,18
|
||||
ServiceStack,194,,7,27,,75,92,,,7,
|
||||
System,28,3,1221,,4,,23,1,3,611,610
|
||||
System,28,3,2336,,4,,23,1,3,611,1725
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user