Skip to content

Commit c13e8e4

Browse files
committed
Merge branch 'main' into formatTaint
2 parents bb4bc55 + fd5f678 commit c13e8e4

File tree

889 files changed

+14300
-55344
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

889 files changed

+14300
-55344
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: "Swift: Build and test Xcode autobuilder"
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- "swift/xcode-autobuilder/**"
7+
- "misc/bazel/**"
8+
- "*.bazel*"
9+
- .github/workflows/swift-autobuilder.yml
10+
branches:
11+
- main
12+
13+
jobs:
14+
autobuilder:
15+
runs-on: macos-latest
16+
steps:
17+
- uses: actions/checkout@v3
18+
- uses: bazelbuild/setup-bazelisk@v2
19+
- uses: actions/setup-python@v4
20+
with:
21+
python-version-file: 'swift/.python-version'
22+
- name: Build the Xcode autobuilder
23+
run: |
24+
bazel build //swift/xcode-autobuilder
25+
- name: Test the Xcode autobuilder
26+
run: |
27+
bazel test //swift/xcode-autobuilder/tests

.github/workflows/swift-codegen.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ on:
1010
- .github/actions/fetch-codeql/action.yml
1111
branches:
1212
- main
13+
defaults:
14+
run:
15+
working-directory: swift
1316

1417
jobs:
1518
codegen:
@@ -18,7 +21,9 @@ jobs:
1821
- uses: actions/checkout@v3
1922
- uses: ./.github/actions/fetch-codeql
2023
- uses: bazelbuild/setup-bazelisk@v2
21-
- uses: actions/setup-python@v3
24+
- uses: actions/setup-python@v4
25+
with:
26+
python-version-file: 'swift/.python-version'
2227
- uses: pre-commit/[email protected]
2328
name: Check that python code is properly formatted
2429
with:

.github/workflows/swift-integration-tests.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ jobs:
2828
- uses: actions/checkout@v3
2929
- uses: ./.github/actions/fetch-codeql
3030
- uses: bazelbuild/setup-bazelisk@v2
31-
- uses: actions/setup-python@v3
31+
- uses: actions/setup-python@v4
32+
with:
33+
python-version-file: 'swift/.python-version'
3234
- name: Build Swift extractor
3335
run: |
3436
bazel run //swift:create-extractor-pack

.github/workflows/swift-qltest.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ jobs:
3333
- uses: actions/checkout@v3
3434
- uses: ./.github/actions/fetch-codeql
3535
- uses: bazelbuild/setup-bazelisk@v2
36+
- uses: actions/setup-python@v4
37+
with:
38+
python-version-file: 'swift/.python-version'
3639
- name: Build Swift extractor
3740
run: |
3841
bazel run //swift:create-extractor-pack

CODEOWNERS

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @github/codeql-java @github/codeql-go
2121

2222
# CodeQL tools and associated docs
23-
/docs/codeql-cli/ @github/codeql-cli-reviewers
24-
/docs/codeql-for-visual-studio-code/ @github/codeql-vscode-reviewers
25-
/docs/ql-language-reference/ @github/codeql-frontend-reviewers
23+
/docs/codeql/codeql-cli/ @github/codeql-cli-reviewers
24+
/docs/codeql/codeql-for-visual-studio-code/ @github/codeql-vscode-reviewers
25+
/docs/codeql/ql-language-reference/ @github/codeql-frontend-reviewers
2626
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
2727

2828
# QL for QL reviewers

cpp/ql/src/Best Practices/Unused Entities/UnusedStaticFunctions.ql

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,32 @@
1313

1414
import cpp
1515

16+
pragma[noinline]
17+
predicate possiblyIncompleteFile(File f) {
18+
exists(Diagnostic d | d.getFile() = f and d.getSeverity() >= 3)
19+
}
20+
1621
predicate immediatelyReachableFunction(Function f) {
17-
not f.isStatic() or
18-
exists(BlockExpr be | be.getFunction() = f) or
19-
f instanceof MemberFunction or
20-
f instanceof TemplateFunction or
21-
f.getFile() instanceof HeaderFile or
22-
f.getAnAttribute().hasName("constructor") or
23-
f.getAnAttribute().hasName("destructor") or
24-
f.getAnAttribute().hasName("used") or
22+
not f.isStatic()
23+
or
24+
exists(BlockExpr be | be.getFunction() = f)
25+
or
26+
f instanceof MemberFunction
27+
or
28+
f instanceof TemplateFunction
29+
or
30+
f.getFile() instanceof HeaderFile
31+
or
32+
f.getAnAttribute().hasName("constructor")
33+
or
34+
f.getAnAttribute().hasName("destructor")
35+
or
36+
f.getAnAttribute().hasName("used")
37+
or
2538
f.getAnAttribute().hasName("unused")
39+
or
40+
// a compiler error in the same file suggests we may be missing data
41+
possiblyIncompleteFile(f.getFile())
2642
}
2743

