mirror of
https://github.com/github/codeql.git
synced 2026-05-24 08:07:07 +02:00
Compare commits
149 Commits
calumgrant
...
max-schaef
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95c2788c83 | ||
|
|
73f71d8ace | ||
|
|
f6c22d466f | ||
|
|
aeacfb82c1 | ||
|
|
2fa2a5a53c | ||
|
|
977ac71b26 | ||
|
|
5dcd635403 | ||
|
|
a34bb2608d | ||
|
|
ece0d1f477 | ||
|
|
bfce01cef6 | ||
|
|
3d8ac1441a | ||
|
|
9eb51a9b9e | ||
|
|
9e47909208 | ||
|
|
3690f294da | ||
|
|
b6a1266ade | ||
|
|
ce0edcc265 | ||
|
|
e9957aa4a6 | ||
|
|
f6e2e1319b | ||
|
|
e6ba0a34f4 | ||
|
|
45b41bb506 | ||
|
|
6b1d1d427c | ||
|
|
6ea99825be | ||
|
|
ab255d70b5 | ||
|
|
fda3c92612 | ||
|
|
59ae6dd5f5 | ||
|
|
86bf4fbbc0 | ||
|
|
5b07e14fb3 | ||
|
|
0243d9f2b9 | ||
|
|
d9c40488bb | ||
|
|
b8e38288e3 | ||
|
|
ba89f1b6b1 | ||
|
|
7bb2b57394 | ||
|
|
8711232a38 | ||
|
|
2382f76317 | ||
|
|
f9d10cec08 | ||
|
|
6cd94cf253 | ||
|
|
050682c477 | ||
|
|
8e9b4336da | ||
|
|
27c6e2421c | ||
|
|
b617667b0e | ||
|
|
30c9ec1926 | ||
|
|
7a0446740b | ||
|
|
497325455a | ||
|
|
b4a6f75ad7 | ||
|
|
3e9602854a | ||
|
|
3bfaab9182 | ||
|
|
6a8c592900 | ||
|
|
d610d721a4 | ||
|
|
e3744c435a | ||
|
|
ec3d041c8d | ||
|
|
bd2ecd3346 | ||
|
|
2075716df7 | ||
|
|
d786ea90a4 | ||
|
|
2de62dfcdd | ||
|
|
c5604c97bd | ||
|
|
0646744928 | ||
|
|
cf9e2dcea1 | ||
|
|
f89109df7c | ||
|
|
d7258f76d3 | ||
|
|
f84609dbc4 | ||
|
|
0c5ea975a4 | ||
|
|
a950de36a0 | ||
|
|
c11b8f9d51 | ||
|
|
ff23f572d0 | ||
|
|
5bc710b406 | ||
|
|
98bf5269a0 | ||
|
|
f5ebd3d501 | ||
|
|
f67b5f9158 | ||
|
|
757b9bb5fa | ||
|
|
6fc99e3ad6 | ||
|
|
3d82318839 | ||
|
|
71ab804274 | ||
|
|
dcebcc35b6 | ||
|
|
568bddc4a9 | ||
|
|
17193ac11b | ||
|
|
a4401963f5 | ||
|
|
f347784ec2 | ||
|
|
3d9bc6fc89 | ||
|
|
5e0961b348 | ||
|
|
9fa2f19990 | ||
|
|
c48e64e536 | ||
|
|
1e0766dffa | ||
|
|
f2ff6c476a | ||
|
|
5cb5ee026c | ||
|
|
f317f782ae | ||
|
|
6cf956d07a | ||
|
|
cc8dcf63b0 | ||
|
|
ee36e3b72b | ||
|
|
403e86878c | ||
|
|
5243a62a41 | ||
|
|
c0874ab04b | ||
|
|
f66811048d | ||
|
|
bc0724e2b3 | ||
|
|
d5443b3f10 | ||
|
|
29e93edf90 | ||
|
|
00c7dd5f92 | ||
|
|
e59487a324 | ||
|
|
c7cb885e71 | ||
|
|
f44becea7f | ||
|
|
c283894b4b | ||
|
|
33b807f3bb | ||
|
|
7377cbb46e | ||
|
|
d516db6abc | ||
|
|
d805bbcd27 | ||
|
|
120fb93c23 | ||
|
|
dea922958b | ||
|
|
9c9f4b956e | ||
|
|
2f0b54c801 | ||
|
|
b94d33d78d | ||
|
|
7f53509022 | ||
|
|
6707fc3a7c | ||
|
|
148033e020 | ||
|
|
5ab5244171 | ||
|
|
ca5d85c57e | ||
|
|
0fa40af131 | ||
|
|
5a771ad2cf | ||
|
|
762b4ce42e | ||
|
|
1a8932bc28 | ||
|
|
c653f1ce8c | ||
|
|
a07ee8e961 | ||
|
|
178a45af25 | ||
|
|
ca72b0583d | ||
|
|
4b13ad1310 | ||
|
|
9ed8ca27a1 | ||
|
|
1f04229def | ||
|
|
73b4e8fe6a | ||
|
|
9b23bfa038 | ||
|
|
5885938eaf | ||
|
|
8223781978 | ||
|
|
5ca6b40c34 | ||
|
|
23aeb1d878 | ||
|
|
98285b5171 | ||
|
|
87ad170067 | ||
|
|
c520cb6d58 | ||
|
|
eef60c9ad2 | ||
|
|
c74d6348f9 | ||
|
|
0d527b2f75 | ||
|
|
96a6dd72cd | ||
|
|
1cfde49297 | ||
|
|
589a5039c8 | ||
|
|
be027e217e | ||
|
|
467f4e11a1 | ||
|
|
5a30ad162a | ||
|
|
3d4f7d880d | ||
|
|
ba10ea8121 | ||
|
|
3649af3f05 | ||
|
|
60b5e49905 | ||
|
|
916b1e959e | ||
|
|
533b63743b |
15
.github/workflows/codeql-analysis.yml
vendored
15
.github/workflows/codeql-analysis.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
uses: github/codeql-action/init@main
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
with:
|
||||
languages: csharp, cpp
|
||||
languages: csharp
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
@@ -57,19 +57,6 @@ jobs:
|
||||
|
||||
- run: |
|
||||
dotnet build csharp
|
||||
|
||||
- name: "[Ubuntu] Remove GCC 13 from runner image"
|
||||
shell: bash
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --allow-downgrades libc6=2.35-* libc6-dev=2.35-* libstdc++6=12.3.0-* libgcc-s1=12.3.0-*
|
||||
|
||||
- name: "Build Swift extractor using Bazel"
|
||||
run: |
|
||||
bazel clean --expunge
|
||||
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local --features=-layering_check
|
||||
bazel shutdown
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@main
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/cpp/ @github/codeql-c-analysis
|
||||
/cpp/autobuilder/ @github/codeql-c-extractor
|
||||
/csharp/ @github/codeql-csharp
|
||||
/go/ @github/codeql-go
|
||||
/java/ @github/codeql-java
|
||||
|
||||
@@ -18,7 +18,7 @@ bazel_dep(name = "rules_pkg", version = "0.9.1")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.0.3")
|
||||
bazel_dep(name = "rules_python", version = "0.31.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.5.0")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||
bazel_dep(name = "fmt", version = "10.0.0")
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ provide:
|
||||
- "misc/suite-helpers/qlpack.yml"
|
||||
- "ruby/extractor-pack/codeql-extractor.yml"
|
||||
- "swift/extractor-pack/codeql-extractor.yml"
|
||||
- "swift/integration-tests/qlpack.yml"
|
||||
- "ql/extractor-pack/codeql-extractor.yml"
|
||||
- ".github/codeql/extensions/**/codeql-pack.yml"
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Expr reuse, Expr original
|
||||
where expr_reuse(reuse, original, _)
|
||||
select reuse, original
|
||||
@@ -0,0 +1,22 @@
|
||||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Type extends @type {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate existingType(Expr expr, Type type, int value_category) {
|
||||
expr_types(expr, type, value_category)
|
||||
}
|
||||
|
||||
predicate reuseType(Expr reuse, Type type, int value_category) {
|
||||
exists(Expr original |
|
||||
expr_reuse(reuse, original, value_category) and
|
||||
expr_types(original, type, _)
|
||||
)
|
||||
}
|
||||
|
||||
from Expr expr, Type type, int value_category
|
||||
where existingType(expr, type, value_category) or reuseType(expr, type, value_category)
|
||||
select expr, type, value_category
|
||||
2251
cpp/downgrades/abfce5c170f93e281948f7689ece373464fdaf87/old.dbscheme
Normal file
2251
cpp/downgrades/abfce5c170f93e281948f7689ece373464fdaf87/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
description: Add value category to expr_reuse table
|
||||
compatibility: full
|
||||
expr_reuse.rel: run expr_reuse.qlo
|
||||
expr_types.rel: run expr_types.qlo
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.12.9
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.12.8
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added destructors for temporary objects with extended lifetimes to the intermediate representation.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a `TaintInheritingContent` class that can be extended to model taint flowing from a qualifier to a field.
|
||||
3
cpp/ql/lib/change-notes/released/0.12.9.md
Normal file
3
cpp/ql/lib/change-notes/released/0.12.9.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.12.9
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.12.8
|
||||
lastReleaseVersion: 0.12.9
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.12.9-dev
|
||||
version: 0.12.10-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -590,6 +590,33 @@ class TemplateVariable extends Variable {
|
||||
Variable getAnInstantiation() { result.isConstructedFrom(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable that is an instantiation of a template. For example
|
||||
* the instantiation `myTemplateVariable<int>` in the following code:
|
||||
* ```
|
||||
* template<class T>
|
||||
* T myTemplateVariable;
|
||||
*
|
||||
* void caller(int i) {
|
||||
* myTemplateVariable<int> = i;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class VariableTemplateInstantiation extends Variable {
|
||||
TemplateVariable tv;
|
||||
|
||||
VariableTemplateInstantiation() { tv.getAnInstantiation() = this }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "VariableTemplateInstantiation" }
|
||||
|
||||
/**
|
||||
* Gets the variable template from which this instantiation was instantiated.
|
||||
*
|
||||
* Example: For `int x<int>`, returns `T x`.
|
||||
*/
|
||||
TemplateVariable getTemplate() { result = tv }
|
||||
}
|
||||
|
||||
/**
|
||||
* A non-static local variable or parameter that is not part of an
|
||||
* uninstantiated template. Uninstantiated templates are purely syntax, and
|
||||
|
||||
@@ -1340,5 +1340,13 @@ class ReuseExpr extends Expr, @reuseexpr {
|
||||
/**
|
||||
* Gets the expression that is being re-used.
|
||||
*/
|
||||
Expr getReusedExpr() { expr_reuse(underlyingElement(this), unresolveElement(result)) }
|
||||
Expr getReusedExpr() { expr_reuse(underlyingElement(this), unresolveElement(result), _) }
|
||||
|
||||
override Type getType() { result = this.getReusedExpr().getType() }
|
||||
|
||||
override predicate isLValueCategory() { expr_reuse(underlyingElement(this), _, 3) }
|
||||
|
||||
override predicate isXValueCategory() { expr_reuse(underlyingElement(this), _, 2) }
|
||||
|
||||
override predicate isPRValueCategory() { expr_reuse(underlyingElement(this), _, 1) }
|
||||
}
|
||||
|
||||
20
cpp/ql/lib/semmle/code/cpp/ir/dataflow/FlowSteps.qll
Normal file
20
cpp/ql/lib/semmle/code/cpp/ir/dataflow/FlowSteps.qll
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* This file provides an abstract class that can be used to model additional
|
||||
* object-to-field taint-flow.
|
||||
*/
|
||||
|
||||
private import codeql.util.Unit
|
||||
private import semmle.code.cpp.dataflow.new.DataFlow
|
||||
|
||||
/**
|
||||
* A `Content` that should be implicitly regarded as tainted whenever an object with such `Content`
|
||||
* is itself tainted.
|
||||
*
|
||||
* For example, if we had a type `struct Container { int field; }`, then by default a tainted
|
||||
* `Container` and a `Container` with a tainted `int` stored in its `field` are distinct.
|
||||
*
|
||||
* If `any(DataFlow::FieldContent fc | fc.getField().hasQualifiedName("Container", "field"))` was
|
||||
* included in this type however, then a tainted `Container` would imply that its `field` is also
|
||||
* tainted (but not vice versa).
|
||||
*/
|
||||
abstract class TaintInheritingContent extends DataFlow::Content { }
|
||||
@@ -2301,8 +2301,8 @@ private import ContentStars
|
||||
|
||||
/** A reference through a non-union instance field. */
|
||||
class FieldContent extends Content, TFieldContent {
|
||||
Field f;
|
||||
int indirectionIndex;
|
||||
private Field f;
|
||||
private int indirectionIndex;
|
||||
|
||||
FieldContent() { this = TFieldContent(f, indirectionIndex) }
|
||||
|
||||
@@ -2329,9 +2329,9 @@ class FieldContent extends Content, TFieldContent {
|
||||
|
||||
/** A reference through an instance field of a union. */
|
||||
class UnionContent extends Content, TUnionContent {
|
||||
Union u;
|
||||
int indirectionIndex;
|
||||
int bytes;
|
||||
private Union u;
|
||||
private int indirectionIndex;
|
||||
private int bytes;
|
||||
|
||||
UnionContent() { this = TUnionContent(u, bytes, indirectionIndex) }
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ private import semmle.code.cpp.models.interfaces.SideEffect
|
||||
private import DataFlowUtil
|
||||
private import DataFlowPrivate
|
||||
private import SsaInternals as Ssa
|
||||
private import semmle.code.cpp.ir.dataflow.FlowSteps
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||
@@ -37,6 +38,12 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
|
||||
)
|
||||
or
|
||||
any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo)
|
||||
or
|
||||
// object->field conflation for content that is a `TaintInheritingContent`.
|
||||
exists(DataFlow::ContentSet f |
|
||||
readStep(nodeFrom, f, nodeTo) and
|
||||
f.getAReadContent() instanceof TaintInheritingContent
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -130,11 +130,6 @@ private predicate ignoreExprAndDescendants(Expr expr) {
|
||||
or
|
||||
// suppress destructors of temporary variables until proper support is added for them.
|
||||
exists(Expr parent | parent.getAnImplicitDestructorCall() = expr)
|
||||
or
|
||||
exists(Stmt parent |
|
||||
parent.getAnImplicitDestructorCall() = expr and
|
||||
expr.(DestructorCall).getQualifier() instanceof ReuseExpr
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2769,6 +2769,50 @@ class TranslatedTemporaryObjectExpr extends TranslatedNonConstantExpr,
|
||||
final override Instruction getResult() { result = this.getTargetAddress() }
|
||||
}
|
||||
|
||||
/**
|
||||
* IR translation of a `ReuseExpr`.
|
||||
*
|
||||
* This translation produces a copy of the glvalue instruction holding the (unconverted) result
|
||||
* of the reused expression. In the case where the original expression was a prvalue, the
|
||||
* result will be a copy of the glvalue operand of a `TranslatedLoad`.
|
||||
*/
|
||||
class TranslatedReuseExpr extends TranslatedNonConstantExpr {
|
||||
override ReuseExpr expr;
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
opcode instanceof Opcode::CopyValue and
|
||||
tag instanceof OnlyInstructionTag and
|
||||
resultType = this.getResultType()
|
||||
}
|
||||
|
||||
override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
if getTranslatedExpr(expr.getReusedExpr()) instanceof TranslatedLoad
|
||||
then result = getTranslatedExpr(expr.getReusedExpr()).(TranslatedLoad).getOperand().getResult()
|
||||
else result = getTranslatedExpr(expr.getReusedExpr()).getResult()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IR translation of a `throw` expression.
|
||||
*/
|
||||
|
||||
@@ -248,19 +248,9 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
final override TranslatedElement getChild(int id) {
|
||||
result = this.getChildInternal(id)
|
||||
or
|
||||
exists(int destructorIndex, int tempDestructorCount |
|
||||
exists(int destructorIndex |
|
||||
result.(TranslatedExpr).getExpr() = stmt.getImplicitDestructorCall(destructorIndex) and
|
||||
id = this.getFirstDestructorCallIndex() + destructorIndex - tempDestructorCount and
|
||||
// suppress destructors of temporary variables until proper support is added for them.
|
||||
tempDestructorCount =
|
||||
count(DestructorCall call, int tempIndex |
|
||||
stmt.getImplicitDestructorCall(tempIndex) = call and
|
||||
tempIndex < destructorIndex and
|
||||
call.getQualifier() instanceof ReuseExpr
|
||||
|
|
||||
call
|
||||
) and
|
||||
not stmt.getImplicitDestructorCall(destructorIndex).getQualifier() instanceof ReuseExpr
|
||||
id = this.getFirstDestructorCallIndex() + destructorIndex
|
||||
)
|
||||
}
|
||||
|
||||
@@ -271,11 +261,7 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
}
|
||||
|
||||
final override predicate hasAnImplicitDestructorCall() {
|
||||
exists(stmt.getAnImplicitDestructorCall()) and
|
||||
// suppress destructors of temporary variables until proper support is added for them.
|
||||
exists(Expr expr | stmt.getAnImplicitDestructorCall().getQualifier() = expr |
|
||||
not expr instanceof ReuseExpr
|
||||
)
|
||||
exists(stmt.getAnImplicitDestructorCall())
|
||||
}
|
||||
|
||||
final override string toString() { result = stmt.toString() }
|
||||
|
||||
@@ -1515,7 +1515,8 @@ exprs(
|
||||
|
||||
expr_reuse(
|
||||
int reuse: @expr ref,
|
||||
int original: @expr ref
|
||||
int original: @expr ref,
|
||||
int value_category: int ref
|
||||
)
|
||||
|
||||
/*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Expr reuse, Expr original, int value_category
|
||||
where expr_reuse(reuse, original) and expr_types(original, _, value_category)
|
||||
select reuse, original, value_category
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Add value category to expr_reuse table
|
||||
compatibility: full
|
||||
expr_reuse.rel: run expr_reuse.qlo
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.9.8
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.9.7
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
cpp/ql/src/change-notes/released/0.9.8.md
Normal file
3
cpp/ql/src/change-notes/released/0.9.8.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.9.8
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.9.7
|
||||
lastReleaseVersion: 0.9.8
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.9.8-dev
|
||||
version: 0.9.9-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -6676,6 +6676,7 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
|
||||
| taint.cpp:757:7:757:10 | path | taint.cpp:759:8:759:11 | path | |
|
||||
| taint.cpp:758:21:758:24 | ref arg path | taint.cpp:759:8:759:11 | path | |
|
||||
| taint.cpp:759:8:759:11 | path | taint.cpp:759:7:759:11 | * ... | |
|
||||
| taint.cpp:769:37:769:42 | call to source | taint.cpp:770:7:770:9 | obj | |
|
||||
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
|
||||
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
|
||||
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |
|
||||
|
||||
@@ -757,4 +757,15 @@ void test_call_sprintf() {
|
||||
char path[10];
|
||||
call_sprintf_twice(path, indirect_source());
|
||||
sink(*path); // $ ast,ir
|
||||
}
|
||||
|
||||
struct TaintInheritingContentObject {
|
||||
int flowFromObject;
|
||||
};
|
||||
|
||||
TaintInheritingContentObject source(bool);
|
||||
|
||||
void test_TaintInheritingContent() {
|
||||
TaintInheritingContentObject obj = source(true);
|
||||
sink(obj.flowFromObject); // $ ir MISSING: ast
|
||||
}
|
||||
@@ -76,6 +76,24 @@ module AstTest {
|
||||
module IRTest {
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
private import semmle.code.cpp.ir.dataflow.FlowSteps
|
||||
|
||||
/**
|
||||
* Object->field flow when the object is of type
|
||||
* TaintInheritingContentObject and the field is named
|
||||
* flowFromObject
|
||||
*/
|
||||
class TaintInheritingContentTest extends TaintInheritingContent, DataFlow::FieldContent {
|
||||
TaintInheritingContentTest() {
|
||||
exists(Struct o, Field f |
|
||||
this.getField() = f and
|
||||
f = o.getAField() and
|
||||
o.hasGlobalName("TaintInheritingContentObject") and
|
||||
f.hasName("flowFromObject") and
|
||||
this.getIndirectionIndex() = 1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
module TestAllocationConfig implements DataFlow::ConfigSig {
|
||||
|
||||
@@ -15605,7 +15605,7 @@ ir.cpp:
|
||||
# 1934| Type = [ClassTemplateInstantiation,Struct] Bar2<int>
|
||||
# 1934| ValueCategory = lvalue
|
||||
# 1935| getStmt(2): [ReturnStmt] return ...
|
||||
# 1938| [GlobalVariable] char global_template<char>
|
||||
# 1938| [GlobalVariable,VariableTemplateInstantiation] char global_template<char>
|
||||
# 1938| getInitializer(): [Initializer] initializer for global_template
|
||||
# 1938| getExpr(): [Literal] 42
|
||||
# 1938| Type = [IntType] int
|
||||
@@ -15616,7 +15616,7 @@ ir.cpp:
|
||||
# 1938| Type = [PlainCharType] char
|
||||
# 1938| Value = [CStyleCast] 42
|
||||
# 1938| ValueCategory = prvalue
|
||||
# 1938| [GlobalVariable] int global_template<int>
|
||||
# 1938| [GlobalVariable,VariableTemplateInstantiation] int global_template<int>
|
||||
# 1938| getInitializer(): [Initializer] initializer for global_template
|
||||
# 1938| getExpr(): [Literal] 42
|
||||
# 1938| Type = [IntType] int
|
||||
|
||||
@@ -891,24 +891,32 @@ destructors_for_temps.cpp:
|
||||
|
||||
# 29| void temp_test3()
|
||||
# 29| Block 0
|
||||
# 29| v29_1(void) = EnterFunction :
|
||||
# 29| m29_2(unknown) = AliasedDefinition :
|
||||
# 29| m29_3(unknown) = InitializeNonLocal :
|
||||
# 29| m29_4(unknown) = Chi : total:m29_2, partial:m29_3
|
||||
# 30| r30_1(glval<ClassWithDestructor2 &>) = VariableAddress[rs] :
|
||||
# 30| r30_2(glval<ClassWithDestructor2>) = VariableAddress[#temp30:38] :
|
||||
# 30| r30_3(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 30| r30_4(ClassWithDestructor2) = Call[returnValue] : func:r30_3
|
||||
# 30| m30_5(unknown) = ^CallSideEffect : ~m29_4
|
||||
# 30| m30_6(unknown) = Chi : total:m29_4, partial:m30_5
|
||||
# 30| m30_7(ClassWithDestructor2) = Store[#temp30:38] : &:r30_2, r30_4
|
||||
# 30| r30_8(glval<ClassWithDestructor2>) = Convert : r30_2
|
||||
# 30| r30_9(ClassWithDestructor2 &) = CopyValue : r30_8
|
||||
# 30| m30_10(ClassWithDestructor2 &) = Store[rs] : &:r30_1, r30_9
|
||||
# 31| v31_1(void) = NoOp :
|
||||
# 29| v29_5(void) = ReturnVoid :
|
||||
# 29| v29_6(void) = AliasedUse : ~m30_6
|
||||
# 29| v29_7(void) = ExitFunction :
|
||||
# 29| v29_1(void) = EnterFunction :
|
||||
# 29| m29_2(unknown) = AliasedDefinition :
|
||||
# 29| m29_3(unknown) = InitializeNonLocal :
|
||||
# 29| m29_4(unknown) = Chi : total:m29_2, partial:m29_3
|
||||
# 30| r30_1(glval<ClassWithDestructor2 &>) = VariableAddress[rs] :
|
||||
# 30| r30_2(glval<ClassWithDestructor2>) = VariableAddress[#temp30:38] :
|
||||
# 30| r30_3(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 30| r30_4(ClassWithDestructor2) = Call[returnValue] : func:r30_3
|
||||
# 30| m30_5(unknown) = ^CallSideEffect : ~m29_4
|
||||
# 30| m30_6(unknown) = Chi : total:m29_4, partial:m30_5
|
||||
# 30| m30_7(ClassWithDestructor2) = Store[#temp30:38] : &:r30_2, r30_4
|
||||
# 30| r30_8(glval<ClassWithDestructor2>) = Convert : r30_2
|
||||
# 30| r30_9(ClassWithDestructor2 &) = CopyValue : r30_8
|
||||
# 30| m30_10(ClassWithDestructor2 &) = Store[rs] : &:r30_1, r30_9
|
||||
# 31| v31_1(void) = NoOp :
|
||||
# 31| r31_2(glval<ClassWithDestructor2>) = CopyValue : r30_2
|
||||
# 31| r31_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
|
||||
# 31| v31_4(void) = Call[~ClassWithDestructor2] : func:r31_3, this:r31_2
|
||||
# 31| m31_5(unknown) = ^CallSideEffect : ~m30_6
|
||||
# 31| m31_6(unknown) = Chi : total:m30_6, partial:m31_5
|
||||
# 31| v31_7(void) = ^IndirectReadSideEffect[-1] : &:r31_2, m30_7
|
||||
# 31| m31_8(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r31_2
|
||||
# 31| m31_9(ClassWithDestructor2) = Chi : total:m30_7, partial:m31_8
|
||||
# 29| v29_5(void) = ReturnVoid :
|
||||
# 29| v29_6(void) = AliasedUse : ~m31_6
|
||||
# 29| v29_7(void) = ExitFunction :
|
||||
|
||||
# 33| void temp_test4()
|
||||
# 33| Block 0
|
||||
@@ -935,16 +943,24 @@ destructors_for_temps.cpp:
|
||||
# 35| r35_9(ClassWithDestructor2 &) = CopyValue : r35_8
|
||||
# 35| m35_10(ClassWithDestructor2 &) = Store[rs2] : &:r35_1, r35_9
|
||||
# 36| v36_1(void) = NoOp :
|
||||
# 36| r36_2(glval<ClassWithDestructor2>) = VariableAddress[c] :
|
||||
# 36| r36_2(glval<ClassWithDestructor2>) = CopyValue : r35_2
|
||||
# 36| r36_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
|
||||
# 36| v36_4(void) = Call[~ClassWithDestructor2] : func:r36_3, this:r36_2
|
||||
# 36| m36_5(unknown) = ^CallSideEffect : ~m35_6
|
||||
# 36| m36_6(unknown) = Chi : total:m35_6, partial:m36_5
|
||||
# 36| v36_7(void) = ^IndirectReadSideEffect[-1] : &:r36_2, m34_8
|
||||
# 36| v36_7(void) = ^IndirectReadSideEffect[-1] : &:r36_2, m35_7
|
||||
# 36| m36_8(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r36_2
|
||||
# 36| m36_9(ClassWithDestructor2) = Chi : total:m34_8, partial:m36_8
|
||||
# 36| m36_9(ClassWithDestructor2) = Chi : total:m35_7, partial:m36_8
|
||||
# 36| r36_10(glval<ClassWithDestructor2>) = VariableAddress[c] :
|
||||
# 36| r36_11(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
|
||||
# 36| v36_12(void) = Call[~ClassWithDestructor2] : func:r36_11, this:r36_10
|
||||
# 36| m36_13(unknown) = ^CallSideEffect : ~m36_6
|
||||
# 36| m36_14(unknown) = Chi : total:m36_6, partial:m36_13
|
||||
# 36| v36_15(void) = ^IndirectReadSideEffect[-1] : &:r36_10, m34_8
|
||||
# 36| m36_16(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r36_10
|
||||
# 36| m36_17(ClassWithDestructor2) = Chi : total:m34_8, partial:m36_16
|
||||
# 33| v33_5(void) = ReturnVoid :
|
||||
# 33| v33_6(void) = AliasedUse : ~m36_6
|
||||
# 33| v33_6(void) = AliasedUse : ~m36_14
|
||||
# 33| v33_7(void) = ExitFunction :
|
||||
|
||||
# 38| void temp_test5(bool)
|
||||
@@ -8882,16 +8898,24 @@ ir.cpp:
|
||||
# 1425| m1425_5(unknown) = Chi : total:m1423_11, partial:m1425_4
|
||||
# 1425| m1425_6(String) = Store[#temp1425:5] : &:r1425_1, r1425_3
|
||||
# 1426| v1426_1(void) = NoOp :
|
||||
# 1426| r1426_2(glval<String>) = VariableAddress[s] :
|
||||
# 1426| r1426_2(glval<String>) = CopyValue : r1416_2
|
||||
# 1426| r1426_3(glval<unknown>) = FunctionAddress[~String] :
|
||||
# 1426| v1426_4(void) = Call[~String] : func:r1426_3, this:r1426_2
|
||||
# 1426| m1426_5(unknown) = ^CallSideEffect : ~m1425_5
|
||||
# 1426| m1426_6(unknown) = Chi : total:m1425_5, partial:m1426_5
|
||||
# 1426| v1426_7(void) = ^IndirectReadSideEffect[-1] : &:r1426_2, m1415_6
|
||||
# 1426| v1426_7(void) = ^IndirectReadSideEffect[-1] : &:r1426_2, m1416_7
|
||||
# 1426| m1426_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r1426_2
|
||||
# 1426| m1426_9(String) = Chi : total:m1415_6, partial:m1426_8
|
||||
# 1426| m1426_9(String) = Chi : total:m1416_7, partial:m1426_8
|
||||
# 1426| r1426_10(glval<String>) = VariableAddress[s] :
|
||||
# 1426| r1426_11(glval<unknown>) = FunctionAddress[~String] :
|
||||
# 1426| v1426_12(void) = Call[~String] : func:r1426_11, this:r1426_10
|
||||
# 1426| m1426_13(unknown) = ^CallSideEffect : ~m1426_6
|
||||
# 1426| m1426_14(unknown) = Chi : total:m1426_6, partial:m1426_13
|
||||
# 1426| v1426_15(void) = ^IndirectReadSideEffect[-1] : &:r1426_10, m1415_6
|
||||
# 1426| m1426_16(String) = ^IndirectMayWriteSideEffect[-1] : &:r1426_10
|
||||
# 1426| m1426_17(String) = Chi : total:m1415_6, partial:m1426_16
|
||||
# 1414| v1414_5(void) = ReturnVoid :
|
||||
# 1414| v1414_6(void) = AliasedUse : ~m1426_6
|
||||
# 1414| v1414_6(void) = AliasedUse : ~m1426_14
|
||||
# 1414| v1414_7(void) = ExitFunction :
|
||||
|
||||
# 1428| void temporary_destructor_only()
|
||||
@@ -8973,16 +8997,24 @@ ir.cpp:
|
||||
# 1438| v1438_7(void) = ^IndirectReadSideEffect[-1] : &:r1438_2, m1431_2
|
||||
# 1438| m1438_8(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1438_2
|
||||
# 1438| m1438_9(destructor_only) = Chi : total:m1431_2, partial:m1438_8
|
||||
# 1438| r1438_10(glval<destructor_only>) = VariableAddress[d] :
|
||||
# 1438| r1438_10(glval<destructor_only>) = CopyValue : r1430_2
|
||||
# 1438| r1438_11(glval<unknown>) = FunctionAddress[~destructor_only] :
|
||||
# 1438| v1438_12(void) = Call[~destructor_only] : func:r1438_11, this:r1438_10
|
||||
# 1438| m1438_13(unknown) = ^CallSideEffect : ~m1438_6
|
||||
# 1438| m1438_14(unknown) = Chi : total:m1438_6, partial:m1438_13
|
||||
# 1438| v1438_15(void) = ^IndirectReadSideEffect[-1] : &:r1438_10, m1429_6
|
||||
# 1438| v1438_15(void) = ^IndirectReadSideEffect[-1] : &:r1438_10, m1430_7
|
||||
# 1438| m1438_16(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1438_10
|
||||
# 1438| m1438_17(destructor_only) = Chi : total:m1429_6, partial:m1438_16
|
||||
# 1438| m1438_17(destructor_only) = Chi : total:m1430_7, partial:m1438_16
|
||||
# 1438| r1438_18(glval<destructor_only>) = VariableAddress[d] :
|
||||
# 1438| r1438_19(glval<unknown>) = FunctionAddress[~destructor_only] :
|
||||
# 1438| v1438_20(void) = Call[~destructor_only] : func:r1438_19, this:r1438_18
|
||||
# 1438| m1438_21(unknown) = ^CallSideEffect : ~m1438_14
|
||||
# 1438| m1438_22(unknown) = Chi : total:m1438_14, partial:m1438_21
|
||||
# 1438| v1438_23(void) = ^IndirectReadSideEffect[-1] : &:r1438_18, m1429_6
|
||||
# 1438| m1438_24(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1438_18
|
||||
# 1438| m1438_25(destructor_only) = Chi : total:m1429_6, partial:m1438_24
|
||||
# 1428| v1428_5(void) = ReturnVoid :
|
||||
# 1428| v1428_6(void) = AliasedUse : ~m1438_14
|
||||
# 1428| v1428_6(void) = AliasedUse : ~m1438_22
|
||||
# 1428| v1428_7(void) = ExitFunction :
|
||||
|
||||
# 1440| void temporary_copy_constructor()
|
||||
|
||||
@@ -805,7 +805,7 @@
|
||||
| destructors_for_temps.cpp:23:68:23:72 | Unary | r23_27 |
|
||||
| destructors_for_temps.cpp:29:6:29:15 | ChiPartial | partial:m29_3 |
|
||||
| destructors_for_temps.cpp:29:6:29:15 | ChiTotal | total:m29_2 |
|
||||
| destructors_for_temps.cpp:29:6:29:15 | SideEffect | ~m30_6 |
|
||||
| destructors_for_temps.cpp:29:6:29:15 | SideEffect | ~m31_6 |
|
||||
| destructors_for_temps.cpp:30:33:30:34 | Address | &:r30_1 |
|
||||
| destructors_for_temps.cpp:30:38:30:70 | CallTarget | func:r30_3 |
|
||||
| destructors_for_temps.cpp:30:38:30:70 | ChiPartial | partial:m30_5 |
|
||||
@@ -815,10 +815,21 @@
|
||||
| destructors_for_temps.cpp:30:38:30:72 | Address | &:r30_2 |
|
||||
| destructors_for_temps.cpp:30:38:30:72 | StoreValue | r30_9 |
|
||||
| destructors_for_temps.cpp:30:38:30:72 | Unary | r30_2 |
|
||||
| destructors_for_temps.cpp:30:38:30:72 | Unary | r30_2 |
|
||||
| destructors_for_temps.cpp:30:38:30:72 | Unary | r30_8 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | Address | &:r31_2 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | Address | &:r31_2 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | Arg(this) | this:r31_2 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | CallTarget | func:r31_3 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | ChiPartial | partial:m31_5 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | ChiPartial | partial:m31_8 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | ChiTotal | total:m30_6 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | ChiTotal | total:m30_7 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | SideEffect | m30_7 |
|
||||
| destructors_for_temps.cpp:31:1:31:1 | SideEffect | ~m30_6 |
|
||||
| destructors_for_temps.cpp:33:6:33:15 | ChiPartial | partial:m33_3 |
|
||||
| destructors_for_temps.cpp:33:6:33:15 | ChiTotal | total:m33_2 |
|
||||
| destructors_for_temps.cpp:33:6:33:15 | SideEffect | ~m36_6 |
|
||||
| destructors_for_temps.cpp:33:6:33:15 | SideEffect | ~m36_14 |
|
||||
| destructors_for_temps.cpp:34:26:34:26 | Address | &:r34_1 |
|
||||
| destructors_for_temps.cpp:34:26:34:26 | Address | &:r34_1 |
|
||||
| destructors_for_temps.cpp:34:26:34:26 | Arg(this) | this:r34_1 |
|
||||
@@ -837,17 +848,28 @@
|
||||
| destructors_for_temps.cpp:35:39:35:73 | Address | &:r35_2 |
|
||||
| destructors_for_temps.cpp:35:39:35:73 | StoreValue | r35_9 |
|
||||
| destructors_for_temps.cpp:35:39:35:73 | Unary | r35_2 |
|
||||
| destructors_for_temps.cpp:35:39:35:73 | Unary | r35_2 |
|
||||
| destructors_for_temps.cpp:35:39:35:73 | Unary | r35_8 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | Address | &:r36_2 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | Address | &:r36_2 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | Address | &:r36_10 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | Address | &:r36_10 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | Arg(this) | this:r36_2 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | Arg(this) | this:r36_10 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | CallTarget | func:r36_3 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | CallTarget | func:r36_11 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | ChiPartial | partial:m36_5 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | ChiPartial | partial:m36_8 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | ChiPartial | partial:m36_13 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | ChiPartial | partial:m36_16 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | ChiTotal | total:m34_8 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | ChiTotal | total:m35_6 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | ChiTotal | total:m35_7 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | ChiTotal | total:m36_6 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | SideEffect | m34_8 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | SideEffect | m35_7 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | SideEffect | ~m35_6 |
|
||||
| destructors_for_temps.cpp:36:1:36:1 | SideEffect | ~m36_6 |
|
||||
| destructors_for_temps.cpp:38:6:38:15 | ChiPartial | partial:m38_3 |
|
||||
| destructors_for_temps.cpp:38:6:38:15 | ChiTotal | total:m38_2 |
|
||||
| destructors_for_temps.cpp:38:6:38:15 | SideEffect | ~m39_5 |
|
||||
@@ -7276,7 +7298,7 @@
|
||||
| ir.cpp:1376:5:1376:15 | StoreValue | r1376_2 |
|
||||
| ir.cpp:1414:6:1414:21 | ChiPartial | partial:m1414_3 |
|
||||
| ir.cpp:1414:6:1414:21 | ChiTotal | total:m1414_2 |
|
||||
| ir.cpp:1414:6:1414:21 | SideEffect | ~m1426_6 |
|
||||
| ir.cpp:1414:6:1414:21 | SideEffect | ~m1426_14 |
|
||||
| ir.cpp:1415:12:1415:12 | Address | &:r1415_1 |
|
||||
| ir.cpp:1415:16:1415:34 | CallTarget | func:r1415_2 |
|
||||
| ir.cpp:1415:16:1415:34 | ChiPartial | partial:m1415_4 |
|
||||
@@ -7292,6 +7314,7 @@
|
||||
| ir.cpp:1416:24:1416:44 | Address | &:r1416_2 |
|
||||
| ir.cpp:1416:24:1416:44 | StoreValue | r1416_9 |
|
||||
| ir.cpp:1416:24:1416:44 | Unary | r1416_2 |
|
||||
| ir.cpp:1416:24:1416:44 | Unary | r1416_2 |
|
||||
| ir.cpp:1416:24:1416:44 | Unary | r1416_8 |
|
||||
| ir.cpp:1418:5:1418:13 | CallTarget | func:r1418_1 |
|
||||
| ir.cpp:1418:5:1418:13 | ChiPartial | partial:m1418_6 |
|
||||
@@ -7403,17 +7426,27 @@
|
||||
| ir.cpp:1425:5:1425:30 | Address | &:r1425_1 |
|
||||
| ir.cpp:1426:1:1426:1 | Address | &:r1426_2 |
|
||||
| ir.cpp:1426:1:1426:1 | Address | &:r1426_2 |
|
||||
| ir.cpp:1426:1:1426:1 | Address | &:r1426_10 |
|
||||
| ir.cpp:1426:1:1426:1 | Address | &:r1426_10 |
|
||||
| ir.cpp:1426:1:1426:1 | Arg(this) | this:r1426_2 |
|
||||
| ir.cpp:1426:1:1426:1 | Arg(this) | this:r1426_10 |
|
||||
| ir.cpp:1426:1:1426:1 | CallTarget | func:r1426_3 |
|
||||
| ir.cpp:1426:1:1426:1 | CallTarget | func:r1426_11 |
|
||||
| ir.cpp:1426:1:1426:1 | ChiPartial | partial:m1426_5 |
|
||||
| ir.cpp:1426:1:1426:1 | ChiPartial | partial:m1426_8 |
|
||||
| ir.cpp:1426:1:1426:1 | ChiPartial | partial:m1426_13 |
|
||||
| ir.cpp:1426:1:1426:1 | ChiPartial | partial:m1426_16 |
|
||||
| ir.cpp:1426:1:1426:1 | ChiTotal | total:m1415_6 |
|
||||
| ir.cpp:1426:1:1426:1 | ChiTotal | total:m1416_7 |
|
||||
| ir.cpp:1426:1:1426:1 | ChiTotal | total:m1425_5 |
|
||||
| ir.cpp:1426:1:1426:1 | ChiTotal | total:m1426_6 |
|
||||
| ir.cpp:1426:1:1426:1 | SideEffect | m1415_6 |
|
||||
| ir.cpp:1426:1:1426:1 | SideEffect | m1416_7 |
|
||||
| ir.cpp:1426:1:1426:1 | SideEffect | ~m1425_5 |
|
||||
| ir.cpp:1426:1:1426:1 | SideEffect | ~m1426_6 |
|
||||
| ir.cpp:1428:6:1428:30 | ChiPartial | partial:m1428_3 |
|
||||
| ir.cpp:1428:6:1428:30 | ChiTotal | total:m1428_2 |
|
||||
| ir.cpp:1428:6:1428:30 | SideEffect | ~m1438_14 |
|
||||
| ir.cpp:1428:6:1428:30 | SideEffect | ~m1438_22 |
|
||||
| ir.cpp:1429:21:1429:21 | Address | &:r1429_1 |
|
||||
| ir.cpp:1429:25:1429:52 | CallTarget | func:r1429_2 |
|
||||
| ir.cpp:1429:25:1429:52 | ChiPartial | partial:m1429_4 |
|
||||
@@ -7429,6 +7462,7 @@
|
||||
| ir.cpp:1430:33:1430:62 | Address | &:r1430_2 |
|
||||
| ir.cpp:1430:33:1430:62 | StoreValue | r1430_9 |
|
||||
| ir.cpp:1430:33:1430:62 | Unary | r1430_2 |
|
||||
| ir.cpp:1430:33:1430:62 | Unary | r1430_2 |
|
||||
| ir.cpp:1430:33:1430:62 | Unary | r1430_8 |
|
||||
| ir.cpp:1431:21:1431:22 | Address | &:r1431_1 |
|
||||
| ir.cpp:1432:5:1432:13 | CallTarget | func:r1432_1 |
|
||||
@@ -7489,22 +7523,32 @@
|
||||
| ir.cpp:1438:1:1438:1 | Address | &:r1438_2 |
|
||||
| ir.cpp:1438:1:1438:1 | Address | &:r1438_10 |
|
||||
| ir.cpp:1438:1:1438:1 | Address | &:r1438_10 |
|
||||
| ir.cpp:1438:1:1438:1 | Address | &:r1438_18 |
|
||||
| ir.cpp:1438:1:1438:1 | Address | &:r1438_18 |
|
||||
| ir.cpp:1438:1:1438:1 | Arg(this) | this:r1438_2 |
|
||||
| ir.cpp:1438:1:1438:1 | Arg(this) | this:r1438_10 |
|
||||
| ir.cpp:1438:1:1438:1 | Arg(this) | this:r1438_18 |
|
||||
| ir.cpp:1438:1:1438:1 | CallTarget | func:r1438_3 |
|
||||
| ir.cpp:1438:1:1438:1 | CallTarget | func:r1438_11 |
|
||||
| ir.cpp:1438:1:1438:1 | CallTarget | func:r1438_19 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiPartial | partial:m1438_5 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiPartial | partial:m1438_8 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiPartial | partial:m1438_13 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiPartial | partial:m1438_16 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiPartial | partial:m1438_21 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiPartial | partial:m1438_24 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiTotal | total:m1429_6 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiTotal | total:m1430_7 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiTotal | total:m1431_2 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiTotal | total:m1437_5 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiTotal | total:m1438_6 |
|
||||
| ir.cpp:1438:1:1438:1 | ChiTotal | total:m1438_14 |
|
||||
| ir.cpp:1438:1:1438:1 | SideEffect | m1429_6 |
|
||||
| ir.cpp:1438:1:1438:1 | SideEffect | m1430_7 |
|
||||
| ir.cpp:1438:1:1438:1 | SideEffect | m1431_2 |
|
||||
| ir.cpp:1438:1:1438:1 | SideEffect | ~m1437_5 |
|
||||
| ir.cpp:1438:1:1438:1 | SideEffect | ~m1438_6 |
|
||||
| ir.cpp:1438:1:1438:1 | SideEffect | ~m1438_14 |
|
||||
| ir.cpp:1440:6:1440:31 | ChiPartial | partial:m1440_3 |
|
||||
| ir.cpp:1440:6:1440:31 | ChiTotal | total:m1440_2 |
|
||||
| ir.cpp:1440:6:1440:31 | SideEffect | ~m1450_6 |
|
||||
|
||||
@@ -849,22 +849,28 @@ destructors_for_temps.cpp:
|
||||
|
||||
# 29| void temp_test3()
|
||||
# 29| Block 0
|
||||
# 29| v29_1(void) = EnterFunction :
|
||||
# 29| mu29_2(unknown) = AliasedDefinition :
|
||||
# 29| mu29_3(unknown) = InitializeNonLocal :
|
||||
# 30| r30_1(glval<ClassWithDestructor2 &>) = VariableAddress[rs] :
|
||||
# 30| r30_2(glval<ClassWithDestructor2>) = VariableAddress[#temp30:38] :
|
||||
# 30| r30_3(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 30| r30_4(ClassWithDestructor2) = Call[returnValue] : func:r30_3
|
||||
# 30| mu30_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 30| mu30_6(ClassWithDestructor2) = Store[#temp30:38] : &:r30_2, r30_4
|
||||
# 30| r30_7(glval<ClassWithDestructor2>) = Convert : r30_2
|
||||
# 30| r30_8(ClassWithDestructor2 &) = CopyValue : r30_7
|
||||
# 30| mu30_9(ClassWithDestructor2 &) = Store[rs] : &:r30_1, r30_8
|
||||
# 31| v31_1(void) = NoOp :
|
||||
# 29| v29_4(void) = ReturnVoid :
|
||||
# 29| v29_5(void) = AliasedUse : ~m?
|
||||
# 29| v29_6(void) = ExitFunction :
|
||||
# 29| v29_1(void) = EnterFunction :
|
||||
# 29| mu29_2(unknown) = AliasedDefinition :
|
||||
# 29| mu29_3(unknown) = InitializeNonLocal :
|
||||
# 30| r30_1(glval<ClassWithDestructor2 &>) = VariableAddress[rs] :
|
||||
# 30| r30_2(glval<ClassWithDestructor2>) = VariableAddress[#temp30:38] :
|
||||
# 30| r30_3(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 30| r30_4(ClassWithDestructor2) = Call[returnValue] : func:r30_3
|
||||
# 30| mu30_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 30| mu30_6(ClassWithDestructor2) = Store[#temp30:38] : &:r30_2, r30_4
|
||||
# 30| r30_7(glval<ClassWithDestructor2>) = Convert : r30_2
|
||||
# 30| r30_8(ClassWithDestructor2 &) = CopyValue : r30_7
|
||||
# 30| mu30_9(ClassWithDestructor2 &) = Store[rs] : &:r30_1, r30_8
|
||||
# 31| v31_1(void) = NoOp :
|
||||
# 31| r31_2(glval<ClassWithDestructor2>) = CopyValue : r30_2
|
||||
# 31| r31_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
|
||||
# 31| v31_4(void) = Call[~ClassWithDestructor2] : func:r31_3, this:r31_2
|
||||
# 31| mu31_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 31| v31_6(void) = ^IndirectReadSideEffect[-1] : &:r31_2, ~m?
|
||||
# 31| mu31_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r31_2
|
||||
# 29| v29_4(void) = ReturnVoid :
|
||||
# 29| v29_5(void) = AliasedUse : ~m?
|
||||
# 29| v29_6(void) = ExitFunction :
|
||||
|
||||
# 33| void temp_test4()
|
||||
# 33| Block 0
|
||||
@@ -887,12 +893,18 @@ destructors_for_temps.cpp:
|
||||
# 35| r35_8(ClassWithDestructor2 &) = CopyValue : r35_7
|
||||
# 35| mu35_9(ClassWithDestructor2 &) = Store[rs2] : &:r35_1, r35_8
|
||||
# 36| v36_1(void) = NoOp :
|
||||
# 36| r36_2(glval<ClassWithDestructor2>) = VariableAddress[c] :
|
||||
# 36| r36_2(glval<ClassWithDestructor2>) = CopyValue : r35_2
|
||||
# 36| r36_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
|
||||
# 36| v36_4(void) = Call[~ClassWithDestructor2] : func:r36_3, this:r36_2
|
||||
# 36| mu36_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 36| v36_6(void) = ^IndirectReadSideEffect[-1] : &:r36_2, ~m?
|
||||
# 36| mu36_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r36_2
|
||||
# 36| r36_8(glval<ClassWithDestructor2>) = VariableAddress[c] :
|
||||
# 36| r36_9(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
|
||||
# 36| v36_10(void) = Call[~ClassWithDestructor2] : func:r36_9, this:r36_8
|
||||
# 36| mu36_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 36| v36_12(void) = ^IndirectReadSideEffect[-1] : &:r36_8, ~m?
|
||||
# 36| mu36_13(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r36_8
|
||||
# 33| v33_4(void) = ReturnVoid :
|
||||
# 33| v33_5(void) = AliasedUse : ~m?
|
||||
# 33| v33_6(void) = ExitFunction :
|
||||
@@ -8321,12 +8333,18 @@ ir.cpp:
|
||||
# 1425| mu1425_4(unknown) = ^CallSideEffect : ~m?
|
||||
# 1425| mu1425_5(String) = Store[#temp1425:5] : &:r1425_1, r1425_3
|
||||
# 1426| v1426_1(void) = NoOp :
|
||||
# 1426| r1426_2(glval<String>) = VariableAddress[s] :
|
||||
# 1426| r1426_2(glval<String>) = CopyValue : r1416_2
|
||||
# 1426| r1426_3(glval<unknown>) = FunctionAddress[~String] :
|
||||
# 1426| v1426_4(void) = Call[~String] : func:r1426_3, this:r1426_2
|
||||
# 1426| mu1426_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 1426| v1426_6(void) = ^IndirectReadSideEffect[-1] : &:r1426_2, ~m?
|
||||
# 1426| mu1426_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r1426_2
|
||||
# 1426| r1426_8(glval<String>) = VariableAddress[s] :
|
||||
# 1426| r1426_9(glval<unknown>) = FunctionAddress[~String] :
|
||||
# 1426| v1426_10(void) = Call[~String] : func:r1426_9, this:r1426_8
|
||||
# 1426| mu1426_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 1426| v1426_12(void) = ^IndirectReadSideEffect[-1] : &:r1426_8, ~m?
|
||||
# 1426| mu1426_13(String) = ^IndirectMayWriteSideEffect[-1] : &:r1426_8
|
||||
# 1414| v1414_4(void) = ReturnVoid :
|
||||
# 1414| v1414_5(void) = AliasedUse : ~m?
|
||||
# 1414| v1414_6(void) = ExitFunction :
|
||||
@@ -8397,12 +8415,18 @@ ir.cpp:
|
||||
# 1438| mu1438_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 1438| v1438_6(void) = ^IndirectReadSideEffect[-1] : &:r1438_2, ~m?
|
||||
# 1438| mu1438_7(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1438_2
|
||||
# 1438| r1438_8(glval<destructor_only>) = VariableAddress[d] :
|
||||
# 1438| r1438_8(glval<destructor_only>) = CopyValue : r1430_2
|
||||
# 1438| r1438_9(glval<unknown>) = FunctionAddress[~destructor_only] :
|
||||
# 1438| v1438_10(void) = Call[~destructor_only] : func:r1438_9, this:r1438_8
|
||||
# 1438| mu1438_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 1438| v1438_12(void) = ^IndirectReadSideEffect[-1] : &:r1438_8, ~m?
|
||||
# 1438| mu1438_13(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1438_8
|
||||
# 1438| r1438_14(glval<destructor_only>) = VariableAddress[d] :
|
||||
# 1438| r1438_15(glval<unknown>) = FunctionAddress[~destructor_only] :
|
||||
# 1438| v1438_16(void) = Call[~destructor_only] : func:r1438_15, this:r1438_14
|
||||
# 1438| mu1438_17(unknown) = ^CallSideEffect : ~m?
|
||||
# 1438| v1438_18(void) = ^IndirectReadSideEffect[-1] : &:r1438_14, ~m?
|
||||
# 1438| mu1438_19(destructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1438_14
|
||||
# 1428| v1428_4(void) = ReturnVoid :
|
||||
# 1428| v1428_5(void) = AliasedUse : ~m?
|
||||
# 1428| v1428_6(void) = ExitFunction :
|
||||
|
||||
@@ -51,7 +51,9 @@ namespace Semmle.Autobuild.CSharp
|
||||
break;
|
||||
case CSharpBuildStrategy.Buildless:
|
||||
// No need to check that the extractor has been executed in buildless mode
|
||||
attempt = new StandaloneBuildRule().Analyse(this, false);
|
||||
attempt = BuildScript.Bind(
|
||||
AddBuildlessStartedDiagnostic() & new StandaloneBuildRule().Analyse(this, false),
|
||||
AddBuildlessEndedDiagnostic);
|
||||
break;
|
||||
case CSharpBuildStrategy.MSBuild:
|
||||
attempt = new MsBuildRule().Analyse(this, false) & CheckExtractorRun(true);
|
||||
@@ -86,6 +88,52 @@ namespace Semmle.Autobuild.CSharp
|
||||
return 1;
|
||||
});
|
||||
|
||||
private BuildScript AddBuildlessStartedDiagnostic()
|
||||
{
|
||||
return BuildScript.Create(actions =>
|
||||
{
|
||||
AddDiagnostic(new DiagnosticMessage(
|
||||
Options.Language,
|
||||
"buildless/mode-active",
|
||||
"C# with build-mode set to 'none'",
|
||||
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
|
||||
markdownMessage: "C# with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
severity: DiagnosticMessage.TspSeverity.Note
|
||||
));
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
private BuildScript AddBuildlessEndedDiagnostic(int buildResult)
|
||||
{
|
||||
return BuildScript.Create(actions =>
|
||||
{
|
||||
if (buildResult == 0)
|
||||
{
|
||||
AddDiagnostic(new DiagnosticMessage(
|
||||
Options.Language,
|
||||
"buildless/complete",
|
||||
"C# analysis with build-mode 'none' completed",
|
||||
visibility: new DiagnosticMessage.TspVisibility(statusPage: false, cliSummaryTable: true, telemetry: true),
|
||||
markdownMessage: "C# analysis with build-mode 'none' completed.",
|
||||
severity: DiagnosticMessage.TspSeverity.Unknown
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddDiagnostic(new DiagnosticMessage(
|
||||
Options.Language,
|
||||
"buildless/failed",
|
||||
"C# analysis with build-mode 'none' failed",
|
||||
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
|
||||
markdownMessage: "C# analysis with build-mode 'none' failed.",
|
||||
severity: DiagnosticMessage.TspSeverity.Error
|
||||
));
|
||||
}
|
||||
return buildResult;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void AutobuildFailureDiagnostic()
|
||||
{
|
||||
// if `ScriptPath` is not null here, the `BuildCommandAuto` rule was
|
||||
|
||||
@@ -728,6 +728,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
/// </summary>
|
||||
public IEnumerable<string> GeneratedSourceFiles => generatedSources;
|
||||
|
||||
/// <summary>
|
||||
/// All of the non-generated source files in the source directory.
|
||||
/// </summary>
|
||||
public IEnumerable<string> NonGeneratedSourcesFiles => nonGeneratedSources;
|
||||
|
||||
/// <summary>
|
||||
/// All of the source files in the source directory.
|
||||
/// </summary>
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Semmle.Extraction.CSharp.Standalone
|
||||
logger.Log(Severity.Info, "Extracting C# in buildless mode");
|
||||
using var dependencyManager = new DependencyManager(options.SrcDir, logger);
|
||||
|
||||
if (!dependencyManager.AllSourceFiles.Any())
|
||||
if (!dependencyManager.NonGeneratedSourcesFiles.Any())
|
||||
{
|
||||
logger.Log(Severity.Error, "No source files found");
|
||||
return ExitCode.Errors;
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace Semmle.Util
|
||||
[JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy))]
|
||||
public enum TspSeverity
|
||||
{
|
||||
Unknown,
|
||||
Note,
|
||||
Warning,
|
||||
Error
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.7.12
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.12
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.11
|
||||
lastReleaseVersion: 1.7.12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.7.12-dev
|
||||
version: 1.7.13-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.7.12
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.12
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.11
|
||||
lastReleaseVersion: 1.7.12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.7.12-dev
|
||||
version: 1.7.13-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"markdownMessage": "C# analysis with build-mode 'none' completed.",
|
||||
"severity": "unknown",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
"id": "csharp/autobuilder/buildless/complete",
|
||||
"name": "C# analysis with build-mode 'none' completed"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
"id": "csharp/autobuilder/buildless/mode-active",
|
||||
"name": "C# with build-mode set to 'none'"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": true,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import os
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
|
||||
os.environ['CODEQL_EXTRACTOR_CSHARP_OPTION_COMPILER_DIAGNOSTIC_LIMIT'] = '2'
|
||||
os.environ['CODEQL_EXTRACTOR_CSHARP_OPTION_MESSAGE_LIMIT'] = '5'
|
||||
run_codeql_database_create([], lang="csharp", extra_args=["--build-mode=none"])
|
||||
|
||||
check_diagnostics()
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"markdownMessage": "C# analysis with build-mode 'none' failed.",
|
||||
"severity": "error",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
"id": "csharp/autobuilder/buildless/failed",
|
||||
"name": "C# analysis with build-mode 'none' failed"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": true,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
"id": "csharp/autobuilder/buildless/mode-active",
|
||||
"name": "C# with build-mode set to 'none'"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": true,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="DeleteBinObjFolders" BeforeTargets="Clean">
|
||||
<RemoveDir Directories=".\bin" />
|
||||
<RemoveDir Directories=".\obj" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
|
||||
run_codeql_database_create([], db=None, lang="csharp", extra_args=["--build-mode=none"], runFunction=runUnsuccessfully)
|
||||
|
||||
check_diagnostics()
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.8.12
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.8.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added new source models for the `Dapper` package. These models can be enabled by enabling the `database` threat model.
|
||||
3
csharp/ql/lib/change-notes/released/0.8.12.md
Normal file
3
csharp/ql/lib/change-notes/released/0.8.12.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.8.12
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.8.11
|
||||
lastReleaseVersion: 0.8.12
|
||||
|
||||
@@ -58,3 +58,54 @@ extensions:
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync", "(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>)", "", "Argument[1]", "sql-injection", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync", "(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>)", "", "Argument[2]", "sql-injection", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync<T>", "(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>)", "", "Argument[1]", "sql-injection", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["Dapper", "SqlMapper", False, "ExecuteReader", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "ExecuteReaderAsync", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "ExecuteScalar", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "ExecuteScalar<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "ExecuteScalarAsync", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "ExecuteScalarAsync<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TFourth,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query<TFirst,TSecond,TThird,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "Query<TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TFourth,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync<TFirst,TSecond,TThird,TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryAsync<TReturn>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryFirst", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryFirst<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryFirstAsync", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryFirstAsync<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryFirstOrDefault", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryFirstOrDefault<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryFirstOrDefaultAsync", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryFirstOrDefaultAsync<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryMultiple", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QueryMultipleAsync", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingle", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingle<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleAsync", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleAsync<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefault", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefault<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync", "", "", "ReturnValue", "database", "manual"]
|
||||
- ["Dapper", "SqlMapper", False, "QuerySingleOrDefaultAsync<T>", "", "", "ReturnValue", "database", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["Dapper", "SqlMapper", False, "AsList<T>", "(System.Collections.Generic.IEnumerable<T>)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 0.8.12-dev
|
||||
version: 0.8.13-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.8.12
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.8.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
csharp/ql/src/change-notes/released/0.8.12.md
Normal file
3
csharp/ql/src/change-notes/released/0.8.12.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.8.12
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.8.11
|
||||
lastReleaseVersion: 0.8.12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 0.8.12-dev
|
||||
version: 0.8.13-dev
|
||||
groups:
|
||||
- csharp
|
||||
- queries
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
extensions:
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/threat-models
|
||||
extensible: threatModelConfiguration
|
||||
data:
|
||||
- ["database", true, 0]
|
||||
@@ -0,0 +1,12 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.security.dataflow.flowsources.FlowSources
|
||||
import TestUtilities.InlineFlowTest
|
||||
import TaintFlowTest<DatabaseConfig>
|
||||
|
||||
module DatabaseConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodCall mc | mc.getTarget().hasName("Sink") | sink.asExpr() = mc.getArgument(0))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Entity;
|
||||
using System.Data.SqlClient;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
class UseDapper
|
||||
{
|
||||
public static void Bad01(string connectionString, string query)
|
||||
{
|
||||
using (var connection = new SqlConnection(connectionString))
|
||||
{
|
||||
var result = connection.Query<object>(query);
|
||||
Sink(result); // $ hasTaintFlow=line:16
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task Bad02(string connectionString, string query)
|
||||
{
|
||||
using (var connection = new SqlConnection(connectionString))
|
||||
{
|
||||
var result = await connection.QueryAsync<object>(query);
|
||||
Sink(result); // $ hasTaintFlow=line:25
|
||||
}
|
||||
}
|
||||
|
||||
public static void Bad03(string connectionString, string query)
|
||||
{
|
||||
using (var connection = new SqlConnection(connectionString))
|
||||
{
|
||||
var result = connection.QueryFirst(query);
|
||||
Sink(result); // $ hasTaintFlow=line:34
|
||||
}
|
||||
}
|
||||
|
||||
public static void Bad04(string connectionString, string query)
|
||||
{
|
||||
using (var connection = new SqlConnection(connectionString))
|
||||
{
|
||||
var results = connection.Query<object>(query).AsList();
|
||||
Sink(results[0]); // $ hasTaintFlow=line:43
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sink(object o) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
semmle-extractor-options: /nostdlib /noconfig
|
||||
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../../resources/stubs/Dapper/2.1.24/Dapper.csproj
|
||||
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../../resources/stubs/System.Data.SqlClient/4.8.5/System.Data.SqlClient.csproj
|
||||
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../../resources/stubs/System.Data.SQLite/1.0.118/System.Data.SQLite.csproj
|
||||
semmle-extractor-options: ${testdir}/../../../../../../resources/stubs/System.Windows.cs
|
||||
@@ -1,4 +1,95 @@
|
||||
source
|
||||
| Dapper;SqlMapper;false;ExecuteReader;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteReader;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Data.CommandBehavior);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteReader;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.Common.DbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.Common.DbConnection,Dapper.CommandDefinition,System.Data.CommandBehavior);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.Common.DbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Data.CommandBehavior);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteScalar;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteScalar;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteScalar<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteScalar<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteScalarAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteScalarAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteScalarAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;ExecuteScalarAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;Query<TReturn>;(System.Data.IDbConnection,System.String,System.Type[],System.Func<System.Object[],TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TReturn>,System.String);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.String);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.String);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>,System.String);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.String);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TReturn>;(System.Data.IDbConnection,Dapper.CommandDefinition,System.Func<TFirst,TSecond,TThird,TReturn>,System.String);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TFirst,TSecond,TThird,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryAsync<TReturn>;(System.Data.IDbConnection,System.String,System.Type[],System.Func<System.Object[],TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirst;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirst;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirst<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirst<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefault;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefault;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefault<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefault<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryFirstOrDefaultAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryMultiple;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryMultiple;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryMultipleAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QueryMultipleAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingle;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingle;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingle<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingle<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefault;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefault;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefault<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefault<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,System.Type,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync<T>;(System.Data.IDbConnection,Dapper.CommandDefinition);;ReturnValue;database;manual |
|
||||
| Dapper;SqlMapper;false;QuerySingleOrDefaultAsync<T>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;ReturnValue;database;manual |
|
||||
| Microsoft.Extensions.Configuration;EnvironmentVariablesExtensions;false;AddEnvironmentVariables;(Microsoft.Extensions.Configuration.IConfigurationBuilder);;Argument[0];environment;manual |
|
||||
| Microsoft.Extensions.Configuration;EnvironmentVariablesExtensions;false;AddEnvironmentVariables;(Microsoft.Extensions.Configuration.IConfigurationBuilder);;ReturnValue;environment;manual |
|
||||
| Microsoft.Extensions.Configuration;EnvironmentVariablesExtensions;false;AddEnvironmentVariables;(Microsoft.Extensions.Configuration.IConfigurationBuilder,System.Action<Microsoft.Extensions.Configuration.EnvironmentVariables.EnvironmentVariablesConfigurationSource>);;Argument[0];environment;manual |
|
||||
@@ -645,6 +736,7 @@ summary
|
||||
| Dapper;SqlMapper+GridReader;false;Read<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.String,System.Boolean);;Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper+GridReader;false;Read<TFirst,TSecond,TThird,TReturn>;(System.Func<TFirst,TSecond,TThird,TReturn>,System.String,System.Boolean);;Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper+GridReader;false;Read<TReturn>;(System.Type[],System.Func<System.Object[],TReturn>,System.String,System.Boolean);;Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper;false;AsList<T>;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;ReturnValue.Element;value;manual |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
| Dapper;SqlMapper+GridReader;false;Read<TFirst,TSecond,TThird,TFourth,TReturn>;(System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.String,System.Boolean);;Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper+GridReader;false;Read<TFirst,TSecond,TThird,TReturn>;(System.Func<TFirst,TSecond,TThird,TReturn>,System.String,System.Boolean);;Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper+GridReader;false;Read<TReturn>;(System.Type[],System.Func<System.Object[],TReturn>,System.String,System.Boolean);;Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper;false;AsList<T>;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;ReturnValue.Element;value;manual |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
|
||||
| Dapper;SqlMapper;false;Query<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];Argument[2].Parameter[delegate-self];value;hq-generated |
|
||||
|
||||
@@ -13,6 +13,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
|
||||
abstract-syntax-tree-classes-for-working-with-ruby-programs
|
||||
analyzing-data-flow-in-ruby
|
||||
using-api-graphs-in-ruby
|
||||
customizing-library-models-for-ruby
|
||||
|
||||
- :doc:`Basic query for Ruby code <basic-query-for-ruby-code>`: Learn to write and run a simple CodeQL query.
|
||||
|
||||
@@ -23,3 +24,5 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
|
||||
- :doc:`Using API graphs in Ruby <using-api-graphs-in-ruby>`: API graphs are a uniform interface for referring to functions, classes, and methods defined in external libraries.
|
||||
|
||||
- :doc:`Abstract syntax tree classes for working with Ruby programs <abstract-syntax-tree-classes-for-working-with-ruby-programs>`: CodeQL has a large selection of classes for representing the abstract syntax tree of Ruby programs.
|
||||
|
||||
- :doc:`Customizing library models for Ruby <customizing-library-models-for-ruby>`: You can model frameworks and libraries that your codebase depends on using data extensions and publish them as CodeQL model packs.
|
||||
|
||||
@@ -0,0 +1,402 @@
|
||||
.. _customizing-library-models-for-ruby:
|
||||
|
||||
|
||||
Customizing Library Models for Ruby
|
||||
===================================
|
||||
|
||||
.. include:: ../reusables/beta-note-customizing-library-models.rst
|
||||
|
||||
Ruby analysis can be customized by adding library models in data extension files.
|
||||
|
||||
A data extension for Ruby is a YAML file of the form:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: <name of extensible predicate>
|
||||
data:
|
||||
- <tuple1>
|
||||
- <tuple2>
|
||||
- ...
|
||||
|
||||
The CodeQL library for Ruby exposes the following extensible predicates:
|
||||
|
||||
- **sourceModel**\(type, path, kind)
|
||||
- **sinkModel**\(type, path, kind)
|
||||
- **typeModel**\(type1, type2, path)
|
||||
- **summaryModel**\(type, path, input, output, kind)
|
||||
|
||||
We'll explain how to use these using a few examples, and provide some reference material at the end of this article.
|
||||
|
||||
Example: Taint sink in the 'tty-command' gem
|
||||
--------------------------------------------
|
||||
|
||||
In this example, we'll show how to add the following argument, passed to **tty-command**, as a command-line injection sink:
|
||||
|
||||
.. code-block:: ruby
|
||||
|
||||
tty = TTY::Command.new
|
||||
tty.run(cmd) # <-- add 'cmd' as a taint sink
|
||||
|
||||
For this example, you can use the following data extension:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["TTY::Command", "Method[run].Argument[0]", "command-injection"]
|
||||
|
||||
|
||||
- Since we're adding a new sink, we add a tuple to the **sinkModel** extensible predicate.
|
||||
- The first column, **"TTY::Command"**, identifies a set of values from which to begin the search for the sink.
|
||||
The string **"TTY::Command""** means we start at the places where the codebase constructs instances of the class **TTY::Command**.
|
||||
- The second column is an access path that is evaluated from left to right, starting at the values that were identified by the first column.
|
||||
|
||||
- **Method[run]** selects calls to the **run** method of the **TTY::Command** class.
|
||||
- **Argument[0]** selects the first argument to calls to that member.
|
||||
|
||||
- **command-injection** indicates that this is considered a sink for the command injection query.
|
||||
|
||||
Example: Taint sources from 'sinatra' block parameters
|
||||
------------------------------------------------------
|
||||
|
||||
In this example, we'll show how the 'x' parameter below could be marked as a remote flow source:
|
||||
|
||||
.. code-block:: ruby
|
||||
|
||||
class MyApp < Sinatra::Base
|
||||
get '/' do |x| # <-- add 'x' as a taint source
|
||||
# ...
|
||||
end
|
||||
end
|
||||
|
||||
For this example you could use the following data extension:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- [
|
||||
"Sinatra::Base!",
|
||||
"Method[get].Argument[block].Parameter[0]",
|
||||
"remote",
|
||||
]
|
||||
|
||||
- Since we're adding a new taint source, we add a tuple to the **sourceModel** extensible predicate.
|
||||
- The first column, **"Sinatra::Base!"**, begins the search at references to the **Sinatra::Base** class.
|
||||
The **!** suffix indicates that we want to search for references to the class itself, rather than instances of the class.
|
||||
- **Method[get]** selects calls to the **get** method of the **Sinatra::Base** class.
|
||||
- **Argument[block]** selects the block argument to the **get** method call.
|
||||
- **Parameter[0]** selects the first parameter of the block argument (the parameter named **x**).
|
||||
- Finally, the kind **remote** indicates that this is considered a source of remote flow.
|
||||
|
||||
Example: Using types to add MySQL injection sinks
|
||||
-------------------------------------------------
|
||||
|
||||
In this example, we'll show how to add the following SQL injection sink:
|
||||
|
||||
.. code-block:: ruby
|
||||
|
||||
def submit(q)
|
||||
client = Mysql2::Client.new
|
||||
client.query(q) # <-- add 'q' as a SQL injection sink
|
||||
end
|
||||
|
||||
We can recognize this using the following extension:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["Mysql2::Client", "Method[query].Argument[0]", "sql-injection"]
|
||||
|
||||
- The first column, **"Mysql2::Client"**, begins the search at any instance of the **Mysql2::Client** class.
|
||||
- **Method[query]** selects any call to the **query** method on that instance.
|
||||
- **Argument[0]** selects the first argument to the method call.
|
||||
- **sql-injection** indicates that this is considered a sink for the SQL injection query.
|
||||
|
||||
Continued example: Using type models
|
||||
------------------------------------
|
||||
|
||||
Consider this variation on the previous example, the mysql2 EventMachine API is used.
|
||||
The client is obtained via a call to **Mysql2::EM::Client.new**.
|
||||
|
||||
.. code-block:: ruby
|
||||
|
||||
def submit(client, q)
|
||||
client = Mysql2::EM::Client.new
|
||||
client.query(q)
|
||||
end
|
||||
|
||||
So far we have only one model for **Mysql2::Client**, but in the real world we
|
||||
may have many models for the various methods available. Because **Mysql2::EM::Client** is a subclass of **Mysql2::Client**, it inherits all of the same methods.
|
||||
Instead of updating all our models to include both classes, we can add a type
|
||||
model to indicate that **Mysql2::EM::Client** is a subclass of **Mysql2::Client**:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
- ["Mysql2::Client", "Mysql2::EM::Client", ""]
|
||||
|
||||
Example: Adding flow through 'URI.decode_uri_component'
|
||||
-------------------------------------------------------
|
||||
|
||||
In this example, we'll show how to add flow through calls to 'URI.decode_uri_component':
|
||||
|
||||
.. code-block:: ruby
|
||||
|
||||
y = URI.decode_uri_component(x); # add taint flow from 'x' to 'y'
|
||||
|
||||
We can model this using the following data extension:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- [
|
||||
"URI!",
|
||||
"Method[decode_uri_component]",
|
||||
"Argument[0]",
|
||||
"ReturnValue",
|
||||
"taint",
|
||||
]
|
||||
|
||||
|
||||
- Since we're adding flow through a method call, we add a tuple to the **summaryModel** extensible predicate.
|
||||
- The first column, **"URI!"**, begins the search for relevant calls at references to the **URI** class.
|
||||
- The **!** suffix indicates that we are looking for the class itself, rather than instances of the class.
|
||||
- The second column, **Method[decode_uri_component]**, is a path leading to the method calls we wish to model.
|
||||
In this case, we select references to the **decode_uri_component** method from the **URI** class.
|
||||
- The third column, **Argument[0]**, indicates the input of the flow. In this case, the first argument to the method call.
|
||||
- The fourth column, **ReturnValue**, indicates the output of the flow. In this case, the return value of the method call.
|
||||
- The last column, **taint**, indicates the kind of flow to add. The value **taint** means the output is not necessarily equal
|
||||
to the input, but was derived from the input in a taint-preserving way.
|
||||
|
||||
Example: Adding flow through 'File#each'
|
||||
----------------------------------------
|
||||
|
||||
In this example, we'll show how to add flow through calls to **File#each** from the standard library, which iterates over the lines of a file:
|
||||
|
||||
.. code-block:: ruby
|
||||
|
||||
f = File.new("example.txt")
|
||||
f.each { |line| ... } # add taint flow from `f` to `line`
|
||||
|
||||
We can model this using the following data extension:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- [
|
||||
"File",
|
||||
"Method[each]",
|
||||
"Argument[self]",
|
||||
"Argument[block].Parameter[0]",
|
||||
"taint",
|
||||
]
|
||||
|
||||
|
||||
- Since we're adding flow through a method call, we add a tuple to the **summaryModel** extensible predicate.
|
||||
- The first column, **"File"**, begins the search for relevant calls at places where the **File** class is used.
|
||||
- The second column, **Method[each]**, selects references to the **each** method on the **File** class.
|
||||
- The third column specifies the input of the flow. **Argument[self]** selects the **self** argument of **each**, which is the **File** instance being iterated over.
|
||||
|
||||
- The fourth column specifies the output of the flow:
|
||||
|
||||
- **Argument[block]** selects the block argument of **each** (the block which is executed for each line in the file).
|
||||
- **Parameter[0]** selects the first parameter of the block (the parameter named **line**).
|
||||
|
||||
- The last column, **taint**, indicates the kind of flow to add.
|
||||
|
||||
Reference material
|
||||
------------------
|
||||
|
||||
The following sections provide reference material for extensible predicates, access paths, types, and kinds.
|
||||
|
||||
Extensible predicates
|
||||
---------------------
|
||||
|
||||
sourceModel(type, path, kind)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Adds a new taint source. Most taint-tracking queries will use the new source.
|
||||
|
||||
- **type**: Name of a type from which to evaluate **path**.
|
||||
- **path**: Access path leading to the source.
|
||||
- **kind**: Kind of source to add. Currently only **remote** is used.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["User", "Method[name]", "remote"]
|
||||
|
||||
sinkModel(type, path, kind)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Adds a new taint sink. Sinks are query-specific and will typically affect one or two queries.
|
||||
|
||||
- **type**: Name of a type from which to evaluate **path**.
|
||||
- **path**: Access path leading to the sink.
|
||||
- **kind**: Kind of sink to add. See the section on sink kinds for a list of supported kinds.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["ExecuteShell", "Method[run].Argument[0]", "command-injection"]
|
||||
|
||||
summaryModel(type, path, input, output, kind)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Adds flow through a method call.
|
||||
|
||||
- **type**: Name of a type from which to evaluate **path**.
|
||||
- **path**: Access path leading to a method call.
|
||||
- **input**: Path relative to the method call that leads to input of the flow.
|
||||
- **output**: Path relative to the method call leading to the output of the flow.
|
||||
- **kind**: Kind of summary to add. Can be **taint** for taint-propagating flow, or **value** for value-preserving flow.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- [
|
||||
"URI",
|
||||
"Method[decode_uri_component]",
|
||||
"Argument[0]",
|
||||
"ReturnValue",
|
||||
"taint",
|
||||
]
|
||||
|
||||
typeModel(type1, type2, path)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Adds a new definition of a type.
|
||||
|
||||
- **type1**: Name of the type to define.
|
||||
- **type2**: Name of the type from which to evaluate **path**.
|
||||
- **path**: Access path leading from **type2** to **type1**.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
- [
|
||||
"Mysql2::Client",
|
||||
"MyDbWrapper",
|
||||
"Method[getConnection].ReturnValue",
|
||||
]
|
||||
|
||||
Types
|
||||
-----
|
||||
|
||||
A type is a string that identifies a set of values.
|
||||
In each of the extensible predicates mentioned in previous section, the first column is always the name of a type.
|
||||
A type can be defined by adding **typeModel** tuples for that type.
|
||||
|
||||
Access paths
|
||||
------------
|
||||
|
||||
The **path**, **input**, and **output** columns consist of a **.**-separated list of components, which is evaluated from left to right,
|
||||
with each step selecting a new set of values derived from the previous set of values.
|
||||
|
||||
The following components are supported:
|
||||
|
||||
- **Argument[**\ `number`\ **]** selects the argument at the given index.
|
||||
- **Argument[**\ `string`:\ **]** selects the keyword argument with the given name.
|
||||
- **Argument[self]** selects the receiver of a method call.
|
||||
- **Argument[block]** selects the block argument.
|
||||
- **Argument[any]** selects any argument, except self or block arguments.
|
||||
- **Argument[any-named]** selects any keyword argument.
|
||||
- **Argument[hash-splat]** selects a special argument representing all keyword arguments passed in the method call.
|
||||
- **Parameter[**\ `number`\ **]** selects the argument at the given index.
|
||||
- **Parameter[**\ `string`:\ **]** selects the keyword argument with the given name.
|
||||
- **Parameter[self]** selects the **self** parameter of a method.
|
||||
- **Parameter[block]** selects the block parameter.
|
||||
- **Parameter[any]** selects any parameter, except self or block parameters.
|
||||
- **Parameter[any-named]** selects any keyword parameter.
|
||||
- **Parameter[hash-splat]** selects the hash splat parameter, often written as **\*\*kwargs**.
|
||||
- **ReturnValue** selects the return value of a call.
|
||||
- **Method[**\ `name`\ **]** selects a call to the method with the given name.
|
||||
- **Element[any]** selects any element of an array or hash.
|
||||
- **Element[**\ `number`\ **]** selects an array element at the given index.
|
||||
- **Element[**\ `string`\ **]** selects a hash element at the given key.
|
||||
- **Field[@**\ `string`\ **]** selects an instance variable with the given name.
|
||||
- **Fuzzy** selects all values that are derived from the current value through a combination of the other operations described in this list.
|
||||
For example, this can be used to find all values that appear to originate from a particular class. This can be useful for finding method calls
|
||||
from a known class, but where the receiver type is not known or is difficult to model.
|
||||
|
||||
Additional notes about the syntax of operands:
|
||||
|
||||
- Multiple operands may be given to a single component, as a shorthand for the union of the operands. For example, **Method[foo,bar]** matches the union of **Method[foo]** and **Method[bar]**.
|
||||
- Numeric operands to **Argument**, **Parameter**, and **Element** may be given as a lower bound. For example, **Argument[1..]** matches all arguments except 0.
|
||||
|
||||
Kinds
|
||||
-----
|
||||
|
||||
Source kinds
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- **remote**: A generic source of remote flow. Most taint-tracking queries will use such a source. Currently this is the only supported source kind.
|
||||
|
||||
Sink kinds
|
||||
~~~~~~~~~~
|
||||
|
||||
Unlike sources, sinks tend to be highly query-specific, rarely affecting more than one or two queries.
|
||||
Not every query supports customizable sinks. If the following sinks are not suitable for your use case, you should add a new query.
|
||||
|
||||
- **code-injection**: A sink that can be used to inject code, such as in calls to **eval**.
|
||||
- **command-injection**: A sink that can be used to inject shell commands, such as in calls to **Process.spawn**.
|
||||
- **path-injection**: A sink that can be used for path injection in a file system access, such as in calls to **File.open**.
|
||||
- **sql-injection**: A sink that can be used for SQL injection, such as in an ActiveRecord **where** call.
|
||||
- **url-redirection**: A sink that can be used to redirect the user to a malicious URL.
|
||||
- **log-injection**: A sink that can be used for log injection, such as in a **Rails.logger** call.
|
||||
|
||||
Summary kinds
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
- **taint**: A summary that propagates taint. This means the output is not necessarily equal to the input, but it was derived from the input in an unrestrictive way. An attacker who controls the input will have significant control over the output as well.
|
||||
- **value**: A summary that preserves the value of the input or creates a copy of the input such that all of its object properties are preserved.
|
||||
@@ -0,0 +1,25 @@
|
||||
.. _codeql-cli-2.16.5:
|
||||
|
||||
==========================
|
||||
CodeQL 2.16.5 (2024-03-21)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/code-scanning/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.16.5 runs a total of 409 security queries when configured with the Default suite (covering 160 CWE). The Extended suite enables an additional 132 queries (covering 34 more CWE).
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Beta support has been added for analyzing Java codebases without needing a working build. To enable this, pass the :code:`--build-mode none` option to :code:`codeql database create`.
|
||||
@@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here <https://docs.g
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
codeql-cli-2.16.5
|
||||
codeql-cli-2.16.4
|
||||
codeql-cli-2.16.3
|
||||
codeql-cli-2.16.2
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
.NET 5, .NET 6, .NET 7, .NET 8","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
|
||||
Go (aka Golang), "Go up to 1.22", "Go 1.11 or more recent", ``.go``
|
||||
Java,"Java 7 to 21 [5]_","javac (OpenJDK and Oracle JDK),
|
||||
Java,"Java 7 to 22 [5]_","javac (OpenJDK and Oracle JDK),
|
||||
|
||||
Eclipse compiler for Java (ECJ) [6]_",``.java``
|
||||
Kotlin [7]_,"Kotlin 1.5.0 to 1.9.2\ *x*","kotlinc",``.kt``
|
||||
@@ -33,7 +33,7 @@
|
||||
.. [2] Objective-C, Objective-C++, C++/CLI, and C++/CX are not supported.
|
||||
.. [3] Support for the clang-cl compiler is preliminary.
|
||||
.. [4] Support for the Arm Compiler (armcc) is preliminary.
|
||||
.. [5] Builds that execute on Java 7 to 21 can be analyzed. The analysis understands Java 21 standard language features.
|
||||
.. [5] Builds that execute on Java 7 to 22 can be analyzed. The analysis understands Java 22 standard language features.
|
||||
.. [6] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin.
|
||||
.. [7] Kotlin support is currently in beta.
|
||||
.. [8] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files.
|
||||
|
||||
@@ -417,7 +417,7 @@ func installDependencies(workspace project.GoWorkspace) {
|
||||
} else {
|
||||
if workspace.Modules == nil {
|
||||
project.InitGoModForLegacyProject(workspace.BaseDir)
|
||||
workspace.Modules = project.LoadGoModules([]string{filepath.Join(workspace.BaseDir, "go.mod")})
|
||||
workspace.Modules = project.LoadGoModules(true, []string{filepath.Join(workspace.BaseDir, "go.mod")})
|
||||
}
|
||||
|
||||
// get dependencies for all modules
|
||||
|
||||
@@ -497,7 +497,7 @@ func EmitNewerSystemGoRequired(requiredVersion string) {
|
||||
func EmitExtractionFailedForProjects(path []string) {
|
||||
emitDiagnostic(
|
||||
"go/autobuilder/extraction-failed-for-project",
|
||||
fmt.Sprintf("Unable to extract %d Go projects", len(path)),
|
||||
"Unable to extract some Go projects",
|
||||
fmt.Sprintf(
|
||||
"The following %d Go project%s could not be extracted successfully:\n\n`%s`\n",
|
||||
len(path),
|
||||
@@ -508,3 +508,18 @@ func EmitExtractionFailedForProjects(path []string) {
|
||||
noLocation,
|
||||
)
|
||||
}
|
||||
|
||||
func EmitInvalidToolchainVersion(goModPath string, version string) {
|
||||
emitDiagnostic(
|
||||
"go/autobuilder/invalid-go-toolchain-version",
|
||||
"Invalid Go toolchain version",
|
||||
strings.Join([]string{
|
||||
"As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://go.dev/doc/toolchain#version).",
|
||||
fmt.Sprintf("`%s` in `%s` does not match this syntax and there is no additional `toolchain` directive, which may cause some `go` commands to fail.", version, goModPath),
|
||||
},
|
||||
"\n\n"),
|
||||
severityWarning,
|
||||
fullVisibility,
|
||||
&locationStruct{File: goModPath},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -176,10 +176,13 @@ func findGoModFiles(root string) []string {
|
||||
return util.FindAllFilesWithName(root, "go.mod", "vendor")
|
||||
}
|
||||
|
||||
// A regular expression for the Go toolchain version syntax.
|
||||
var toolchainVersionRe *regexp.Regexp = regexp.MustCompile(`(?m)^([0-9]+\.[0-9]+\.[0-9]+)$`)
|
||||
|
||||
// Given a list of `go.mod` file paths, try to parse them all. The resulting array of `GoModule` objects
|
||||
// will be the same length as the input array and the objects will contain at least the `go.mod` path.
|
||||
// If parsing the corresponding file is successful, then the parsed contents will also be available.
|
||||
func LoadGoModules(goModFilePaths []string) []*GoModule {
|
||||
func LoadGoModules(emitDiagnostics bool, goModFilePaths []string) []*GoModule {
|
||||
results := make([]*GoModule, len(goModFilePaths))
|
||||
|
||||
for i, goModFilePath := range goModFilePaths {
|
||||
@@ -201,6 +204,25 @@ func LoadGoModules(goModFilePaths []string) []*GoModule {
|
||||
}
|
||||
|
||||
results[i].Module = modFile
|
||||
|
||||
// If this `go.mod` file specifies a Go language version, that version is `1.21` or greater, and
|
||||
// there is no `toolchain` directive, check that it is a valid Go toolchain version. Otherwise,
|
||||
// `go` commands which try to download the right version of the Go toolchain will fail. We detect
|
||||
// this situation and emit a diagnostic.
|
||||
if modFile.Toolchain == nil && modFile.Go != nil &&
|
||||
!toolchainVersionRe.Match([]byte(modFile.Go.Version)) && semver.Compare("v"+modFile.Go.Version, "v1.21.0") >= 0 {
|
||||
diagnostics.EmitInvalidToolchainVersion(goModFilePath, modFile.Go.Version)
|
||||
|
||||
modPath := filepath.Dir(goModFilePath)
|
||||
|
||||
log.Printf(
|
||||
"`%s` is not a valid toolchain version, trying to install it explicitly using the canonical representation in `%s`.",
|
||||
modFile.Go.Version,
|
||||
modPath,
|
||||
)
|
||||
|
||||
toolchain.InstallVersion(modPath, modFile.Go.Version)
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
@@ -209,7 +231,7 @@ func LoadGoModules(goModFilePaths []string) []*GoModule {
|
||||
// Given a path to a `go.work` file, this function attempts to parse the `go.work` file. If unsuccessful,
|
||||
// we attempt to discover `go.mod` files within subdirectories of the directory containing the `go.work`
|
||||
// file ourselves.
|
||||
func discoverWorkspace(workFilePath string) GoWorkspace {
|
||||
func discoverWorkspace(emitDiagnostics bool, workFilePath string) GoWorkspace {
|
||||
log.Printf("Loading %s...\n", workFilePath)
|
||||
baseDir := filepath.Dir(workFilePath)
|
||||
workFileSrc, err := os.ReadFile(workFilePath)
|
||||
@@ -223,7 +245,7 @@ func discoverWorkspace(workFilePath string) GoWorkspace {
|
||||
|
||||
return GoWorkspace{
|
||||
BaseDir: baseDir,
|
||||
Modules: LoadGoModules(goModFilePaths),
|
||||
Modules: LoadGoModules(emitDiagnostics, goModFilePaths),
|
||||
DepMode: GoGetWithModules,
|
||||
ModMode: getModMode(GoGetWithModules, baseDir),
|
||||
}
|
||||
@@ -240,7 +262,7 @@ func discoverWorkspace(workFilePath string) GoWorkspace {
|
||||
|
||||
return GoWorkspace{
|
||||
BaseDir: baseDir,
|
||||
Modules: LoadGoModules(goModFilePaths),
|
||||
Modules: LoadGoModules(emitDiagnostics, goModFilePaths),
|
||||
DepMode: GoGetWithModules,
|
||||
ModMode: getModMode(GoGetWithModules, baseDir),
|
||||
}
|
||||
@@ -263,7 +285,7 @@ func discoverWorkspace(workFilePath string) GoWorkspace {
|
||||
return GoWorkspace{
|
||||
BaseDir: baseDir,
|
||||
WorkspaceFile: workFile,
|
||||
Modules: LoadGoModules(goModFilePaths),
|
||||
Modules: LoadGoModules(emitDiagnostics, goModFilePaths),
|
||||
DepMode: GoGetWithModules,
|
||||
ModMode: ModReadonly, // Workspaces only support "readonly"
|
||||
}
|
||||
@@ -286,7 +308,7 @@ func discoverWorkspaces(emitDiagnostics bool) []GoWorkspace {
|
||||
for i, goModFile := range goModFiles {
|
||||
results[i] = GoWorkspace{
|
||||
BaseDir: filepath.Dir(goModFile),
|
||||
Modules: LoadGoModules([]string{goModFile}),
|
||||
Modules: LoadGoModules(emitDiagnostics, []string{goModFile}),
|
||||
DepMode: GoGetWithModules,
|
||||
ModMode: getModMode(GoGetWithModules, filepath.Dir(goModFile)),
|
||||
}
|
||||
@@ -303,7 +325,7 @@ func discoverWorkspaces(emitDiagnostics bool) []GoWorkspace {
|
||||
|
||||
results := make([]GoWorkspace, len(goWorkFiles))
|
||||
for i, workFilePath := range goWorkFiles {
|
||||
results[i] = discoverWorkspace(workFilePath)
|
||||
results[i] = discoverWorkspace(emitDiagnostics, workFilePath)
|
||||
}
|
||||
|
||||
// Add all stray `go.mod` files (i.e. those not referenced by `go.work` files)
|
||||
@@ -335,7 +357,7 @@ func discoverWorkspaces(emitDiagnostics bool) []GoWorkspace {
|
||||
log.Printf("Module %s is not referenced by any go.work file; adding it separately.\n", goModFile)
|
||||
results = append(results, GoWorkspace{
|
||||
BaseDir: filepath.Dir(goModFile),
|
||||
Modules: LoadGoModules([]string{goModFile}),
|
||||
Modules: LoadGoModules(emitDiagnostics, []string{goModFile}),
|
||||
DepMode: GoGetWithModules,
|
||||
ModMode: getModMode(GoGetWithModules, filepath.Dir(goModFile)),
|
||||
})
|
||||
|
||||
@@ -18,7 +18,15 @@ func IsInstalled() bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// The default Go version that is available on a system and a set of all versions
|
||||
// that we know are installed on the system.
|
||||
var goVersion = ""
|
||||
var goVersions = map[string]struct{}{}
|
||||
|
||||
// Adds an entry to the set of installed Go versions for the normalised `version` number.
|
||||
func addGoVersion(version string) {
|
||||
goVersions[semver.Canonical("v"+version)] = struct{}{}
|
||||
}
|
||||
|
||||
// Returns the current Go version as returned by 'go version', e.g. go1.14.4
|
||||
func GetEnvGoVersion() string {
|
||||
@@ -27,7 +35,7 @@ func GetEnvGoVersion() string {
|
||||
// download the version of Go specified in there. That may either fail or result in us just
|
||||
// being told what's already in 'go.mod'. Setting 'GOTOOLCHAIN' to 'local' will force it
|
||||
// to use the local Go toolchain instead.
|
||||
cmd := exec.Command("go", "version")
|
||||
cmd := Version()
|
||||
cmd.Env = append(os.Environ(), "GOTOOLCHAIN=local")
|
||||
out, err := cmd.CombinedOutput()
|
||||
|
||||
@@ -36,10 +44,59 @@ func GetEnvGoVersion() string {
|
||||
}
|
||||
|
||||
goVersion = parseGoVersion(string(out))
|
||||
addGoVersion(goVersion[2:])
|
||||
}
|
||||
return goVersion
|
||||
}
|
||||
|
||||
// Determines whether, to our knowledge, `version` is available on the current system.
|
||||
func HasGoVersion(version string) bool {
|
||||
_, found := goVersions[semver.Canonical("v"+version)]
|
||||
return found
|
||||
}
|
||||
|
||||
// Attempts to install the Go toolchain `version`.
|
||||
func InstallVersion(workingDir string, version string) bool {
|
||||
// No need to install it if we know that it is already installed.
|
||||
if HasGoVersion(version) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Construct a command to invoke `go version` with `GOTOOLCHAIN=go1.N.0` to give
|
||||
// Go a valid toolchain version to download the toolchain we need; subsequent commands
|
||||
// should then work even with an invalid version that's still in `go.mod`
|
||||
toolchainArg := "GOTOOLCHAIN=go" + semver.Canonical("v" + version)[1:]
|
||||
versionCmd := Version()
|
||||
versionCmd.Dir = workingDir
|
||||
versionCmd.Env = append(os.Environ(), toolchainArg)
|
||||
versionCmd.Stdout = os.Stdout
|
||||
versionCmd.Stderr = os.Stderr
|
||||
|
||||
log.Printf(
|
||||
"Trying to install Go %s using its canonical representation in `%s`.",
|
||||
version,
|
||||
workingDir,
|
||||
)
|
||||
|
||||
// Run the command. If something goes wrong, report it to the log and signal failure
|
||||
// to the caller.
|
||||
if versionErr := versionCmd.Run(); versionErr != nil {
|
||||
log.Printf(
|
||||
"Failed to invoke `%s go version` in %s: %s\n",
|
||||
toolchainArg,
|
||||
versionCmd.Dir,
|
||||
versionErr.Error(),
|
||||
)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Add the version to the set of versions that we know are installed and signal
|
||||
// success to the caller.
|
||||
addGoVersion(version)
|
||||
return true
|
||||
}
|
||||
|
||||
// Returns the current Go version in semver format, e.g. v1.14.4
|
||||
func GetEnvGoSemVer() string {
|
||||
goVersion := GetEnvGoVersion()
|
||||
@@ -107,3 +164,9 @@ func VendorModule(path string) *exec.Cmd {
|
||||
modVendor.Dir = path
|
||||
return modVendor
|
||||
}
|
||||
|
||||
// Constructs a command to run `go version`.
|
||||
func Version() *exec.Cmd {
|
||||
version := exec.Command("go", "version")
|
||||
return version
|
||||
}
|
||||
|
||||
@@ -14,3 +14,9 @@ func TestParseGoVersion(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasGoVersion(t *testing.T) {
|
||||
if HasGoVersion("1.21") {
|
||||
t.Error("Expected HasGoVersion(\"1.21\") to be false, but got true")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.0.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.0.10
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 0.0.11
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.10
|
||||
lastReleaseVersion: 0.0.11
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql-go-consistency-queries
|
||||
version: 0.0.11-dev
|
||||
version: 0.0.12-dev
|
||||
groups:
|
||||
- go
|
||||
- queries
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"location": {
|
||||
"file": "go.mod"
|
||||
},
|
||||
"markdownMessage": "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://go.dev/doc/toolchain#version).\n\n`1.21` in `go.mod` does not match this syntax and there is no additional `toolchain` directive, which may cause some `go` commands to fail.",
|
||||
"severity": "warning",
|
||||
"source": {
|
||||
"extractorName": "go",
|
||||
"id": "go/autobuilder/invalid-go-toolchain-version",
|
||||
"name": "Invalid Go toolchain version"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": true,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "A single `go.mod` file was found.\n\n`go.mod`",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "go",
|
||||
"id": "go/autobuilder/single-root-go-mod-found",
|
||||
"name": "A single `go.mod` file was found in the root"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": false,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
go 1.21
|
||||
|
||||
module example
|
||||
@@ -0,0 +1,5 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
|
||||
# Set up a GOPATH relative to this test's root directory;
|
||||
# we set os.environ instead of using extra_env because we
|
||||
# need it to be set for the call to "go clean -modcache" later
|
||||
goPath = os.path.join(os.path.abspath(os.getcwd()), ".go")
|
||||
os.environ['GOPATH'] = goPath
|
||||
os.environ['LGTM_INDEX_IMPORT_PATH'] = "test"
|
||||
run_codeql_database_create([], lang="go", source="src")
|
||||
|
||||
check_diagnostics()
|
||||
|
||||
# Clean up the temporary GOPATH to prevent Bazel failures next
|
||||
# time the tests are run; see https://github.com/golang/go/issues/27161
|
||||
subprocess.call(["go", "clean", "-modcache"])
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"location": {
|
||||
"file": "go.mod"
|
||||
},
|
||||
"markdownMessage": "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://go.dev/doc/toolchain#version).\n\n`1.21` in `go.mod` does not match this syntax and there is no additional `toolchain` directive, which may cause some `go` commands to fail.",
|
||||
"severity": "warning",
|
||||
"source": {
|
||||
"extractorName": "go",
|
||||
"id": "go/autobuilder/invalid-go-toolchain-version",
|
||||
"name": "Invalid Go toolchain version"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": true,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "A single `go.mod` file was found.\n\n`go.mod`",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "go",
|
||||
"id": "go/autobuilder/single-root-go-mod-found",
|
||||
"name": "A single `go.mod` file was found in the root"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": false,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
go 1.21
|
||||
|
||||
module test
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,18 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
|
||||
# Set up a GOPATH relative to this test's root directory;
|
||||
# we set os.environ instead of using extra_env because we
|
||||
# need it to be set for the call to "go clean -modcache" later
|
||||
goPath = os.path.join(os.path.abspath(os.getcwd()), ".go")
|
||||
os.environ['GOPATH'] = goPath
|
||||
run_codeql_database_create([], lang="go", source="src")
|
||||
|
||||
check_diagnostics()
|
||||
|
||||
# Clean up the temporary GOPATH to prevent Bazel failures next
|
||||
# time the tests are run; see https://github.com/golang/go/issues/27161
|
||||
subprocess.call(["go", "clean", "-modcache"])
|
||||
@@ -18,7 +18,7 @@
|
||||
"source": {
|
||||
"extractorName": "go",
|
||||
"id": "go/autobuilder/extraction-failed-for-project",
|
||||
"name": "Unable to extract 1 Go projects"
|
||||
"name": "Unable to extract some Go projects"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.7.12
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.7.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `CODEQL_EXTRACTOR_GO_FAST_PACKAGE_INFO` option, which speeds up retrieval of dependency information, is now on by default. This was originally an external contribution by @xhd2015.
|
||||
3
go/ql/lib/change-notes/released/0.7.12.md
Normal file
3
go/ql/lib/change-notes/released/0.7.12.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.7.12
|
||||
|
||||
No user-facing changes.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user