2844
predicate immediatelyReachableVariable(Variable v) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Fixed false positives from the "Unused static function" (`cpp/unused-static-function`) query in files that had errors during compilation.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
int main(int argc, char** argv) {
3+
char *filePath = argv[2];
4+
5+
{
6+
// BAD: the user-controlled string is injected
7+
// directly into `wordexp` which performs command substitution
8+
9+
wordexp_t we;
10+
wordexp(filePath, &we, 0);
11+
}
12+
13+
{
14+
// GOOD: command substitution is disabled
15+
16+
wordexp_t we;
17+
wordexp(filePath, &we, WRDE_NOCMD);
18+
}
19+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>The code passes user input to <code>wordexp</code>. This leaves the code
7+
vulnerable to attack by command injection, because <code>wordexp</code> performs command substitution.
8+
Command substitution is a feature that replaces <code>$(command)</code> or <code>`command`</code> with the
9+
output of the given command, allowing the user to run arbitrary code on the system.
10+
</p>
11+
12+
</overview>
13+
<recommendation>
14+
15+
<p>When calling <code>wordexp</code>, pass the <code>WRDE_NOCMD</code> flag to prevent command substitution.</p>
16+
17+
</recommendation>
18+
<example>
19+
<p>The following example passes a user-supplied file path to <code>wordexp</code> in two ways. The
20+
first way uses <code>wordexp</code> with no specified flags. As such, it is vulnerable to command
21+
injection.
22+
The second way uses <code>wordexp</code> with the <code>WRDE_NOCMD</code> flag. As such, no command substitution
23+
is performed, making this safe from command injection.</p>
24+
<sample src="WordexpTainted.c" />
25+
26+
</example>
27+
<references>
28+
29+
<li>CERT C Coding Standard:
30+
<a href="https://www.securecoding.cert.org/confluence/display/c/STR02-C.+Sanitize+data+passed+to+complex+subsystems">STR02-C.
31+
Sanitize data passed to complex subsystems</a>.</li>
32+
<li>
33+
OWASP:
34+
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
35+
</li>
36+
37+
38+
<!-- LocalWords: CWE STR
39+
-->
40+
41+
</references>
42+
</qhelp>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @name Uncontrolled data used in `wordexp` command
3+
* @description Using user-supplied data in a `wordexp` command, without
4+
* disabling command substitution, can make code vulnerable
5+
* to command injection.
6+
* @kind path-problem
7+
* @problem.severity error
8+
* @precision high
9+
* @id cpp/wordexp-injection
10+
* @tags security
11+
* external/cwe/cwe-078
12+
*/
13+
14+
import cpp
15+
import semmle.code.cpp.ir.dataflow.TaintTracking
16+
import semmle.code.cpp.security.FlowSources
17+
import DataFlow::PathGraph
18+
19+
/**
20+
* The `wordexp` function, which can perform command substitution.
21+
*/
22+
private class WordexpFunction extends Function {
23+
WordexpFunction() { hasGlobalName("wordexp") }
24+
}
25+
26+
/**
27+
* Holds if `fc` disables command substitution by containing `WRDE_NOCMD` as a flag argument.
28+
*/
29+
private predicate isCommandSubstitutionDisabled(FunctionCall fc) {
30+
fc.getArgument(2).getValue().toInt().bitAnd(4) = 4
31+
/* 4 = WRDE_NOCMD. Check whether the flag is set. */
32+
}
33+
34+
/**
35+
* A configuration to track user-supplied data to the `wordexp` function.
36+
*/
37+
class WordexpTaintConfiguration extends TaintTracking::Configuration {
38+
WordexpTaintConfiguration() { this = "WordexpTaintConfiguration" }
39+
40+
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
41+
42+
override predicate isSink(DataFlow::Node sink) {
43+
exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction |
44+
fc.getArgument(0) = sink.asExpr() and
45+
not isCommandSubstitutionDisabled(fc)
46+
)
47+
}
48+
49+
override predicate isSanitizer(DataFlow::Node node) {
50+
node.asExpr().getUnspecifiedType() instanceof IntegralType
51+
}
52+
}
53+
54+
from WordexpTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode
55+
where conf.hasFlowPath(sourceNode, sinkNode)
56+
select sinkNode.getNode(), sourceNode, sinkNode,
57+
"Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection."

0 commit comments

Comments
 (0)