mirror of
https://github.com/github/codeql.git
synced 2026-05-24 08:07:07 +02:00
Compare commits
5 Commits
release-pr
...
criemen/ru
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fba481a04 | ||
|
|
9433201b58 | ||
|
|
c097397c32 | ||
|
|
3d5d1bc59e | ||
|
|
007fc89543 |
@@ -1 +1 @@
|
||||
7.0.2
|
||||
6.5.0
|
||||
|
||||
2
.github/labeler.yml
vendored
2
.github/labeler.yml
vendored
@@ -20,7 +20,7 @@ JS:
|
||||
|
||||
Kotlin:
|
||||
- java/kotlin-extractor/**/*
|
||||
- java/ql/test-kotlin*/**/*
|
||||
- java/ql/test/kotlin/**/*
|
||||
|
||||
Python:
|
||||
- python/**/*
|
||||
|
||||
2
.github/workflows/compile-queries.yml
vendored
2
.github/workflows/compile-queries.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
with:
|
||||
key: all-queries
|
||||
- name: check formatting
|
||||
run: find shared */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
- name: compile queries - check-only
|
||||
# run with --check-only if running in a PR (github.sha != main)
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -39,9 +39,6 @@
|
||||
# local bazel options
|
||||
/local.bazelrc
|
||||
|
||||
# generated cmake directory
|
||||
/.bazel-cmake
|
||||
|
||||
# CLion project files
|
||||
/.clwb
|
||||
|
||||
|
||||
16
MODULE.bazel
16
MODULE.bazel
@@ -21,6 +21,7 @@ bazel_dep(name = "bazel_skylib", version = "1.5.0")
|
||||
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")
|
||||
bazel_dep(name = "rules_rust", version = "0.39.0")
|
||||
|
||||
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
|
||||
pip.parse(
|
||||
@@ -51,3 +52,18 @@ use_repo(node, "nodejs", "nodejs_toolchains")
|
||||
register_toolchains(
|
||||
"@nodejs_toolchains//:all",
|
||||
)
|
||||
|
||||
crate = use_extension(
|
||||
"@rules_rust//crate_universe:extension.bzl",
|
||||
"crate",
|
||||
)
|
||||
|
||||
crate.from_cargo(
|
||||
name = "r", # short name due to long path issues on windows
|
||||
cargo_lockfile = "//ruby/extractor:Cargo.lock",
|
||||
manifests = [
|
||||
"//ruby/extractor:Cargo.toml",
|
||||
],
|
||||
)
|
||||
|
||||
use_repo(crate, "r")
|
||||
|
||||
@@ -431,6 +431,13 @@
|
||||
"java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp",
|
||||
"java/ql/src/experimental/Security/CWE/CWE-400/ThreadResourceAbuse.qhelp"
|
||||
],
|
||||
"IDE Contextual Queries": [
|
||||
"cpp/ql/lib/IDEContextual.qll",
|
||||
"csharp/ql/lib/IDEContextual.qll",
|
||||
"java/ql/lib/IDEContextual.qll",
|
||||
"javascript/ql/lib/IDEContextual.qll",
|
||||
"python/ql/lib/analysis/IDEContextual.qll"
|
||||
],
|
||||
"CryptoAlgorithms Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
|
||||
"python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Semmle.Autobuild.Shared;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Autobuild.Cpp
|
||||
{
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
## 0.12.8
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.12.7
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added destructors for named objects to the intermediate representation.
|
||||
|
||||
## 0.12.6
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import codeql.util.FileSystem
|
||||
|
||||
/**
|
||||
* Returns the `File` matching the given source file name as encoded by the VS
|
||||
@@ -11,5 +10,13 @@ private import codeql.util.FileSystem
|
||||
*/
|
||||
cached
|
||||
File getFileBySourceArchiveName(string name) {
|
||||
result = IdeContextual<File>::getFileBySourceArchiveName(name)
|
||||
// The name provided for a file in the source archive by the VS Code extension
|
||||
// has some differences from the absolute path in the database:
|
||||
// 1. colons are replaced by underscores
|
||||
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
|
||||
// "/C_/foo/bar"
|
||||
// 3. double slashes in UNC prefixes are replaced with a single slash
|
||||
// We can handle 2 and 3 together by unconditionally adding a leading slash
|
||||
// before replacing double slashes.
|
||||
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
## 0.12.7
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added destructors for named objects to the intermediate representation.
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.12.8
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.12.8
|
||||
lastReleaseVersion: 0.12.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.12.8
|
||||
version: 0.12.7-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -60,6 +60,4 @@ Element exprEnclosingElement(Expr e) {
|
||||
)
|
||||
else result = de.getDeclaration()
|
||||
)
|
||||
or
|
||||
result.(Stmt).getAnImplicitDestructorCall() = e
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// NOTE: There are two copies of this file, and they must be kept identical:
|
||||
// - semmle/code/cpp/controlflow/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll [now DEPRECATED]
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
|
||||
//
|
||||
// The second one is a private copy of the `SubBasicBlocks` library for
|
||||
// internal use by the data flow library. Having an extra copy prevents
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides a local analysis for identifying where a variable address
|
||||
* is effectively taken. Array-like offsets are allowed to pass through but
|
||||
* not field-like offsets.
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowUtil
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImpl
|
||||
import MakeImpl<CppOldDataFlow>
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImplCommon
|
||||
import MakeImplCommon<CppOldDataFlow>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides consistency queries for checking invariants in the language-specific
|
||||
* data-flow classes and predicates.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import DataFlowUtil
|
||||
private import DataFlowDispatch
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides a class for handling variables in the data flow analysis.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// NOTE: There are two copies of this file, and they must be kept identical:
|
||||
// - semmle/code/cpp/controlflow/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll [now DEPRECATED]
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
|
||||
//
|
||||
// The second one is a private copy of the `SubBasicBlocks` library for
|
||||
// internal use by the data flow library. Having an extra copy prevents
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the taint tracking library.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
* global (inter-procedural) taint-tracking analyses.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
|
||||
|
||||
module Private {
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
|
||||
|
||||
module Private {
|
||||
|
||||
@@ -34,7 +34,7 @@ private import Node0ToString
|
||||
cached
|
||||
private newtype TIRDataFlowNode =
|
||||
TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or
|
||||
TGlobalLikeVariableNode(GlobalLikeVariable var, int indirectionIndex) {
|
||||
TVariableNode(Variable var, int indirectionIndex) {
|
||||
indirectionIndex =
|
||||
[getMinIndirectionsForType(var.getUnspecifiedType()) .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
|
||||
} or
|
||||
@@ -396,7 +396,7 @@ class Node extends TIRDataFlowNode {
|
||||
* modeling flow in and out of global variables.
|
||||
*/
|
||||
Variable asVariable() {
|
||||
this = TGlobalLikeVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType()))
|
||||
this = TVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType()))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -406,7 +406,7 @@ class Node extends TIRDataFlowNode {
|
||||
*/
|
||||
Variable asIndirectVariable(int indirectionIndex) {
|
||||
indirectionIndex > getMinIndirectionsForType(result.getUnspecifiedType()) and
|
||||
this = TGlobalLikeVariableNode(result, indirectionIndex)
|
||||
this = TVariableNode(result, indirectionIndex)
|
||||
}
|
||||
|
||||
/** Gets an indirection of this node's underlying variable, if any. */
|
||||
@@ -1751,18 +1751,15 @@ class DefinitionByReferenceNode extends IndirectArgumentOutNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Node` corresponding to a global (or `static` local) variable in the
|
||||
* program, as opposed to the value of that variable at some particular point.
|
||||
* This is used to model flow through global variables (and `static` local
|
||||
* variables).
|
||||
*
|
||||
* There is no `VariableNode` for non-`static` local variables.
|
||||
* A `Node` corresponding to a variable in the program, as opposed to the
|
||||
* value of that variable at some particular point. This can be used for
|
||||
* modeling flow in and out of global variables.
|
||||
*/
|
||||
class VariableNode extends Node, TGlobalLikeVariableNode {
|
||||
class VariableNode extends Node, TVariableNode {
|
||||
Variable v;
|
||||
int indirectionIndex;
|
||||
|
||||
VariableNode() { this = TGlobalLikeVariableNode(v, indirectionIndex) }
|
||||
VariableNode() { this = TVariableNode(v, indirectionIndex) }
|
||||
|
||||
/** Gets the variable corresponding to this node. */
|
||||
Variable getVariable() { result = v }
|
||||
|
||||
@@ -11,7 +11,6 @@ private import InstructionTag
|
||||
private import TranslatedCondition
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import TranslatedCall
|
||||
private import TranslatedStmt
|
||||
private import TranslatedFunction
|
||||
private import TranslatedGlobalVar
|
||||
|
||||
@@ -85,14 +85,10 @@ newtype TInstructionTag =
|
||||
// The next three cases handle generation of branching for __except handling.
|
||||
TryExceptCompareNegativeOneBranch() or
|
||||
TryExceptCompareZeroBranch() or
|
||||
TryExceptCompareOneBranch() or
|
||||
ImplicitDestructorTag(int index) {
|
||||
exists(Expr e | exists(e.getImplicitDestructorCall(index))) or
|
||||
exists(Stmt s | exists(s.getImplicitDestructorCall(index)))
|
||||
}
|
||||
TryExceptCompareOneBranch()
|
||||
|
||||
class InstructionTag extends TInstructionTag {
|
||||
final string toString() { result = getInstructionTagId(this) }
|
||||
final string toString() { result = "Tag" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,8 +255,4 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
tag = TryExceptCompareZeroBranch() and result = "TryExceptCompareZeroBranch"
|
||||
or
|
||||
tag = TryExceptCompareOneBranch() and result = "TryExceptCompareOneBranch"
|
||||
or
|
||||
exists(int index |
|
||||
tag = ImplicitDestructorTag(index) and result = "ImplicitDestructor(" + index + ")"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ private CallInstruction getTranslatedCallInstruction(Call call) {
|
||||
* of a higher-level constructor (e.g. the allocator call in a `NewExpr`).
|
||||
*/
|
||||
abstract class TranslatedCall extends TranslatedExpr {
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
final override TranslatedElement getChild(int id) {
|
||||
// We choose the child's id in the order of evaluation.
|
||||
// The qualifier is evaluated before the call target, because the value of
|
||||
// the call target may depend on the value of the qualifier for virtual
|
||||
@@ -47,19 +47,13 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
else result = this.getFirstCallTargetInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getSideEffects().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getSideEffects() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getTypeForPRValue(this.getCallResultType())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getQualifier() and
|
||||
result = this.getFirstCallTargetInstruction(kind)
|
||||
or
|
||||
@@ -93,7 +87,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CallTag() and
|
||||
result = this.getSideEffects().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -231,7 +225,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement te, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement te, EdgeKind kind) {
|
||||
exists(int i |
|
||||
this.getChild(i) = te and
|
||||
if exists(this.getChild(i + 1))
|
||||
@@ -240,10 +234,6 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int i | exists(this.getChild(i))))
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
none()
|
||||
}
|
||||
@@ -256,18 +246,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if exists(this.getAChild())
|
||||
then result = this.getChild(max(int i | exists(this.getChild(i)))).getALastInstruction()
|
||||
else
|
||||
// If there are no side effects, the "last" instruction should be the parent call's last
|
||||
// instruction, so that implicit destructors can be inserted in the right place.
|
||||
result = this.getParent().getInstruction(CallTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
/** Gets the primary instruction to be associated with each side effect instruction. */
|
||||
abstract Instruction getPrimaryInstruction();
|
||||
@@ -294,8 +273,8 @@ abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
resultType = getFunctionGLValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedCall.super.getInstructionSuccessorInternal(tag, kind)
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
tag = CallTargetTag() and
|
||||
result = this.getFirstArgumentOrCallInstruction(kind)
|
||||
@@ -388,16 +367,6 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
|
||||
context = this.getParent() and
|
||||
result = context.getReceiver()
|
||||
)
|
||||
or
|
||||
exists(Stmt parent |
|
||||
expr = parent.getAnImplicitDestructorCall() and
|
||||
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
|
||||
)
|
||||
or
|
||||
exists(Expr parent |
|
||||
expr = parent.getAnImplicitDestructorCall() and
|
||||
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasQualifier() { any() }
|
||||
@@ -447,25 +416,19 @@ private int initializeAllocationGroup() { result = 3 }
|
||||
abstract class TranslatedSideEffect extends TranslatedElement {
|
||||
final override TranslatedElement getChild(int n) { none() }
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
tag = OnlyInstructionTag() and
|
||||
this.sideEffectInstruction(opcode, type)
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = this.getParent().getChildSuccessor(this, kind) and
|
||||
tag = OnlyInstructionTag()
|
||||
}
|
||||
|
||||
@@ -50,29 +50,19 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
|
||||
{
|
||||
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getOperand().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getOperand().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
abstract TranslatedCondition getOperand();
|
||||
}
|
||||
@@ -98,16 +88,12 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
|
||||
abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslatedNativeCondition {
|
||||
TranslatedNativeCondition() { this = TTranslatedNativeCondition(expr) }
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeCondition, ConditionContext {
|
||||
override BinaryLogicalOperation expr;
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getLeftOperand()
|
||||
or
|
||||
@@ -118,19 +104,11 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
|
||||
result = this.getLeftOperand().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getLeftOperand().getALastInstruction()
|
||||
or
|
||||
result = this.getRightOperand().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final TranslatedCondition getLeftOperand() {
|
||||
result = getTranslatedCondition(expr.getLeftOperand().getFullyConverted())
|
||||
@@ -184,25 +162,19 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
result = this.getValueExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
}
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
opcode instanceof Opcode::ConditionalBranch and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getValueExpr() and
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
|
||||
@@ -60,10 +60,6 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
|
||||
*/
|
||||
abstract LocalVariable getVariable();
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = getVariableType(this.getVariable()) }
|
||||
|
||||
final override TranslatedInitialization getInitialization() {
|
||||
@@ -156,13 +152,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(DynamicInitializationConditionalBranchTag())
|
||||
or
|
||||
result = this.getInstruction(DynamicInitializationFlagStoreTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(DynamicInitializationFlagLoadTag())
|
||||
@@ -188,7 +178,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getInstruction(DynamicInitializationFlagConstantTag()) and
|
||||
kind instanceof GotoEdge
|
||||
|
||||
@@ -20,14 +20,10 @@ private import SideEffects
|
||||
* they were explicit nodes in the expression tree, rather than as implicit
|
||||
* nodes as in the regular AST representation.
|
||||
*/
|
||||
Element getRealParent(Expr expr) {
|
||||
private Element getRealParent(Expr expr) {
|
||||
result = expr.getParentWithConversions()
|
||||
or
|
||||
result.(Destructor).getADestruction() = expr
|
||||
or
|
||||
result.(Expr).getAnImplicitDestructorCall() = expr
|
||||
or
|
||||
result.(Stmt).getAnImplicitDestructorCall() = expr
|
||||
}
|
||||
|
||||
IRUserVariable getIRUserVariable(Declaration decl, Variable var) {
|
||||
@@ -109,6 +105,12 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
newExpr.getAllocatorCall() = expr
|
||||
)
|
||||
or
|
||||
exists(DeleteOrDeleteArrayExpr deleteExpr |
|
||||
// Ignore the destructor call as we don't model it yet. Don't ignore
|
||||
// its arguments, though, as they are the arguments to the deallocator.
|
||||
deleteExpr.getDestructorCall() = expr
|
||||
)
|
||||
or
|
||||
// The extractor deliberately emits an `ErrorExpr` as the first argument to
|
||||
// the allocator call, if any, of a `NewOrNewArrayExpr`. That `ErrorExpr`
|
||||
// should not be translated.
|
||||
@@ -116,11 +118,6 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
or
|
||||
not translateFunction(getEnclosingFunction(expr)) and
|
||||
not Raw::varHasIRFunc(getEnclosingVariable(expr))
|
||||
or
|
||||
exists(DeleteOrDeleteArrayExpr deleteExpr |
|
||||
// Ignore the destructor call, because the duplicated qualifier breaks control flow.
|
||||
deleteExpr.getDestructorCall() = expr
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -611,27 +608,16 @@ newtype TTranslatedElement =
|
||||
TTranslatedInitialization(Expr expr) {
|
||||
not ignoreExpr(expr) and
|
||||
(
|
||||
exists(Initializer init | init.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(ClassAggregateLiteral initList | initList.getAFieldExpr(_).getFullyConverted() = expr)
|
||||
or
|
||||
exists(Initializer init | init.getExpr().getFullyConverted() = expr) or
|
||||
exists(ClassAggregateLiteral initList | initList.getAFieldExpr(_).getFullyConverted() = expr) or
|
||||
exists(ArrayOrVectorAggregateLiteral initList |
|
||||
initList.getAnElementExpr(_).getFullyConverted() = expr
|
||||
)
|
||||
or
|
||||
exists(ReturnStmt returnStmt |
|
||||
returnStmt.getExpr().getFullyConverted() = expr and
|
||||
hasReturnValue(returnStmt.getEnclosingFunction())
|
||||
)
|
||||
or
|
||||
exists(ConstructorFieldInit fieldInit | fieldInit.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(NewExpr newExpr | newExpr.getInitializer().getFullyConverted() = expr)
|
||||
or
|
||||
exists(ThrowExpr throw | throw.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(TemporaryObjectExpr temp | temp.getExpr() = expr)
|
||||
or
|
||||
) or
|
||||
exists(ReturnStmt returnStmt | returnStmt.getExpr().getFullyConverted() = expr) or
|
||||
exists(ConstructorFieldInit fieldInit | fieldInit.getExpr().getFullyConverted() = expr) or
|
||||
exists(NewExpr newExpr | newExpr.getInitializer().getFullyConverted() = expr) or
|
||||
exists(ThrowExpr throw | throw.getExpr().getFullyConverted() = expr) or
|
||||
exists(TemporaryObjectExpr temp | temp.getExpr() = expr) or
|
||||
exists(LambdaExpression lambda | lambda.getInitializer().getFullyConverted() = expr)
|
||||
)
|
||||
} or
|
||||
@@ -765,6 +751,8 @@ newtype TTranslatedElement =
|
||||
// on `*this` without an `Expr`.
|
||||
TTranslatedStructorQualifierSideEffect(Call call, SideEffectOpcode opcode) {
|
||||
not ignoreSideEffects(call) and
|
||||
// Don't bother with destructor calls for now, since we won't see very many of them in the IR
|
||||
// until we start injecting implicit destructor calls.
|
||||
call instanceof ConstructorCall and
|
||||
opcode = getASideEffectOpcode(call, -1)
|
||||
} or
|
||||
@@ -878,23 +866,6 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
1 + sum(TranslatedElement child | child = this.getChildByRank(_) | child.getDescendantCount())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element has implicit destructor calls that should follow it.
|
||||
*/
|
||||
predicate hasAnImplicitDestructorCall() { none() }
|
||||
|
||||
/**
|
||||
* Gets the child index of the first destructor call that should be executed after this `TranslatedElement`
|
||||
*/
|
||||
int getFirstDestructorCallIndex() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this `TranslatedElement` includes any destructor calls that must be performed after
|
||||
* it in its `getChildSuccessorInternal`, `getInstructionSuccessorInternal`, and
|
||||
* `getALastInstructionInternal` relations, rather than needing them inserted.
|
||||
*/
|
||||
predicate handlesDestructorsExplicitly() { none() }
|
||||
|
||||
private int getUniqueId() {
|
||||
if not exists(this.getParent())
|
||||
then result = 0
|
||||
@@ -930,81 +901,15 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
/**
|
||||
* Gets the successor instruction of the instruction that was generated by
|
||||
* this element for tag `tag`. The successor edge kind is specified by `kind`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getInstructionSuccessor` unless `handlesDestructorsExplicitly`
|
||||
* holds.
|
||||
*/
|
||||
abstract Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind);
|
||||
|
||||
/**
|
||||
* Gets the successor instruction of the instruction that was generated by
|
||||
* this element for tag `tag`. The successor edge kind is specified by `kind`.
|
||||
*/
|
||||
final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
if
|
||||
this.hasAnImplicitDestructorCall() and
|
||||
this.getInstruction(tag) = this.getALastInstructionInternal() and
|
||||
not this.handlesDestructorsExplicitly()
|
||||
then
|
||||
result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind) and
|
||||
kind instanceof GotoEdge
|
||||
else result = this.getInstructionSuccessorInternal(tag, kind)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction within this `TranslatedElement` (including its transitive children) which
|
||||
* will be followed by an instruction outside the `TranslatedElement`.
|
||||
*/
|
||||
final Instruction getALastInstruction() {
|
||||
if this.hasAnImplicitDestructorCall() and not this.handlesDestructorsExplicitly()
|
||||
then result = this.getChild(max(int n | exists(this.getChild(n)))).getALastInstruction() // last destructor
|
||||
else result = this.getALastInstructionInternal()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction within this `TranslatedElement` (including its transitive children) which
|
||||
* will be followed by an instruction outside the `TranslatedElement`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getALastInstruction` unless `handlesDestructorsExplicitly` holds.
|
||||
*/
|
||||
abstract Instruction getALastInstructionInternal();
|
||||
|
||||
TranslatedElement getLastChild() { none() }
|
||||
|
||||
/**
|
||||
* Gets the successor instruction to which control should flow after the
|
||||
* child element specified by `child` has finished execution. The successor
|
||||
* edge kind is specified by `kind`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getChildSuccessor` unless `handlesDestructorsExplicitly` holds.
|
||||
*/
|
||||
Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
abstract Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind);
|
||||
|
||||
/**
|
||||
* Gets the successor instruction to which control should flow after the
|
||||
* child element specified by `child` has finished execution. The successor
|
||||
* edge kind is specified by `kind`.
|
||||
*/
|
||||
final Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
(
|
||||
if
|
||||
// this is the last child and we need to handle destructors for it
|
||||
this.hasAnImplicitDestructorCall() and
|
||||
not this.handlesDestructorsExplicitly() and
|
||||
child = this.getLastChild()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getChildSuccessorInternal(child, kind)
|
||||
)
|
||||
or
|
||||
not this.handlesDestructorsExplicitly() and
|
||||
exists(int id |
|
||||
id >= this.getFirstDestructorCallIndex() and
|
||||
child = this.getChild(id) and
|
||||
if id = max(int n | exists(this.getChild(n)))
|
||||
then result = this.getParent().getChildSuccessor(this, kind)
|
||||
else result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
)
|
||||
}
|
||||
abstract Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind);
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control should flow if an exception is thrown
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -114,11 +114,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
@@ -154,7 +150,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int paramIndex | child = this.getParameter(paramIndex) |
|
||||
if
|
||||
exists(func.getParameter(paramIndex + 1)) or
|
||||
@@ -383,13 +379,7 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasIndirection()
|
||||
then result = this.getInstruction(InitializerIndirectStoreTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerVariableAddressTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
@@ -407,9 +397,7 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
@@ -623,23 +611,15 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getLastChild().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
@@ -698,23 +678,15 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
@@ -756,20 +728,7 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if exists(this.getAChild())
|
||||
then
|
||||
result =
|
||||
max(TranslatedElement child, int id | child = this.getChild(id) | child order by id)
|
||||
.getFirstInstruction(any(GotoEdge goto))
|
||||
else result = this.getParent().getChildSuccessor(this, any(GotoEdge goto))
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id | child = this.getChild(id) |
|
||||
if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = this.getChild(id2))
|
||||
then
|
||||
@@ -787,7 +746,7 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
private TranslatedThisReadEffect getTranslatedThisReadEffect(Function func) {
|
||||
@@ -801,9 +760,9 @@ private TranslatedParameterReadEffect getTranslatedParameterReadEffect(Parameter
|
||||
abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -813,10 +772,6 @@ abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
opcode instanceof Opcode::ReturnIndirection and
|
||||
tag = OnlyInstructionTag() and
|
||||
|
||||
@@ -27,10 +27,6 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int n) {
|
||||
n = 1 and
|
||||
result = getTranslatedInitialization(var.getInitializer().getExpr().getFullyConverted())
|
||||
@@ -62,7 +58,7 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
type = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
@@ -85,7 +81,7 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getChild(1) and
|
||||
result = this.getInstruction(ReturnTag()) and
|
||||
kind instanceof GotoEdge
|
||||
|
||||
@@ -35,19 +35,13 @@ abstract class InitializationContext extends TranslatedElement {
|
||||
* declarations, `return` statements, and `throw` expressions.
|
||||
*/
|
||||
abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext {
|
||||
TranslatedElement getChildInternal(int id) { id = 0 and result = this.getInitialization() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(InitializerVariableAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
or
|
||||
not exists(this.getInitialization()) and result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
@@ -59,7 +53,7 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
resultType = getTypeForPRValue(this.getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
if this.hasUninitializedInstruction()
|
||||
@@ -77,7 +71,7 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getInitializationSuccessor(kind)
|
||||
}
|
||||
@@ -183,11 +177,7 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(max(int i | exists(this.getChild(i)))).getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
@@ -200,9 +190,7 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getTargetAddress() { result = this.getContext().getTargetAddress() }
|
||||
|
||||
@@ -272,22 +260,18 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
not expr instanceof StringLiteral
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(this.getContext().getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and
|
||||
result = this.getInstruction(InitializerStoreTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -312,12 +296,6 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
class TranslatedStringLiteralInitialization extends TranslatedDirectInitialization {
|
||||
override StringLiteral expr;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.zeroInitRange(_, _)
|
||||
then result = this.getInstruction(ZeroPadStringStoreTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
// Load the string literal to make it a prvalue of type `char[len]`
|
||||
tag = InitializerLoadStringTag() and
|
||||
@@ -359,7 +337,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerLoadStringTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
@@ -389,7 +367,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and
|
||||
result = this.getInstruction(InitializerLoadStringTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -479,22 +457,16 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
|
||||
{
|
||||
override ConstructorCall expr;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitializer().getALastInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getInitializer() }
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
none()
|
||||
}
|
||||
@@ -586,29 +558,23 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio
|
||||
this = TTranslatedExplicitFieldInitialization(ast, field, expr, position)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = field.getUnspecifiedType() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getInitialization() }
|
||||
|
||||
private TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(expr)
|
||||
}
|
||||
@@ -629,10 +595,6 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
{
|
||||
TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) }
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(this.getFieldDefaultValueStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
@@ -645,7 +607,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
resultType = getTypeForPRValue(field.getUnspecifiedType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = this.getFieldAddressTag() and
|
||||
@@ -677,7 +639,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -727,7 +689,7 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getInstruction(this.getElementAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -781,24 +743,20 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
|
||||
this = TTranslatedExplicitElementInitialization(initList, elementIndex, position)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = this.getElementType() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessorInternal(tag, kind)
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
@@ -830,10 +788,6 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
this = TTranslatedElementValueInitialization(initList, elementIndex, elementCount)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(this.getElementDefaultValueStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
@@ -846,8 +800,8 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
resultType = this.getDefaultValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessorInternal(tag, kind)
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
@@ -882,7 +836,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -922,13 +876,11 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
|
||||
final override Function getFunction() { result = getEnclosingFunction(call) }
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getStructorCall() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getStructorCall() }
|
||||
|
||||
final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) }
|
||||
}
|
||||
|
||||
@@ -942,17 +894,13 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getStructorCall().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::ConvertToNonVirtualBase and
|
||||
resultType = getTypeForGLValue(call.getTarget().getDeclaringType())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getStructorCall().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -999,17 +947,11 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
result = this.getStructorCall().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getStructorCall().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getReceiver() {
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
@@ -1067,8 +1009,6 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() { none() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
@@ -1077,9 +1017,9 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
|
||||
override Declaration getFunction() { result = this.getParent().getFunction() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
|
||||
|
||||
@@ -138,7 +138,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = "1"
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
// Generate -1 -> Compare condition
|
||||
tag = TryExceptGenerateNegativeOne() and
|
||||
kind instanceof GotoEdge and
|
||||
@@ -202,7 +202,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
child = this.getTranslatedCondition() and
|
||||
result = this.getInstruction(TryExceptGenerateNegativeOne())
|
||||
@@ -211,14 +211,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getTranslatedHandler() }
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getTranslatedHandler().getALastInstruction()
|
||||
or
|
||||
result = this.getInstruction(UnwindTag())
|
||||
}
|
||||
|
||||
private TranslatedExpr getTranslatedCondition() {
|
||||
result = getTranslatedExpr(tryExcept.getCondition())
|
||||
}
|
||||
@@ -243,27 +235,6 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
|
||||
TranslatedStmt() { this = TTranslatedStmt(stmt) }
|
||||
|
||||
abstract TranslatedElement getChildInternal(int id);
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
result = this.getChildInternal(id)
|
||||
or
|
||||
exists(int destructorIndex |
|
||||
result.(TranslatedExpr).getExpr() = stmt.getImplicitDestructorCall(destructorIndex) and
|
||||
id = this.getFirstDestructorCallIndex() + destructorIndex
|
||||
)
|
||||
}
|
||||
|
||||
final override int getFirstDestructorCallIndex() {
|
||||
result = max(int childId | exists(this.getChildInternal(childId))) + 1
|
||||
or
|
||||
not exists(this.getChildInternal(_)) and result = 0
|
||||
}
|
||||
|
||||
final override predicate hasAnImplicitDestructorCall() {
|
||||
exists(stmt.getAnImplicitDestructorCall())
|
||||
}
|
||||
|
||||
final override string toString() { result = stmt.toString() }
|
||||
|
||||
final override Locatable getAst() { result = stmt }
|
||||
@@ -281,29 +252,25 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
stmt instanceof SwitchCase
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +281,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
class TranslatedDeclStmt extends TranslatedStmt {
|
||||
override DeclStmt stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { result = this.getDeclarationEntry(id) }
|
||||
override TranslatedElement getChild(int id) { result = this.getDeclarationEntry(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -327,12 +294,6 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(this.getChildCount() - 1).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getChild(this.getChildCount() - 1) }
|
||||
|
||||
private int getChildCount() { result = count(this.getDeclarationEntry(_)) }
|
||||
|
||||
IRDeclarationEntry getIRDeclarationEntry(int index) {
|
||||
@@ -357,9 +318,9 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getDeclarationEntry(index) and
|
||||
if index = (this.getChildCount() - 1)
|
||||
@@ -374,7 +335,7 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
|
||||
TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { id = 0 and result = this.getExpr() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getExpr() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -384,15 +345,9 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
result = this.getExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getExpr().getALastInstruction()
|
||||
}
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getExpr() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getExpr() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -404,21 +359,6 @@ abstract class TranslatedReturnStmt extends TranslatedStmt {
|
||||
final TranslatedFunction getEnclosingFunction() {
|
||||
result = getTranslatedFunction(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
id >= this.getFirstDestructorCallIndex() and
|
||||
(
|
||||
result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
or
|
||||
not exists(this.getChild(id + 1)) and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,19 +368,7 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
|
||||
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
|
||||
|
||||
final override Instruction getInitializationSuccessor(EdgeKind kind) {
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(1).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = TranslatedVariableInitialization.super.getChildSuccessorInternal(child, kind)
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
@@ -462,7 +390,7 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = this.getExpr()
|
||||
}
|
||||
@@ -471,31 +399,21 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
result = this.getExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
else result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(1).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getExpr() and
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) }
|
||||
@@ -510,43 +428,25 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
not stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
else result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(0).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
this.getChild(id) = child and
|
||||
(
|
||||
result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
or
|
||||
not exists(this.getChild(id + 1)) and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
)
|
||||
)
|
||||
}
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -564,16 +464,6 @@ class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariab
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = TranslatedVariableInitialization.super.getChildSuccessorInternal(child, kind)
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
|
||||
final override TranslatedInitialization getInitialization() { none() }
|
||||
@@ -628,7 +518,7 @@ private class TryOrMicrosoftTryStmt extends Stmt {
|
||||
class TranslatedTryStmt extends TranslatedStmt {
|
||||
override TryOrMicrosoftTryStmt stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getBody()
|
||||
or
|
||||
result = this.getHandler(id - 1)
|
||||
@@ -641,23 +531,13 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getLastChild().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
if exists(this.getFinally())
|
||||
then result = this.getFinally()
|
||||
else result = [this.getBody(), this.getHandler(_)]
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
// All non-finally children go to the successor of the `try` if
|
||||
// there is no finally block, but if there is a finally block
|
||||
// then we go to that one.
|
||||
@@ -701,7 +581,7 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
class TranslatedBlock extends TranslatedStmt {
|
||||
override BlockStmt stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { result = this.getStmt(id) }
|
||||
override TranslatedElement getChild(int id) { result = this.getStmt(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
this.isEmpty() and
|
||||
@@ -716,26 +596,18 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
else result = this.getStmt(0).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.isEmpty()
|
||||
then result = this.getInstruction(OnlyInstructionTag())
|
||||
else result = this.getStmt(this.getStmtCount() - 1).getFirstInstruction(any(GotoEdge goto))
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getStmt(this.getStmtCount() - 1) }
|
||||
|
||||
private predicate isEmpty() { not exists(stmt.getStmt(0)) }
|
||||
|
||||
private TranslatedStmt getStmt(int index) { result = getTranslatedStmt(stmt.getStmt(index)) }
|
||||
|
||||
private int getStmtCount() { result = stmt.getNumStmt() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getStmt(index) and
|
||||
if index = (this.getStmtCount() - 1)
|
||||
@@ -751,20 +623,14 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
abstract class TranslatedHandler extends TranslatedStmt {
|
||||
override Handler stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { id = 1 and result = this.getBlock() }
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = this.getBlock() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(CatchTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getBlock().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getBlock() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBlock() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
@@ -790,20 +656,20 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
result = super.getChildInternal(id)
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = super.getChild(id)
|
||||
or
|
||||
id = 0 and result = this.getParameter()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = super.getChildSuccessorInternal(child, kind)
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
result = super.getChildSuccessor(child, kind)
|
||||
or
|
||||
child = this.getParameter() and
|
||||
result = this.getBlock().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
(
|
||||
kind instanceof GotoEdge and
|
||||
@@ -836,7 +702,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
result = this.getBlock().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -851,13 +717,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getElse().getALastInstruction() or result = this.getThen().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getElse() or result = this.getThen() }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
@@ -887,7 +747,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
|
||||
private predicate hasElse() { exists(stmt.getElse()) }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
@@ -901,7 +761,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
@@ -923,7 +783,7 @@ class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
@@ -953,7 +813,7 @@ class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
|
||||
private predicate hasElse() { exists(stmt.getElse()) }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
@@ -967,7 +827,7 @@ class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
@@ -978,23 +838,11 @@ class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getThen().getALastInstruction()
|
||||
or
|
||||
result = this.getElse().getALastInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
override Loop stmt;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getCondition().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getCondition() }
|
||||
|
||||
final TranslatedCondition getCondition() {
|
||||
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
|
||||
}
|
||||
@@ -1009,7 +857,7 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
|
||||
final predicate hasCondition() { exists(stmt.getCondition()) }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getCondition()
|
||||
or
|
||||
id = 1 and result = this.getBody()
|
||||
@@ -1019,15 +867,13 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -1036,36 +882,13 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
class TranslatedWhileStmt extends TranslatedLoop {
|
||||
TranslatedWhileStmt() { stmt instanceof WhileStmt }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getCondition()
|
||||
or
|
||||
id = 1 and result = this.getBody()
|
||||
or
|
||||
exists(int n |
|
||||
result.getAst() = stmt.getImplicitDestructorCall(n) and
|
||||
id = 2 + n
|
||||
)
|
||||
}
|
||||
|
||||
override predicate handlesDestructorsExplicitly() { any() }
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBody() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
child = this.getChild(this.getFirstDestructorCallIndex()) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1076,7 +899,7 @@ class TranslatedDoStmt extends TranslatedLoop {
|
||||
result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBody() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
@@ -1085,16 +908,7 @@ class TranslatedDoStmt extends TranslatedLoop {
|
||||
class TranslatedForStmt extends TranslatedLoop {
|
||||
override ForStmt stmt;
|
||||
|
||||
override predicate handlesDestructorsExplicitly() { any() }
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
@@ -1102,11 +916,6 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
id = 2 and result = this.getUpdate()
|
||||
or
|
||||
id = 3 and result = this.getBody()
|
||||
or
|
||||
exists(int n |
|
||||
result.getAst() = stmt.getImplicitDestructorCall(n) and
|
||||
id = 4 + n
|
||||
)
|
||||
}
|
||||
|
||||
private TranslatedStmt getInitialization() {
|
||||
@@ -1125,7 +934,7 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
@@ -1137,19 +946,6 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
)
|
||||
or
|
||||
child = this.getUpdate() and result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
exists(int destructorId |
|
||||
destructorId >= this.getFirstDestructorCallIndex() and
|
||||
child = this.getChild(destructorId) and
|
||||
result = this.getChild(destructorId + 1).getFirstInstruction(kind)
|
||||
)
|
||||
or
|
||||
exists(int lastDestructorIndex |
|
||||
lastDestructorIndex =
|
||||
max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
|
||||
child = this.getChild(lastDestructorIndex) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1163,7 +959,7 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override RangeBasedForStmt stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getRangeVariableDeclStmt()
|
||||
@@ -1192,13 +988,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getFirstRangeVariableDeclStmtInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getCondition().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getCondition() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstRangeVariableDeclStmtInstruction(kind)
|
||||
or
|
||||
@@ -1222,7 +1012,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
@@ -1280,11 +1070,7 @@ class TranslatedJumpStmt extends TranslatedStmt {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -1292,12 +1078,12 @@ class TranslatedJumpStmt extends TranslatedStmt {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
private EdgeKind getCaseEdge(SwitchCase switchCase) {
|
||||
@@ -1328,13 +1114,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
else result = this.getFirstExprInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getBody().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getBody() }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getExpr()
|
||||
@@ -1360,7 +1140,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = this.getExpr().getResult()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = SwitchBranchTag() and
|
||||
exists(SwitchCase switchCase |
|
||||
switchCase = stmt.getASwitchCase() and
|
||||
@@ -1374,7 +1154,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = this.getParent().getChildSuccessor(this, any(GotoEdge edge))
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstExprInstruction(kind)
|
||||
or
|
||||
@@ -1389,7 +1169,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
class TranslatedAsmStmt extends TranslatedStmt {
|
||||
override AsmStmt stmt;
|
||||
|
||||
override TranslatedExpr getChildInternal(int id) {
|
||||
override TranslatedExpr getChild(int id) {
|
||||
result = getTranslatedExpr(stmt.getChild(id).(Expr).getFullyConverted())
|
||||
}
|
||||
|
||||
@@ -1401,8 +1181,6 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() { result = this.getInstruction(AsmTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = AsmTag() and
|
||||
opcode instanceof Opcode::InlineAsm and
|
||||
@@ -1413,7 +1191,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
exists(int index |
|
||||
tag = AsmTag() and
|
||||
operandTag = asmOperand(index) and
|
||||
result = this.getChildInternal(index).getResult()
|
||||
result = this.getChild(index).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1425,12 +1203,12 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
result = getUnknownType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = AsmTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
@@ -1445,7 +1223,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
override VlaDimensionStmt stmt;
|
||||
|
||||
override TranslatedExpr getChildInternal(int id) {
|
||||
override TranslatedExpr getChild(int id) {
|
||||
id = 0 and
|
||||
result = getTranslatedExpr(stmt.getDimensionExpr().getFullyConverted())
|
||||
}
|
||||
@@ -1454,19 +1232,13 @@ class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
result = this.getChild(0).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(0).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getChild(0) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getChild(0) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -1475,17 +1247,13 @@ class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
class TranslatedVlaDeclarationStmt extends TranslatedStmt {
|
||||
override VlaDeclStmt stmt;
|
||||
|
||||
override TranslatedExpr getChildInternal(int id) { none() }
|
||||
override TranslatedExpr getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
// TODO: This needs a new kind of instruction that represents initialization of a VLA.
|
||||
// For now we just emit a `NoOp` instruction so that the CFG isn't incomplete.
|
||||
@@ -1494,10 +1262,10 @@ class TranslatedVlaDeclarationStmt extends TranslatedStmt {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ private int getTypeSizeWorkaround(Type type) {
|
||||
exists(Type unspecifiedType |
|
||||
unspecifiedType = type.getUnspecifiedType() and
|
||||
(
|
||||
(unspecifiedType instanceof FunctionReferenceType or unspecifiedType instanceof RoutineType) and
|
||||
unspecifiedType instanceof FunctionReferenceType and
|
||||
result = getPointerSize()
|
||||
or
|
||||
exists(PointerToMemberType ptmType |
|
||||
@@ -176,7 +176,7 @@ private IRType getIRTypeForPRValue(Type type) {
|
||||
isPointerIshType(unspecifiedType) and
|
||||
result.(IRAddressType).getByteSize() = getTypeSize(unspecifiedType)
|
||||
or
|
||||
(unspecifiedType instanceof FunctionPointerIshType or unspecifiedType instanceof RoutineType) and
|
||||
unspecifiedType instanceof FunctionPointerIshType and
|
||||
result.(IRFunctionAddressType).getByteSize() = getTypeSize(type)
|
||||
or
|
||||
unspecifiedType instanceof VoidType and result instanceof IRVoidType
|
||||
|
||||
@@ -168,57 +168,3 @@ private class SmartPtrSetterFunction extends MemberFunction, AliasFunction, Side
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A destructor assocaited with a smart pointer. */
|
||||
private class SmartPtrDestructor extends Destructor, SideEffectFunction, AliasFunction {
|
||||
SmartPtr declaringType;
|
||||
|
||||
SmartPtrDestructor() {
|
||||
declaringType = this.getDeclaringType() and not this.isFromUninstantiatedTemplate(_)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the destructor associated with the base type of this smart pointer.
|
||||
*/
|
||||
private Destructor getBaseTypeDestructor() {
|
||||
result.getDeclaringType() = declaringType.getBaseType()
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() {
|
||||
this.getBaseTypeDestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't have
|
||||
// any strange read side effects.
|
||||
not exists(this.getBaseTypeDestructor())
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() {
|
||||
this.getBaseTypeDestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't have
|
||||
// any strange write side effects.
|
||||
not exists(this.getBaseTypeDestructor())
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = -1 and buffer = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = -1 and buffer = false and mustWrite = true
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) {
|
||||
this.getBaseTypeDestructor().(AliasFunction).parameterNeverEscapes(index)
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't cause
|
||||
// anything to escape.
|
||||
not exists(this.getBaseTypeDestructor()) and
|
||||
index = -1
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) {
|
||||
// A destructor call does not have a return value
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
## 0.9.7
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.9.6
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.
|
||||
* The new C/C++ dataflow and taint-tracking libraries (`semmle.code.cpp.dataflow.new.DataFlow` and `semmle.code.cpp.dataflow.new.TaintTracking`) now implicitly assume that dataflow and taint modelled via `DataFlowFunction` and `TaintFunction` always fully overwrite their buffers and thus act as flow barriers. As a result, many dataflow and taint-tracking queries now produce fewer false positives. To remove this assumption and go back to the previous behavior for a given model, one can override the new `isPartialWrite` predicate.
|
||||
|
||||
## 0.9.5
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* type `const char*` it is still considered non-constant if the value is not coming from a string
|
||||
* literal. For example, for a parameter with type `const char*` of an exported function that is
|
||||
* used as a format string, there is no way to ensure the originating value was a string literal.
|
||||
* @kind path-problem
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
@@ -26,7 +26,6 @@ import semmle.code.cpp.ir.dataflow.internal.ModelUtil
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.ir.IR
|
||||
import NonConstFlow::PathGraph
|
||||
|
||||
class UncalledFunction extends Function {
|
||||
UncalledFunction() {
|
||||
@@ -69,10 +68,7 @@ predicate isNonConst(DataFlow::Node node) {
|
||||
// Parameters of uncalled functions that aren't const
|
||||
exists(UncalledFunction f, Parameter p |
|
||||
f.getAParameter() = p and
|
||||
p = node.asParameter() and
|
||||
// Ignore main's argv parameter as it is already considered a `FlowSource`
|
||||
// not ignoring it will result in path redundancies
|
||||
(f.getName() = "main" implies p != f.getParameter(1))
|
||||
p = node.asParameter()
|
||||
)
|
||||
or
|
||||
// Consider as an input any out arg of a function or a function's return where the function is not:
|
||||
@@ -131,13 +127,11 @@ module NonConstFlowConfig implements DataFlow::ConfigSig {
|
||||
|
||||
module NonConstFlow = TaintTracking::Global<NonConstFlowConfig>;
|
||||
|
||||
from
|
||||
FormattingFunctionCall call, Expr formatString, NonConstFlow::PathNode sink,
|
||||
NonConstFlow::PathNode source
|
||||
from FormattingFunctionCall call, Expr formatString, DataFlow::Node sink
|
||||
where
|
||||
isSinkImpl(sink.getNode(), formatString) and
|
||||
call.getArgument(call.getFormatParameterIndex()) = formatString and
|
||||
NonConstFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"The format string argument to $@ has a source which cannot be " +
|
||||
"verified to originate from a string literal.", call, call.getTarget().getName()
|
||||
NonConstFlow::flowTo(sink) and
|
||||
isSinkImpl(sink, formatString)
|
||||
select formatString,
|
||||
"The format string argument to " + call.getTarget().getName() +
|
||||
" should be constant to prevent security issues and other potential errors."
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
## 0.9.6
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The new C/C++ dataflow and taint-tracking libraries (`semmle.code.cpp.dataflow.new.DataFlow` and `semmle.code.cpp.dataflow.new.TaintTracking`) now implicitly assume that dataflow and taint modelled via `DataFlowFunction` and `TaintFunction` always fully overwrite their buffers and thus act as flow barriers. As a result, many dataflow and taint-tracking queries now produce fewer false positives. To remove this assumption and go back to the previous behavior for a given model, one can override the new `isPartialWrite` predicate.
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.9.7
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.9.7
|
||||
lastReleaseVersion: 0.9.5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.9.7
|
||||
version: 0.9.6-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
| arguments.c | 3 | --edg |
|
||||
| arguments.c | 4 | --disable_system_macros |
|
||||
| arguments.c | 5 | --edg |
|
||||
| arguments.c | 6 | --codeql-verbosity |
|
||||
| arguments.c | 6 | --verbosity |
|
||||
| arguments.c | 7 | --edg |
|
||||
| arguments.c | 8 | 2 |
|
||||
| arguments.c | 9 | --edg |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -605,7 +605,7 @@ struct String {
|
||||
String& operator=(String&&);
|
||||
|
||||
const char* c_str() const;
|
||||
char pop_back();
|
||||
|
||||
private:
|
||||
const char* p;
|
||||
};
|
||||
@@ -2189,146 +2189,4 @@ void static_variable_with_destructor_3() {
|
||||
|
||||
static ClassWithDestructor global_class_with_destructor;
|
||||
|
||||
namespace vacuous_destructor_call {
|
||||
template<typename T>
|
||||
T& get(T& t) { return t; }
|
||||
|
||||
template<typename T>
|
||||
void call_destructor(T& t) {
|
||||
get(t).~T();
|
||||
}
|
||||
|
||||
void non_vacuous_destructor_call() {
|
||||
ClassWithDestructor c;
|
||||
call_destructor(c);
|
||||
}
|
||||
|
||||
void vacuous_destructor_call() {
|
||||
int i;
|
||||
call_destructor(i);
|
||||
}
|
||||
}
|
||||
|
||||
void TryCatchDestructors(bool b) {
|
||||
try {
|
||||
String s;
|
||||
if (b) {
|
||||
throw "string literal";
|
||||
}
|
||||
String s2;
|
||||
}
|
||||
catch (const char* s) {
|
||||
throw String(s);
|
||||
}
|
||||
catch (const String& e) {
|
||||
}
|
||||
catch (...) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void IfDestructors(bool b) {
|
||||
String s1;
|
||||
if(b) {
|
||||
String s2;
|
||||
} else {
|
||||
String s3;
|
||||
}
|
||||
String s4;
|
||||
}
|
||||
|
||||
void ForDestructors() {
|
||||
char c = 'a';
|
||||
for(String s("hello"); c != 0; c = s.pop_back()) {
|
||||
String s2;
|
||||
}
|
||||
|
||||
for(String s : vector<String>(String("hello"))) {
|
||||
String s2;
|
||||
}
|
||||
|
||||
for(String s("hello"), s2("world"); c != 0; c = s.pop_back()) {
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void IfDestructors2(bool b) {
|
||||
if(String s = String("hello"); b) {
|
||||
int x = 0;
|
||||
} else {
|
||||
int y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class Bool {
|
||||
public:
|
||||
Bool(bool b_);
|
||||
operator bool();
|
||||
~Bool();
|
||||
};
|
||||
|
||||
void IfDestructors3(bool b) {
|
||||
if(Bool B = Bool(b)) {
|
||||
String s1;
|
||||
} else {
|
||||
String s2;
|
||||
}
|
||||
}
|
||||
|
||||
void WhileLoopDestructors(bool b) {
|
||||
{
|
||||
String s;
|
||||
while(b) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
while (Bool B = Bool(b)) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoidFunc() {}
|
||||
|
||||
void IfReturnDestructors(bool b) {
|
||||
String s;
|
||||
if(b) {
|
||||
return;
|
||||
}
|
||||
if(b) {
|
||||
return VoidFunc();
|
||||
}
|
||||
s;
|
||||
}
|
||||
|
||||
int IfReturnDestructors3(bool b) {
|
||||
String s;
|
||||
if(b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VoidReturnDestructors() {
|
||||
String s;
|
||||
return VoidFunc();
|
||||
}
|
||||
|
||||
namespace return_routine_type {
|
||||
struct HasVoidToIntFunc
|
||||
{
|
||||
void VoidToInt(int);
|
||||
};
|
||||
|
||||
typedef void (HasVoidToIntFunc::*VoidToIntMemberFunc)(int);
|
||||
|
||||
static VoidToIntMemberFunc GetVoidToIntFunc()
|
||||
{
|
||||
return &HasVoidToIntFunc::VoidToInt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++20 --clang
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,2 @@
|
||||
testFailures
|
||||
failures
|
||||
testFailures
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
| copy.cpp:13:9:13:9 | operator= | protected_cc::Sub2& protected_cc::Sub2::operator=(protected_cc::Sub2 const&) | | |
|
||||
| copy.cpp:13:9:13:9 | operator= | protected_cc::Sub2& protected_cc::Sub2::operator=(protected_cc::Sub2&&) | | |
|
||||
| copy.cpp:17:9:17:9 | HasMember | void protected_cc::HasMember::HasMember() | deleted | |
|
||||
| copy.cpp:17:9:17:9 | HasMember | void protected_cc::HasMember::HasMember(protected_cc::HasMember const&) | deleted | |
|
||||
| copy.cpp:17:9:17:9 | HasMember | void protected_cc::HasMember::HasMember(protected_cc::HasMember const&) | | |
|
||||
| copy.cpp:17:9:17:9 | HasMember | void protected_cc::HasMember::HasMember(protected_cc::HasMember&&) | | |
|
||||
| copy.cpp:17:9:17:9 | operator= | protected_cc::HasMember& protected_cc::HasMember::operator=(protected_cc::HasMember const&) | | |
|
||||
| copy.cpp:17:9:17:9 | operator= | protected_cc::HasMember& protected_cc::HasMember::operator=(protected_cc::HasMember&&) | | |
|
||||
| copy.cpp:25:5:25:5 | C | void deleted_cc::C::C(deleted_cc::C const&) | deleted | |
|
||||
|
||||
@@ -186,6 +186,7 @@
|
||||
| Variable | specifiers2pp.cpp:16:13:16:22 | privateInt | privateInt | private |
|
||||
| Variable | specifiers2pp.cpp:17:21:17:30 | mutableInt | mutableInt | private |
|
||||
| Variable | specifiers2pp.cpp:20:13:20:24 | protectedInt | protectedInt | protected |
|
||||
| Variable | specifiers2pp.cpp:52:25:52:27 | vci | vci | static |
|
||||
| VariableDeclarationEntry | specifiers2.c:5:12:5:12 | declaration of i | i | extern |
|
||||
| VariableDeclarationEntry | specifiers2.c:6:12:6:12 | declaration of i | i | extern |
|
||||
| VariableDeclarationEntry | specifiers2.c:8:12:8:12 | declaration of j | j | extern |
|
||||
|
||||
@@ -7,9 +7,9 @@ missingOperandType
|
||||
duplicateChiOperand
|
||||
sideEffectWithoutPrimary
|
||||
instructionWithoutSuccessor
|
||||
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
|
||||
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
|
||||
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
|
||||
| statements.cpp:25:5:25:9 | ReThrow: re-throw exception | Instruction 'ReThrow: re-throw exception ' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
|
||||
ambiguousSuccessors
|
||||
unexplainedLoop
|
||||
|
||||
@@ -8,11 +8,11 @@ missingOperandType
|
||||
duplicateChiOperand
|
||||
sideEffectWithoutPrimary
|
||||
instructionWithoutSuccessor
|
||||
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
|
||||
| VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x | Instruction 'VariableAddress: x' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
|
||||
| VacuousDestructorCall.cpp:4:3:4:3 | Load: y | Instruction 'Load: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
|
||||
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
|
||||
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
|
||||
| statements.cpp:25:5:25:9 | ReThrow: re-throw exception | Instruction 'ReThrow: re-throw exception ' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
|
||||
| statements.cpp:26:3:26:3 | IndirectMayWriteSideEffect: inner | Instruction 'IndirectMayWriteSideEffect: inner' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
|
||||
| statements.cpp:28:1:28:1 | IndirectMayWriteSideEffect: before | Instruction 'IndirectMayWriteSideEffect: before' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
|
||||
| stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | Instruction 'CopyValue: (statement expression)' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
|
||||
| stmt_in_type.cpp:5:53:5:53 | Constant: 1 | Instruction 'Constant: 1' has no successors in function '$@'. | stmt_in_type.cpp:2:6:2:12 | void cpp_fun() | void cpp_fun() |
|
||||
@@ -30,6 +30,7 @@ multipleIRTypes
|
||||
lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
| VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
|
||||
| ms_try_except.cpp:9:19:9:19 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
|
||||
| ms_try_except.cpp:9:19:9:19 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
|
||||
| ms_try_except.cpp:19:17:19:21 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
|
||||
|
||||
@@ -7,9 +7,9 @@ missingOperandType
|
||||
duplicateChiOperand
|
||||
sideEffectWithoutPrimary
|
||||
instructionWithoutSuccessor
|
||||
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
|
||||
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
|
||||
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
|
||||
| statements.cpp:25:5:25:9 | ReThrow: re-throw exception | Instruction 'ReThrow: re-throw exception ' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
|
||||
ambiguousSuccessors
|
||||
unexplainedLoop
|
||||
|
||||
@@ -1,99 +1,21 @@
|
||||
edges
|
||||
| NonConstantFormat.c:28:27:28:30 | **argv | NonConstantFormat.c:30:10:30:16 | *access to array | provenance | |
|
||||
| NonConstantFormat.c:45:11:45:47 | *call to any_random_function | NonConstantFormat.c:45:9:45:48 | *call to gettext | provenance | |
|
||||
| nested.cpp:19:29:19:32 | *fmt0 | nested.cpp:21:23:21:26 | *fmt0 | provenance | |
|
||||
| nested.cpp:27:32:27:34 | *fmt | nested.cpp:28:16:28:18 | *fmt | provenance | |
|
||||
| nested.cpp:28:16:28:18 | *fmt | nested.cpp:19:29:19:32 | *fmt0 | provenance | |
|
||||
| nested.cpp:34:37:34:39 | *fmt | nested.cpp:35:19:35:21 | *fmt | provenance | |
|
||||
| nested.cpp:35:19:35:21 | *fmt | nested.cpp:27:32:27:34 | *fmt | provenance | |
|
||||
| nested.cpp:42:24:42:34 | *call to ext_fmt_str | nested.cpp:34:37:34:39 | *fmt | provenance | |
|
||||
| nested.cpp:86:19:86:46 | *call to __builtin_alloca | nested.cpp:87:18:87:20 | *fmt | provenance | |
|
||||
| test.cpp:27:39:27:39 | n | test.cpp:27:13:27:24 | **make_message | provenance | |
|
||||
| test.cpp:46:14:46:17 | argc | test.cpp:51:23:51:30 | ... - ... | provenance | |
|
||||
| test.cpp:46:27:46:30 | **argv | test.cpp:130:20:130:26 | *access to array | provenance | |
|
||||
| test.cpp:51:23:51:30 | ... - ... | test.cpp:27:39:27:39 | n | provenance | |
|
||||
| test.cpp:51:23:51:30 | ... - ... | test.cpp:51:10:51:21 | *call to make_message | provenance | |
|
||||
| test.cpp:155:27:155:30 | data | test.cpp:157:12:157:15 | data | provenance | |
|
||||
| test.cpp:167:31:167:34 | data | test.cpp:170:12:170:14 | *res | provenance | |
|
||||
| test.cpp:193:32:193:34 | str | test.cpp:195:31:195:33 | str | provenance | |
|
||||
| test.cpp:193:32:193:34 | str | test.cpp:197:11:197:14 | *wstr | provenance | |
|
||||
| test.cpp:204:25:204:36 | *call to get_string | test.cpp:205:12:205:20 | *... + ... | provenance | |
|
||||
| test.cpp:204:25:204:36 | *call to get_string | test.cpp:206:12:206:16 | *hello | provenance | |
|
||||
| test.cpp:209:25:209:36 | *call to get_string | test.cpp:211:12:211:16 | *hello | provenance | |
|
||||
| test.cpp:215:25:215:36 | *call to get_string | test.cpp:217:12:217:16 | *hello | provenance | |
|
||||
| test.cpp:221:25:221:36 | *call to get_string | test.cpp:223:12:223:16 | *hello | provenance | |
|
||||
| test.cpp:227:25:227:36 | *call to get_string | test.cpp:228:12:228:18 | *++ ... | provenance | |
|
||||
| test.cpp:232:25:232:36 | *call to get_string | test.cpp:235:12:235:16 | *hello | provenance | |
|
||||
| test.cpp:239:25:239:36 | *call to get_string | test.cpp:242:12:242:16 | *hello | provenance | |
|
||||
| test.cpp:245:25:245:36 | *call to get_string | test.cpp:247:12:247:16 | *hello | provenance | |
|
||||
nodes
|
||||
| NonConstantFormat.c:28:27:28:30 | **argv | semmle.label | **argv |
|
||||
| NonConstantFormat.c:30:10:30:16 | *access to array | semmle.label | *access to array |
|
||||
| NonConstantFormat.c:41:9:41:45 | *call to any_random_function | semmle.label | *call to any_random_function |
|
||||
| NonConstantFormat.c:45:9:45:48 | *call to gettext | semmle.label | *call to gettext |
|
||||
| NonConstantFormat.c:45:11:45:47 | *call to any_random_function | semmle.label | *call to any_random_function |
|
||||
| nested.cpp:19:29:19:32 | *fmt0 | semmle.label | *fmt0 |
|
||||
| nested.cpp:21:23:21:26 | *fmt0 | semmle.label | *fmt0 |
|
||||
| nested.cpp:27:32:27:34 | *fmt | semmle.label | *fmt |
|
||||
| nested.cpp:28:16:28:18 | *fmt | semmle.label | *fmt |
|
||||
| nested.cpp:34:37:34:39 | *fmt | semmle.label | *fmt |
|
||||
| nested.cpp:35:19:35:21 | *fmt | semmle.label | *fmt |
|
||||
| nested.cpp:42:24:42:34 | *call to ext_fmt_str | semmle.label | *call to ext_fmt_str |
|
||||
| nested.cpp:79:32:79:38 | *call to get_fmt | semmle.label | *call to get_fmt |
|
||||
| nested.cpp:86:19:86:46 | *call to __builtin_alloca | semmle.label | *call to __builtin_alloca |
|
||||
| nested.cpp:87:18:87:20 | *fmt | semmle.label | *fmt |
|
||||
| test.cpp:27:13:27:24 | **make_message | semmle.label | **make_message |
|
||||
| test.cpp:27:39:27:39 | n | semmle.label | n |
|
||||
| test.cpp:46:14:46:17 | argc | semmle.label | argc |
|
||||
| test.cpp:46:27:46:30 | **argv | semmle.label | **argv |
|
||||
| test.cpp:51:10:51:21 | *call to make_message | semmle.label | *call to make_message |
|
||||
| test.cpp:51:23:51:30 | ... - ... | semmle.label | ... - ... |
|
||||
| test.cpp:130:20:130:26 | *access to array | semmle.label | *access to array |
|
||||
| test.cpp:155:27:155:30 | data | semmle.label | data |
|
||||
| test.cpp:157:12:157:15 | data | semmle.label | data |
|
||||
| test.cpp:167:31:167:34 | data | semmle.label | data |
|
||||
| test.cpp:170:12:170:14 | *res | semmle.label | *res |
|
||||
| test.cpp:193:32:193:34 | str | semmle.label | str |
|
||||
| test.cpp:195:31:195:33 | str | semmle.label | str |
|
||||
| test.cpp:197:11:197:14 | *wstr | semmle.label | *wstr |
|
||||
| test.cpp:204:25:204:36 | *call to get_string | semmle.label | *call to get_string |
|
||||
| test.cpp:205:12:205:20 | *... + ... | semmle.label | *... + ... |
|
||||
| test.cpp:206:12:206:16 | *hello | semmle.label | *hello |
|
||||
| test.cpp:209:25:209:36 | *call to get_string | semmle.label | *call to get_string |
|
||||
| test.cpp:211:12:211:16 | *hello | semmle.label | *hello |
|
||||
| test.cpp:215:25:215:36 | *call to get_string | semmle.label | *call to get_string |
|
||||
| test.cpp:217:12:217:16 | *hello | semmle.label | *hello |
|
||||
| test.cpp:221:25:221:36 | *call to get_string | semmle.label | *call to get_string |
|
||||
| test.cpp:223:12:223:16 | *hello | semmle.label | *hello |
|
||||
| test.cpp:227:25:227:36 | *call to get_string | semmle.label | *call to get_string |
|
||||
| test.cpp:228:12:228:18 | *++ ... | semmle.label | *++ ... |
|
||||
| test.cpp:232:25:232:36 | *call to get_string | semmle.label | *call to get_string |
|
||||
| test.cpp:235:12:235:16 | *hello | semmle.label | *hello |
|
||||
| test.cpp:239:25:239:36 | *call to get_string | semmle.label | *call to get_string |
|
||||
| test.cpp:242:12:242:16 | *hello | semmle.label | *hello |
|
||||
| test.cpp:245:25:245:36 | *call to get_string | semmle.label | *call to get_string |
|
||||
| test.cpp:247:12:247:16 | *hello | semmle.label | *hello |
|
||||
subpaths
|
||||
| test.cpp:51:23:51:30 | ... - ... | test.cpp:27:39:27:39 | n | test.cpp:27:13:27:24 | **make_message | test.cpp:51:10:51:21 | *call to make_message |
|
||||
#select
|
||||
| NonConstantFormat.c:30:10:30:16 | *access to array | NonConstantFormat.c:28:27:28:30 | **argv | NonConstantFormat.c:30:10:30:16 | *access to array | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | NonConstantFormat.c:30:3:30:8 | call to printf | printf |
|
||||
| NonConstantFormat.c:41:9:41:45 | *call to any_random_function | NonConstantFormat.c:41:9:41:45 | *call to any_random_function | NonConstantFormat.c:41:9:41:45 | *call to any_random_function | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | NonConstantFormat.c:41:2:41:7 | call to printf | printf |
|
||||
| NonConstantFormat.c:45:9:45:48 | *call to gettext | NonConstantFormat.c:45:11:45:47 | *call to any_random_function | NonConstantFormat.c:45:9:45:48 | *call to gettext | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | NonConstantFormat.c:45:2:45:7 | call to printf | printf |
|
||||
| nested.cpp:21:23:21:26 | *fmt0 | nested.cpp:42:24:42:34 | *call to ext_fmt_str | nested.cpp:21:23:21:26 | *fmt0 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | nested.cpp:21:5:21:12 | call to snprintf | snprintf |
|
||||
| nested.cpp:79:32:79:38 | *call to get_fmt | nested.cpp:79:32:79:38 | *call to get_fmt | nested.cpp:79:32:79:38 | *call to get_fmt | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | nested.cpp:79:5:79:14 | call to diagnostic | diagnostic |
|
||||
| nested.cpp:87:18:87:20 | *fmt | nested.cpp:86:19:86:46 | *call to __builtin_alloca | nested.cpp:87:18:87:20 | *fmt | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | nested.cpp:87:7:87:16 | call to diagnostic | diagnostic |
|
||||
| test.cpp:51:10:51:21 | *call to make_message | test.cpp:46:14:46:17 | argc | test.cpp:51:10:51:21 | *call to make_message | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:51:3:51:8 | call to printf | printf |
|
||||
| test.cpp:130:20:130:26 | *access to array | test.cpp:46:27:46:30 | **argv | test.cpp:130:20:130:26 | *access to array | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:130:2:130:10 | call to sprintf | sprintf |
|
||||
| test.cpp:157:12:157:15 | data | test.cpp:155:27:155:30 | data | test.cpp:157:12:157:15 | data | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:157:5:157:10 | call to printf | printf |
|
||||
| test.cpp:170:12:170:14 | *res | test.cpp:167:31:167:34 | data | test.cpp:170:12:170:14 | *res | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:170:5:170:10 | call to printf | printf |
|
||||
| test.cpp:195:31:195:33 | str | test.cpp:193:32:193:34 | str | test.cpp:195:31:195:33 | str | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:195:3:195:18 | call to StringCchPrintfW | StringCchPrintfW |
|
||||
| test.cpp:197:11:197:14 | *wstr | test.cpp:193:32:193:34 | str | test.cpp:197:11:197:14 | *wstr | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:197:3:197:9 | call to wprintf | wprintf |
|
||||
| test.cpp:205:12:205:20 | *... + ... | test.cpp:204:25:204:36 | *call to get_string | test.cpp:205:12:205:20 | *... + ... | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:205:5:205:10 | call to printf | printf |
|
||||
| test.cpp:206:12:206:16 | *hello | test.cpp:204:25:204:36 | *call to get_string | test.cpp:206:12:206:16 | *hello | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:206:5:206:10 | call to printf | printf |
|
||||
| test.cpp:211:12:211:16 | *hello | test.cpp:209:25:209:36 | *call to get_string | test.cpp:211:12:211:16 | *hello | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:211:5:211:10 | call to printf | printf |
|
||||
| test.cpp:217:12:217:16 | *hello | test.cpp:215:25:215:36 | *call to get_string | test.cpp:217:12:217:16 | *hello | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:217:5:217:10 | call to printf | printf |
|
||||
| test.cpp:223:12:223:16 | *hello | test.cpp:221:25:221:36 | *call to get_string | test.cpp:223:12:223:16 | *hello | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:223:5:223:10 | call to printf | printf |
|
||||
| test.cpp:228:12:228:18 | *++ ... | test.cpp:227:25:227:36 | *call to get_string | test.cpp:228:12:228:18 | *++ ... | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:228:5:228:10 | call to printf | printf |
|
||||
| test.cpp:235:12:235:16 | *hello | test.cpp:232:25:232:36 | *call to get_string | test.cpp:235:12:235:16 | *hello | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:235:5:235:10 | call to printf | printf |
|
||||
| test.cpp:242:12:242:16 | *hello | test.cpp:239:25:239:36 | *call to get_string | test.cpp:242:12:242:16 | *hello | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:242:5:242:10 | call to printf | printf |
|
||||
| test.cpp:247:12:247:16 | *hello | test.cpp:245:25:245:36 | *call to get_string | test.cpp:247:12:247:16 | *hello | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | test.cpp:247:5:247:10 | call to printf | printf |
|
||||
| NonConstantFormat.c:30:10:30:16 | access to array | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| NonConstantFormat.c:41:9:41:27 | call to any_random_function | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| NonConstantFormat.c:45:9:45:48 | call to gettext | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| nested.cpp:21:23:21:26 | fmt0 | The format string argument to snprintf should be constant to prevent security issues and other potential errors. |
|
||||
| nested.cpp:79:32:79:38 | call to get_fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. |
|
||||
| nested.cpp:87:18:87:20 | fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:51:10:51:21 | call to make_message | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:130:20:130:26 | access to array | The format string argument to sprintf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:157:12:157:15 | data | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:170:12:170:14 | res | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:195:31:195:33 | str | The format string argument to StringCchPrintfW should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:197:11:197:14 | wstr | The format string argument to wprintf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:205:12:205:20 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:206:12:206:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:211:12:211:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:217:12:217:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:223:12:223:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:228:12:228:18 | ++ ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:235:12:235:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:242:12:242:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:247:12:247:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
|
||||
@@ -1,83 +1,14 @@
|
||||
edges
|
||||
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:24:7:24:9 | **gv1 | provenance | |
|
||||
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:29:7:29:25 | **nonConstFuncToArray | provenance | |
|
||||
| consts.cpp:29:7:29:25 | **nonConstFuncToArray | consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | provenance | |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:24:7:24:9 | **gv1 | provenance | |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:86:9:86:10 | *v1 | provenance | |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:95:9:95:10 | *v3 | provenance | |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:100:9:100:10 | *v4 | provenance | |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:116:9:116:13 | *access to array | provenance | |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:121:9:121:10 | *v8 | provenance | |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:130:9:130:10 | *v9 | provenance | |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:135:9:135:11 | *v10 | provenance | |
|
||||
| consts.cpp:90:7:90:10 | *call to gets | consts.cpp:91:9:91:10 | *v2 | provenance | |
|
||||
| consts.cpp:90:7:90:10 | *call to gets | consts.cpp:116:9:116:13 | *access to array | provenance | |
|
||||
| consts.cpp:90:7:90:10 | *call to gets | consts.cpp:121:9:121:10 | *v8 | provenance | |
|
||||
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:24:7:24:9 | **gv1 | provenance | |
|
||||
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:95:9:95:10 | *v3 | provenance | |
|
||||
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:100:9:100:10 | *v4 | provenance | |
|
||||
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:116:9:116:13 | *access to array | provenance | |
|
||||
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:121:9:121:10 | *v8 | provenance | |
|
||||
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:130:9:130:10 | *v9 | provenance | |
|
||||
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:135:9:135:11 | *v10 | provenance | |
|
||||
| consts.cpp:106:13:106:19 | *call to varFunc | consts.cpp:107:9:107:10 | *v5 | provenance | |
|
||||
| consts.cpp:111:7:111:13 | *call to varFunc | consts.cpp:112:9:112:10 | *v6 | provenance | |
|
||||
| consts.cpp:139:13:139:16 | readString output argument | consts.cpp:140:9:140:11 | *v11 | provenance | |
|
||||
| consts.cpp:139:13:139:16 | readString output argument | consts.cpp:140:9:140:11 | v11 | provenance | |
|
||||
| consts.cpp:144:16:144:18 | readStringRef output argument | consts.cpp:145:9:145:11 | *v12 | provenance | |
|
||||
| consts.cpp:144:16:144:18 | readStringRef output argument | consts.cpp:145:9:145:11 | v12 | provenance | |
|
||||
nodes
|
||||
| consts.cpp:24:7:24:9 | **gv1 | semmle.label | **gv1 |
|
||||
| consts.cpp:29:7:29:25 | **nonConstFuncToArray | semmle.label | **nonConstFuncToArray |
|
||||
| consts.cpp:85:7:85:8 | gets output argument | semmle.label | gets output argument |
|
||||
| consts.cpp:86:9:86:10 | *v1 | semmle.label | *v1 |
|
||||
| consts.cpp:90:7:90:10 | *call to gets | semmle.label | *call to gets |
|
||||
| consts.cpp:90:12:90:13 | gets output argument | semmle.label | gets output argument |
|
||||
| consts.cpp:91:9:91:10 | *v2 | semmle.label | *v2 |
|
||||
| consts.cpp:95:9:95:10 | *v3 | semmle.label | *v3 |
|
||||
| consts.cpp:100:9:100:10 | *v4 | semmle.label | *v4 |
|
||||
| consts.cpp:103:9:103:17 | *call to varFunc | semmle.label | *call to varFunc |
|
||||
| consts.cpp:106:13:106:19 | *call to varFunc | semmle.label | *call to varFunc |
|
||||
| consts.cpp:107:9:107:10 | *v5 | semmle.label | *v5 |
|
||||
| consts.cpp:111:7:111:13 | *call to varFunc | semmle.label | *call to varFunc |
|
||||
| consts.cpp:112:9:112:10 | *v6 | semmle.label | *v6 |
|
||||
| consts.cpp:116:9:116:13 | *access to array | semmle.label | *access to array |
|
||||
| consts.cpp:121:9:121:10 | *v8 | semmle.label | *v8 |
|
||||
| consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | semmle.label | *call to nonConstFuncToArray |
|
||||
| consts.cpp:130:9:130:10 | *v9 | semmle.label | *v9 |
|
||||
| consts.cpp:135:9:135:11 | *v10 | semmle.label | *v10 |
|
||||
| consts.cpp:139:13:139:16 | readString output argument | semmle.label | readString output argument |
|
||||
| consts.cpp:139:13:139:16 | readString output argument | semmle.label | readString output argument |
|
||||
| consts.cpp:140:9:140:11 | *v11 | semmle.label | *v11 |
|
||||
| consts.cpp:140:9:140:11 | v11 | semmle.label | v11 |
|
||||
| consts.cpp:144:16:144:18 | readStringRef output argument | semmle.label | readStringRef output argument |
|
||||
| consts.cpp:144:16:144:18 | readStringRef output argument | semmle.label | readStringRef output argument |
|
||||
| consts.cpp:145:9:145:11 | *v12 | semmle.label | *v12 |
|
||||
| consts.cpp:145:9:145:11 | v12 | semmle.label | v12 |
|
||||
subpaths
|
||||
#select
|
||||
| consts.cpp:86:9:86:10 | *v1 | consts.cpp:85:7:85:8 | gets output argument | consts.cpp:86:9:86:10 | *v1 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:86:2:86:7 | call to printf | printf |
|
||||
| consts.cpp:91:9:91:10 | *v2 | consts.cpp:90:7:90:10 | *call to gets | consts.cpp:91:9:91:10 | *v2 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:91:2:91:7 | call to printf | printf |
|
||||
| consts.cpp:95:9:95:10 | *v3 | consts.cpp:85:7:85:8 | gets output argument | consts.cpp:95:9:95:10 | *v3 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:95:2:95:7 | call to printf | printf |
|
||||
| consts.cpp:95:9:95:10 | *v3 | consts.cpp:90:12:90:13 | gets output argument | consts.cpp:95:9:95:10 | *v3 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:95:2:95:7 | call to printf | printf |
|
||||
| consts.cpp:100:9:100:10 | *v4 | consts.cpp:85:7:85:8 | gets output argument | consts.cpp:100:9:100:10 | *v4 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:100:2:100:7 | call to printf | printf |
|
||||
| consts.cpp:100:9:100:10 | *v4 | consts.cpp:90:12:90:13 | gets output argument | consts.cpp:100:9:100:10 | *v4 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:100:2:100:7 | call to printf | printf |
|
||||
| consts.cpp:103:9:103:17 | *call to varFunc | consts.cpp:103:9:103:17 | *call to varFunc | consts.cpp:103:9:103:17 | *call to varFunc | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:103:2:103:7 | call to printf | printf |
|
||||
| consts.cpp:107:9:107:10 | *v5 | consts.cpp:106:13:106:19 | *call to varFunc | consts.cpp:107:9:107:10 | *v5 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:107:2:107:7 | call to printf | printf |
|
||||
| consts.cpp:112:9:112:10 | *v6 | consts.cpp:111:7:111:13 | *call to varFunc | consts.cpp:112:9:112:10 | *v6 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:112:2:112:7 | call to printf | printf |
|
||||
| consts.cpp:116:9:116:13 | *access to array | consts.cpp:85:7:85:8 | gets output argument | consts.cpp:116:9:116:13 | *access to array | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:116:2:116:7 | call to printf | printf |
|
||||
| consts.cpp:116:9:116:13 | *access to array | consts.cpp:90:7:90:10 | *call to gets | consts.cpp:116:9:116:13 | *access to array | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:116:2:116:7 | call to printf | printf |
|
||||
| consts.cpp:116:9:116:13 | *access to array | consts.cpp:90:12:90:13 | gets output argument | consts.cpp:116:9:116:13 | *access to array | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:116:2:116:7 | call to printf | printf |
|
||||
| consts.cpp:121:9:121:10 | *v8 | consts.cpp:85:7:85:8 | gets output argument | consts.cpp:121:9:121:10 | *v8 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:121:2:121:7 | call to printf | printf |
|
||||
| consts.cpp:121:9:121:10 | *v8 | consts.cpp:90:7:90:10 | *call to gets | consts.cpp:121:9:121:10 | *v8 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:121:2:121:7 | call to printf | printf |
|
||||
| consts.cpp:121:9:121:10 | *v8 | consts.cpp:90:12:90:13 | gets output argument | consts.cpp:121:9:121:10 | *v8 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:121:2:121:7 | call to printf | printf |
|
||||
| consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | consts.cpp:85:7:85:8 | gets output argument | consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:126:2:126:7 | call to printf | printf |
|
||||
| consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | consts.cpp:90:12:90:13 | gets output argument | consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:126:2:126:7 | call to printf | printf |
|
||||
| consts.cpp:130:9:130:10 | *v9 | consts.cpp:85:7:85:8 | gets output argument | consts.cpp:130:9:130:10 | *v9 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:130:2:130:7 | call to printf | printf |
|
||||
| consts.cpp:130:9:130:10 | *v9 | consts.cpp:90:12:90:13 | gets output argument | consts.cpp:130:9:130:10 | *v9 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:130:2:130:7 | call to printf | printf |
|
||||
| consts.cpp:135:9:135:11 | *v10 | consts.cpp:85:7:85:8 | gets output argument | consts.cpp:135:9:135:11 | *v10 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:135:2:135:7 | call to printf | printf |
|
||||
| consts.cpp:135:9:135:11 | *v10 | consts.cpp:90:12:90:13 | gets output argument | consts.cpp:135:9:135:11 | *v10 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:135:2:135:7 | call to printf | printf |
|
||||
| consts.cpp:140:9:140:11 | *v11 | consts.cpp:139:13:139:16 | readString output argument | consts.cpp:140:9:140:11 | *v11 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:140:2:140:7 | call to printf | printf |
|
||||
| consts.cpp:140:9:140:11 | v11 | consts.cpp:139:13:139:16 | readString output argument | consts.cpp:140:9:140:11 | v11 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:140:2:140:7 | call to printf | printf |
|
||||
| consts.cpp:145:9:145:11 | *v12 | consts.cpp:144:16:144:18 | readStringRef output argument | consts.cpp:145:9:145:11 | *v12 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:145:2:145:7 | call to printf | printf |
|
||||
| consts.cpp:145:9:145:11 | v12 | consts.cpp:144:16:144:18 | readStringRef output argument | consts.cpp:145:9:145:11 | v12 | The format string argument to $@ has a source which cannot be verified to originate from a string literal. | consts.cpp:145:2:145:7 | call to printf | printf |
|
||||
| consts.cpp:86:9:86:10 | v1 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:91:9:91:10 | v2 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:95:9:95:10 | v3 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:100:9:100:10 | v4 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:103:9:103:15 | call to varFunc | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:107:9:107:10 | v5 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:112:9:112:10 | v6 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:116:9:116:13 | access to array | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:121:9:121:10 | v8 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:126:9:126:27 | call to nonConstFuncToArray | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:130:9:130:10 | v9 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:135:9:135:11 | v10 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:140:9:140:11 | v11 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| consts.cpp:145:9:145:11 | v12 | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
|
||||
@@ -34,10 +34,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semmle.Autobuild.CSharp.Tes
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semmle.Extraction.CSharp.DependencyStubGenerator", "extractor\Semmle.Extraction.CSharp.DependencyStubGenerator\Semmle.Extraction.CSharp.DependencyStubGenerator.csproj", "{0EDA21A3-ADD8-4C10-B494-58B12B526B76}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semmle.Autobuild.Cpp", "..\cpp\autobuilder\Semmle.Autobuild.Cpp\Semmle.Autobuild.Cpp.csproj", "{125C4FB7-34DA-442A-9095-3EA1514270CD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semmle.Autobuild.Cpp.Tests", "..\cpp\autobuilder\Semmle.Autobuild.Cpp.Tests\Semmle.Autobuild.Cpp.Tests.csproj", "{72F369B7-0707-401A-802F-D526F272F9EE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -106,14 +102,6 @@ Global
|
||||
{0EDA21A3-ADD8-4C10-B494-58B12B526B76}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0EDA21A3-ADD8-4C10-B494-58B12B526B76}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0EDA21A3-ADD8-4C10-B494-58B12B526B76}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{125C4FB7-34DA-442A-9095-3EA1514270CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{125C4FB7-34DA-442A-9095-3EA1514270CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{125C4FB7-34DA-442A-9095-3EA1514270CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{125C4FB7-34DA-442A-9095-3EA1514270CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{72F369B7-0707-401A-802F-D526F272F9EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72F369B7-0707-401A-802F-D526F272F9EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72F369B7-0707-401A-802F-D526F272F9EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72F369B7-0707-401A-802F-D526F272F9EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -970,10 +970,12 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
actions.RunProcess["dotnet --list-sdks"] = 0;
|
||||
actions.RunProcessOut["dotnet --list-sdks"] = @"2.1.3 [C:\Program Files\dotnet\sdks]
|
||||
2.1.4 [C:\Program Files\dotnet\sdks]";
|
||||
actions.RunProcess[@"dotnet --info"] = 0;
|
||||
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
|
||||
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
|
||||
actions.RunProcess[@"dotnet build --no-incremental C:\Project/test.csproj"] = 0;
|
||||
actions.RunProcess[@"chmod u+x scratch/.dotnet/dotnet-install.sh"] = 0;
|
||||
actions.RunProcess[@"scratch/.dotnet/dotnet-install.sh --channel release --version 2.1.3 --install-dir scratch/.dotnet"] = 0;
|
||||
actions.RunProcess[@"scratch/.dotnet/dotnet --info"] = 0;
|
||||
actions.RunProcess[@"scratch/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
|
||||
actions.RunProcess[@"scratch/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
|
||||
actions.RunProcess[@"scratch/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
|
||||
actions.FileExists["csharp.log"] = true;
|
||||
actions.FileExists["test.csproj"] = true;
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
@@ -991,15 +993,17 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
|
||||
</Project>");
|
||||
actions.LoadXml[@"C:\Project/test.csproj"] = xml;
|
||||
actions.DownloadFiles.Add(("https://dot.net/v1/dotnet-install.sh", "scratch/.dotnet/dotnet-install.sh"));
|
||||
actions.CreateDirectories.Add(@"scratch/.dotnet");
|
||||
|
||||
var autobuilder = CreateAutoBuilder(false, dotnetVersion: "2.1.3");
|
||||
TestAutobuilderScript(autobuilder, 0, 5);
|
||||
TestAutobuilderScript(autobuilder, 0, 7);
|
||||
}
|
||||
|
||||
private void TestDotnetVersionWindows(Action action, int commandsRun)
|
||||
{
|
||||
actions.RunProcess["cmd.exe /C dotnet --list-sdks"] = 0;
|
||||
actions.RunProcessOut["cmd.exe /C dotnet --list-sdks"] = "2.1.4 [C:\\Program Files\\dotnet\\sdks]";
|
||||
actions.RunProcessOut["cmd.exe /C dotnet --list-sdks"] = "2.1.3 [C:\\Program Files\\dotnet\\sdks]\n2.1.4 [C:\\Program Files\\dotnet\\sdks]";
|
||||
action();
|
||||
actions.RunProcess[@"cmd.exe /C scratch\.dotnet\dotnet --info"] = 0;
|
||||
actions.RunProcess[@"cmd.exe /C scratch\.dotnet\dotnet clean C:\Project\test.csproj"] = 0;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Semmle.Autobuild.Shared;
|
||||
using Semmle.Extraction.CSharp;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Autobuild.CSharp
|
||||
{
|
||||
|
||||
@@ -50,8 +50,11 @@ namespace Semmle.Autobuild.CSharp
|
||||
attempt = new BuildCommandRule(DotNetRule.WithDotNet).Analyse(this, false) & CheckExtractorRun(true);
|
||||
break;
|
||||
case CSharpBuildStrategy.Buildless:
|
||||
// No need to check that the extractor has been executed in buildless mode
|
||||
attempt = new StandaloneBuildRule().Analyse(this, false);
|
||||
attempt = DotNetRule.WithDotNet(this, (dotNetPath, env) =>
|
||||
{
|
||||
// No need to check that the extractor has been executed in buildless mode
|
||||
return new StandaloneBuildRule(dotNetPath).Analyse(this, false);
|
||||
});
|
||||
break;
|
||||
case CSharpBuildStrategy.MSBuild:
|
||||
attempt = new MsBuildRule().Analyse(this, false) & CheckExtractorRun(true);
|
||||
@@ -81,7 +84,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
return 0;
|
||||
|
||||
if (warnOnFailure)
|
||||
Logger.LogError("No C# code detected during build.");
|
||||
Log(Severity.Error, "No C# code detected during build.");
|
||||
|
||||
return 1;
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using Semmle.Util;
|
||||
using Semmle.Util.Logging;
|
||||
using Semmle.Autobuild.Shared;
|
||||
using Semmle.Extraction.CSharp.DependencyFetching;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Semmle.Autobuild.CSharp
|
||||
{
|
||||
@@ -39,14 +39,14 @@ namespace Semmle.Autobuild.CSharp
|
||||
|
||||
if (notDotNetProject is not null)
|
||||
{
|
||||
builder.Logger.Log(Severity.Info, "Not using .NET Core because of incompatible project {0}", notDotNetProject);
|
||||
builder.Log(Severity.Info, "Not using .NET Core because of incompatible project {0}", notDotNetProject);
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
|
||||
builder.Logger.LogInfo("Attempting to build using .NET Core");
|
||||
builder.Log(Severity.Info, "Attempting to build using .NET Core");
|
||||
}
|
||||
|
||||
return WithDotNet(builder, ensureDotNetAvailable: false, (dotNetPath, environment) =>
|
||||
return WithDotNet(builder, (dotNetPath, environment) =>
|
||||
{
|
||||
var ret = GetInfoCommand(builder.Actions, dotNetPath, environment);
|
||||
foreach (var projectOrSolution in builder.ProjectsOrSolutionsToBuild)
|
||||
@@ -79,24 +79,31 @@ namespace Semmle.Autobuild.CSharp
|
||||
/// variables needed by the installed .NET Core (<code>null</code> when no variables
|
||||
/// are needed).
|
||||
/// </summary>
|
||||
public static BuildScript WithDotNet(IAutobuilder<AutobuildOptionsShared> builder, bool ensureDotNetAvailable, Func<string?, IDictionary<string, string>?, BuildScript> f)
|
||||
public static BuildScript WithDotNet(IAutobuilder<AutobuildOptionsShared> builder, Func<string?, IDictionary<string, string>?, BuildScript> f)
|
||||
{
|
||||
var temp = FileUtils.GetTemporaryWorkingDirectory(builder.Actions.GetEnvironmentVariable, builder.Options.Language.UpperCaseName, out var shouldCleanUp);
|
||||
return DotNet.WithDotNet(builder.Actions, builder.Logger, builder.Paths.Select(x => x.Item1), temp, shouldCleanUp, ensureDotNetAvailable, builder.Options.DotNetVersion, installDir =>
|
||||
var installDir = builder.Actions.PathCombine(FileUtils.GetTemporaryWorkingDirectory(builder.Actions.GetEnvironmentVariable, builder.Options.Language.UpperCaseName, out var _), ".dotnet");
|
||||
var installScript = DownloadDotNet(builder, installDir);
|
||||
return BuildScript.Bind(installScript, installed =>
|
||||
{
|
||||
var env = new Dictionary<string, string>
|
||||
Dictionary<string, string>? env;
|
||||
if (installed == 0)
|
||||
{
|
||||
{ "DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "true" },
|
||||
{ "MSBUILDDISABLENODEREUSE", "1" }
|
||||
};
|
||||
if (installDir is not null)
|
||||
{
|
||||
// The installation succeeded, so use the newly installed .NET
|
||||
// The installation succeeded, so use the newly installed .NET Core
|
||||
var path = builder.Actions.GetEnvironmentVariable("PATH");
|
||||
var delim = builder.Actions.IsWindows() ? ";" : ":";
|
||||
env.Add("DOTNET_MULTILEVEL_LOOKUP", "false"); // prevent look up of other .NET SDKs
|
||||
env.Add("PATH", installDir + delim + path);
|
||||
env = new Dictionary<string, string>{
|
||||
{ "DOTNET_MULTILEVEL_LOOKUP", "false" }, // prevent look up of other .NET Core SDKs
|
||||
{ "DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "true" },
|
||||
{ "MSBUILDDISABLENODEREUSE", "1" },
|
||||
{ "PATH", installDir + delim + path }
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
installDir = null;
|
||||
env = null;
|
||||
}
|
||||
|
||||
return f(installDir, env);
|
||||
});
|
||||
}
|
||||
@@ -110,7 +117,126 @@ namespace Semmle.Autobuild.CSharp
|
||||
/// are needed).
|
||||
/// </summary>
|
||||
public static BuildScript WithDotNet(IAutobuilder<AutobuildOptionsShared> builder, Func<IDictionary<string, string>?, BuildScript> f)
|
||||
=> WithDotNet(builder, ensureDotNetAvailable: false, (_, env) => f(env));
|
||||
=> WithDotNet(builder, (_1, env) => f(env));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script for downloading relevant versions of the
|
||||
/// .NET Core SDK. The SDK(s) will be installed at <code>installDir</code>
|
||||
/// (provided that the script succeeds).
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNet(IAutobuilder<AutobuildOptionsShared> builder, string installDir)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(builder.Options.DotNetVersion))
|
||||
// Specific version supplied in configuration: always use that
|
||||
return DownloadDotNetVersion(builder, installDir, builder.Options.DotNetVersion);
|
||||
|
||||
// Download versions mentioned in `global.json` files
|
||||
// See https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
|
||||
var installScript = BuildScript.Success;
|
||||
var validGlobalJson = false;
|
||||
foreach (var path in builder.Paths.Select(p => p.Item1).Where(p => p.EndsWith("global.json", StringComparison.Ordinal)))
|
||||
{
|
||||
string version;
|
||||
try
|
||||
{
|
||||
var o = JObject.Parse(File.ReadAllText(path));
|
||||
version = (string)(o?["sdk"]?["version"]!);
|
||||
}
|
||||
catch // lgtm[cs/catch-of-all-exceptions]
|
||||
{
|
||||
// not a valid global.json file
|
||||
continue;
|
||||
}
|
||||
|
||||
installScript &= DownloadDotNetVersion(builder, installDir, version);
|
||||
validGlobalJson = true;
|
||||
}
|
||||
|
||||
return validGlobalJson ? installScript : BuildScript.Failure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script for downloading a specific .NET Core SDK version, if the
|
||||
/// version is not already installed.
|
||||
///
|
||||
/// See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script.
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNetVersion(IAutobuilder<AutobuildOptionsShared> builder, string path, string version)
|
||||
{
|
||||
return BuildScript.Bind(GetInstalledSdksScript(builder.Actions), (sdks, sdksRet) =>
|
||||
{
|
||||
if (sdksRet == 0 && sdks.Count == 1 && sdks[0].StartsWith(version + " ", StringComparison.Ordinal))
|
||||
// The requested SDK is already installed (and no other SDKs are installed), so
|
||||
// no need to reinstall
|
||||
return BuildScript.Failure;
|
||||
|
||||
builder.Log(Severity.Info, "Attempting to download .NET Core {0}", version);
|
||||
|
||||
if (builder.Actions.IsWindows())
|
||||
{
|
||||
|
||||
var psCommand = $"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version {version} -InstallDir {path}";
|
||||
|
||||
BuildScript GetInstall(string pwsh) =>
|
||||
new CommandBuilder(builder.Actions).
|
||||
RunCommand(pwsh).
|
||||
Argument("-NoProfile").
|
||||
Argument("-ExecutionPolicy").
|
||||
Argument("unrestricted").
|
||||
Argument("-Command").
|
||||
Argument("\"" + psCommand + "\"").
|
||||
Script;
|
||||
|
||||
return GetInstall("pwsh") | GetInstall("powershell");
|
||||
}
|
||||
else
|
||||
{
|
||||
var dotnetInstallPath = builder.Actions.PathCombine(FileUtils.GetTemporaryWorkingDirectory(
|
||||
builder.Actions.GetEnvironmentVariable,
|
||||
builder.Options.Language.UpperCaseName,
|
||||
out var shouldCleanUp), ".dotnet", "dotnet-install.sh");
|
||||
|
||||
var downloadDotNetInstallSh = BuildScript.DownloadFile(
|
||||
"https://dot.net/v1/dotnet-install.sh",
|
||||
dotnetInstallPath,
|
||||
e => builder.Log(Severity.Warning, $"Failed to download 'dotnet-install.sh': {e.Message}"));
|
||||
|
||||
var chmod = new CommandBuilder(builder.Actions).
|
||||
RunCommand("chmod").
|
||||
Argument("u+x").
|
||||
Argument(dotnetInstallPath);
|
||||
|
||||
var install = new CommandBuilder(builder.Actions).
|
||||
RunCommand(dotnetInstallPath).
|
||||
Argument("--channel").
|
||||
Argument("release").
|
||||
Argument("--version").
|
||||
Argument(version).
|
||||
Argument("--install-dir").
|
||||
Argument(path);
|
||||
|
||||
var buildScript = downloadDotNetInstallSh & chmod.Script & install.Script;
|
||||
|
||||
if (shouldCleanUp)
|
||||
{
|
||||
var removeScript = new CommandBuilder(builder.Actions).
|
||||
RunCommand("rm").
|
||||
Argument(dotnetInstallPath);
|
||||
buildScript &= removeScript.Script;
|
||||
}
|
||||
|
||||
return buildScript;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static BuildScript GetInstalledSdksScript(IBuildActions actions)
|
||||
{
|
||||
var listSdks = new CommandBuilder(actions, silent: true).
|
||||
RunCommand("dotnet").
|
||||
Argument("--list-sdks");
|
||||
return listSdks.Script;
|
||||
}
|
||||
|
||||
private static string DotNetCommand(IBuildActions actions, string? dotNetPath) =>
|
||||
dotNetPath is not null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet";
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Semmle.Autobuild.Shared;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Autobuild.CSharp
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Util\Semmle.Util.csproj" />
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj" />
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Extraction.CSharp.DependencyFetching\Semmle.Extraction.CSharp.DependencyFetching.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Autobuild.Shared\Semmle.Autobuild.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Semmle.Autobuild.Shared;
|
||||
using Semmle.Util;
|
||||
using System.Linq;
|
||||
using Semmle.Autobuild.Shared;
|
||||
|
||||
namespace Semmle.Autobuild.CSharp
|
||||
{
|
||||
@@ -8,19 +8,45 @@ namespace Semmle.Autobuild.CSharp
|
||||
/// </summary>
|
||||
internal class StandaloneBuildRule : IBuildRule<CSharpAutobuildOptions>
|
||||
{
|
||||
private readonly string? dotNetPath;
|
||||
|
||||
internal StandaloneBuildRule(string? dotNetPath)
|
||||
{
|
||||
this.dotNetPath = dotNetPath;
|
||||
}
|
||||
|
||||
public BuildScript Analyse(IAutobuilder<CSharpAutobuildOptions> builder, bool auto)
|
||||
{
|
||||
if (builder.CodeQLExtractorLangRoot is null
|
||||
|| builder.CodeQlPlatform is null)
|
||||
BuildScript GetCommand()
|
||||
{
|
||||
string standalone;
|
||||
if (builder.CodeQLExtractorLangRoot is not null && builder.CodeQlPlatform is not null)
|
||||
{
|
||||
standalone = builder.Actions.PathCombine(builder.CodeQLExtractorLangRoot, "tools", builder.CodeQlPlatform, "Semmle.Extraction.CSharp.Standalone");
|
||||
}
|
||||
else
|
||||
{
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
|
||||
var cmd = new CommandBuilder(builder.Actions);
|
||||
cmd.RunCommand(standalone);
|
||||
|
||||
if (!string.IsNullOrEmpty(this.dotNetPath))
|
||||
{
|
||||
cmd.Argument("--dotnet");
|
||||
cmd.QuoteArgument(this.dotNetPath);
|
||||
}
|
||||
|
||||
return cmd.Script;
|
||||
}
|
||||
|
||||
if (!builder.Options.Buildless)
|
||||
{
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
|
||||
var standalone = builder.Actions.PathCombine(builder.CodeQLExtractorLangRoot, "tools", builder.CodeQlPlatform, "Semmle.Extraction.CSharp.Standalone");
|
||||
var cmd = new CommandBuilder(builder.Actions);
|
||||
cmd.RunCommand(standalone);
|
||||
|
||||
return cmd.Script;
|
||||
return GetCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,9 +70,11 @@ namespace Semmle.Autobuild.Shared
|
||||
IBuildActions Actions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A logger.
|
||||
/// Log a given build event to the console.
|
||||
/// </summary>
|
||||
ILogger Logger { get; }
|
||||
/// <param name="format">The format string.</param>
|
||||
/// <param name="args">Inserts to the format string.</param>
|
||||
void Log(Severity severity, string format, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Value of CODEQL_EXTRACTOR_<LANG>_ROOT environment variable.
|
||||
@@ -133,7 +135,21 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <returns>True iff the path was found.</returns>
|
||||
public bool HasPath(string path) => Paths.Any(p => path == p.Item1);
|
||||
|
||||
private void FindFiles(string dir, int depth, int maxDepth, IList<(string, int)> results)
|
||||
{
|
||||
foreach (var f in Actions.EnumerateFiles(dir))
|
||||
{
|
||||
results.Add((f, depth));
|
||||
}
|
||||
|
||||
if (depth < maxDepth)
|
||||
{
|
||||
foreach (var d in Actions.EnumerateDirectories(dir))
|
||||
{
|
||||
FindFiles(d, depth + 1, maxDepth, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The root of the source directory.
|
||||
@@ -180,7 +196,12 @@ namespace Semmle.Autobuild.Shared
|
||||
Options = options;
|
||||
DiagnosticClassifier = diagnosticClassifier;
|
||||
|
||||
pathsLazy = new Lazy<IEnumerable<(string, int)>>(() => Actions.FindFiles(options.RootDirectory, options.SearchDepth));
|
||||
pathsLazy = new Lazy<IEnumerable<(string, int)>>(() =>
|
||||
{
|
||||
var files = new List<(string, int)>();
|
||||
FindFiles(options.RootDirectory, 0, options.SearchDepth, files);
|
||||
return files.OrderBy(f => f.Item2).ToArray();
|
||||
});
|
||||
|
||||
projectsOrSolutionsToBuildLazy = new Lazy<IList<IProjectOrSolution>>(() =>
|
||||
{
|
||||
@@ -193,7 +214,7 @@ namespace Semmle.Autobuild.Shared
|
||||
if (actions.FileExists(solution))
|
||||
ret.Add(new Solution<TAutobuildOptions>(this, solution, true));
|
||||
else
|
||||
logger.LogError($"The specified project or solution file {solution} was not found");
|
||||
Log(Severity.Error, $"The specified project or solution file {solution} was not found");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -252,8 +273,6 @@ namespace Semmle.Autobuild.Shared
|
||||
logThreadId: false) ?? Verbosity.Info,
|
||||
logThreadId: false);
|
||||
|
||||
public ILogger Logger => logger;
|
||||
|
||||
private readonly IDiagnosticsWriter diagnostics;
|
||||
|
||||
/// <summary>
|
||||
@@ -266,6 +285,16 @@ namespace Semmle.Autobuild.Shared
|
||||
return Path.GetRelativePath(this.RootDirectory, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a given build event to the console.
|
||||
/// </summary>
|
||||
/// <param name="format">The format string.</param>
|
||||
/// <param name="args">Inserts to the format string.</param>
|
||||
public void Log(Severity severity, string format, params object[] args)
|
||||
{
|
||||
logger.Log(severity, format, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write <paramref name="diagnostic"/> to the diagnostics file.
|
||||
/// </summary>
|
||||
@@ -281,7 +310,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <returns>The exit code, 0 for success and non-zero for failures.</returns>
|
||||
public int AttemptBuild()
|
||||
{
|
||||
logger.LogInfo($"Working directory: {Options.RootDirectory}");
|
||||
Log(Severity.Info, $"Working directory: {Options.RootDirectory}");
|
||||
|
||||
var script = GetBuildScript();
|
||||
|
||||
@@ -290,12 +319,12 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
void startCallback(string s, bool silent)
|
||||
{
|
||||
logger.Log(silent ? Severity.Debug : Severity.Info, $"\nRunning {s}");
|
||||
Log(silent ? Severity.Debug : Severity.Info, $"\nRunning {s}");
|
||||
}
|
||||
|
||||
void exitCallback(int ret, string msg, bool silent)
|
||||
{
|
||||
logger.Log(silent ? Severity.Debug : Severity.Info, $"Exit code {ret}{(string.IsNullOrEmpty(msg) ? "" : $": {msg}")}");
|
||||
Log(silent ? Severity.Debug : Severity.Info, $"Exit code {ret}{(string.IsNullOrEmpty(msg) ? "" : $": {msg}")}");
|
||||
}
|
||||
|
||||
var onOutput = BuildOutputHandler(Console.Out);
|
||||
@@ -345,7 +374,7 @@ namespace Semmle.Autobuild.Shared
|
||||
protected BuildScript AutobuildFailure() =>
|
||||
BuildScript.Create(actions =>
|
||||
{
|
||||
logger.LogError("Could not auto-detect a suitable build method");
|
||||
Log(Severity.Error, "Could not auto-detect a suitable build method");
|
||||
|
||||
AutobuildFailureDiagnostic();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
|
||||
using System.Xml;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Util
|
||||
namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
public delegate void BuildOutputHandler(string? data);
|
||||
|
||||
@@ -287,30 +287,4 @@ namespace Semmle.Util
|
||||
|
||||
public static IBuildActions Instance { get; } = new SystemBuildActions();
|
||||
}
|
||||
|
||||
public static class BuildActionExtensions
|
||||
{
|
||||
private static void FindFiles(this IBuildActions actions, string dir, int depth, int? maxDepth, IList<(string, int)> results)
|
||||
{
|
||||
foreach (var f in actions.EnumerateFiles(dir))
|
||||
{
|
||||
results.Add((f, depth));
|
||||
}
|
||||
|
||||
if (depth < maxDepth)
|
||||
{
|
||||
foreach (var d in actions.EnumerateDirectories(dir))
|
||||
{
|
||||
actions.FindFiles(d, depth + 1, maxDepth, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static (string path, int depth)[] FindFiles(this IBuildActions actions, string dir, int? maxDepth)
|
||||
{
|
||||
var results = new List<(string, int)>();
|
||||
actions.FindFiles(dir, 0, maxDepth, results);
|
||||
return results.OrderBy(f => f.Item2).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Semmle.Util;
|
||||
using Semmle.Util.Logging;
|
||||
|
||||
namespace Semmle.Autobuild.Shared
|
||||
@@ -55,7 +53,7 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
public BuildScript Analyse(IAutobuilder<AutobuildOptionsShared> builder, bool auto)
|
||||
{
|
||||
builder.Logger.LogInfo("Attempting to locate build script");
|
||||
builder.Log(Severity.Info, "Attempting to locate build script");
|
||||
|
||||
// a list of extensions for files that we consider to be scripts on the current platform
|
||||
var extensions = builder.Actions.IsWindows() ? winExtensions : linuxExtensions;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Autobuild.Shared
|
||||
namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute the build_command rule.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Util
|
||||
namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// A build script.
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Semmle.Util
|
||||
namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility to construct a build command.
|
||||
@@ -40,7 +40,7 @@ namespace Semmle.Autobuild.Shared
|
||||
return BuildScript.Failure;
|
||||
|
||||
if (auto)
|
||||
builder.Logger.LogInfo("Attempting to build using MSBuild");
|
||||
builder.Log(Severity.Info, "Attempting to build using MSBuild");
|
||||
|
||||
var vsTools = GetVcVarsBatFile(builder);
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
if (vsTools is null && builder.Actions.IsWindows())
|
||||
{
|
||||
builder.Logger.LogWarning("Could not find a suitable version of VsDevCmd.bat/vcvarsall.bat");
|
||||
builder.Log(Severity.Warning, "Could not find a suitable version of VsDevCmd.bat/vcvarsall.bat");
|
||||
}
|
||||
|
||||
// Use `nuget.exe` from source code repo, if present, otherwise first attempt with global
|
||||
@@ -165,18 +165,18 @@ namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
foreach (var b in BuildTools.VcVarsAllBatFiles(builder.Actions))
|
||||
{
|
||||
builder.Logger.Log(Severity.Info, "Found {0} version {1}", b.Path, b.ToolsVersion);
|
||||
builder.Log(Severity.Info, "Found {0} version {1}", b.Path, b.ToolsVersion);
|
||||
}
|
||||
|
||||
vsTools = BuildTools.FindCompatibleVcVars(builder.Actions, msToolsVersion);
|
||||
if (vsTools is null)
|
||||
builder.Logger.LogWarning("Could not find build tools matching version {0}", msToolsVersion);
|
||||
builder.Log(Severity.Warning, "Could not find build tools matching version {0}", msToolsVersion);
|
||||
else
|
||||
builder.Logger.Log(Severity.Info, "Setting Visual Studio tools to {0}", vsTools.Path);
|
||||
builder.Log(Severity.Info, "Setting Visual Studio tools to {0}", vsTools.Path);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Logger.LogError("The format of vstools_version is incorrect. Please specify an integer.");
|
||||
builder.Log(Severity.Error, "The format of vstools_version is incorrect. Please specify an integer.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,18 +189,18 @@ namespace Semmle.Autobuild.Shared
|
||||
private static BuildScript DownloadNugetExe<TAutobuildOptions>(IAutobuilder<TAutobuildOptions> builder, string path) where TAutobuildOptions : AutobuildOptionsShared =>
|
||||
BuildScript.Create(_ =>
|
||||
{
|
||||
builder.Logger.LogInfo("Attempting to download nuget.exe");
|
||||
builder.Log(Severity.Info, "Attempting to download nuget.exe");
|
||||
return 0;
|
||||
})
|
||||
&
|
||||
BuildScript.DownloadFile(
|
||||
FileUtils.NugetExeUrl,
|
||||
path,
|
||||
e => builder.Logger.LogWarning($"Failed to download 'nuget.exe': {e.Message}"))
|
||||
e => builder.Log(Severity.Warning, $"Failed to download 'nuget.exe': {e.Message}"))
|
||||
&
|
||||
BuildScript.Create(_ =>
|
||||
{
|
||||
builder.Logger.LogInfo($"Successfully downloaded {path}");
|
||||
builder.Log(Severity.Info, $"Successfully downloaded {path}");
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Semmle.Autobuild.Shared
|
||||
}
|
||||
catch (Exception ex) when (ex is XmlException || ex is FileNotFoundException)
|
||||
{
|
||||
builder.Logger.LogInfo($"Unable to read project file {path}.");
|
||||
builder.Log(Severity.Info, $"Unable to read project file {path}.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Semmle.Autobuild.Shared
|
||||
catch // lgtm[cs/catch-of-all-exceptions]
|
||||
// Generic catch clause - Version constructor throws about 5 different exceptions.
|
||||
{
|
||||
builder.Logger.Log(Severity.Warning, "Project {0} has invalid tools version {1}", path, toolsVersion);
|
||||
builder.Log(Severity.Warning, "Project {0} has invalid tools version {1}", path, toolsVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Semmle.Autobuild.Shared
|
||||
return;
|
||||
}
|
||||
|
||||
builder.Logger.LogInfo($"Unable to read solution file {path}.");
|
||||
builder.Log(Severity.Info, $"Unable to read solution file {path}.");
|
||||
includedProjects = Array.Empty<Project<TAutobuildOptions>>();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ extra_env_vars:
|
||||
build_modes:
|
||||
- autobuild
|
||||
- manual
|
||||
- none
|
||||
github_api_languages:
|
||||
- C#
|
||||
scc_languages:
|
||||
@@ -34,10 +33,8 @@ options:
|
||||
type: string
|
||||
pattern: "^(none|gzip|brotli)$"
|
||||
buildless:
|
||||
title: DEPRECATED - Whether to use buildless (standalone) extraction.
|
||||
title: Whether to use buildless (standalone) extraction.
|
||||
description: >
|
||||
DEPRECATED: Use `--build-mode none` instead.
|
||||
|
||||
A value indicating, which type of extraction the autobuilder should perform.
|
||||
If 'true', then the standalone extractor will be used, otherwise tracing extraction
|
||||
will be performed.
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
class Modifiable extends @modifiable {
|
||||
Modifiable() { compiler_generated(this) }
|
||||
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
select any(Modifiable m)
|
||||
@@ -1,7 +0,0 @@
|
||||
class Expression extends @expr {
|
||||
Expression() { compiler_generated(this) }
|
||||
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
select any(Expression e)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
description: Split `compiler_generated` into `expr_compiler_generated` and `compiler_generated`.
|
||||
compatibility: backwards
|
||||
compiler_generated.rel: run compiler_generated.qlo
|
||||
expr_compiler_generated.rel: run expr_compiler_generated.qlo
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
class Parameter extends @parameter {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class TypeOrRef extends @type_or_ref {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Parameterizable extends @parameterizable {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from
|
||||
Parameter p, string name, TypeOrRef typeId, int index, int mode, Parameterizable parentId,
|
||||
Parameter unboundId, int updatedMode
|
||||
where
|
||||
params(p, name, typeId, index, mode, parentId, unboundId) and
|
||||
if mode = 6 then updatedMode = 0 else updatedMode = mode
|
||||
select p, name, typeId, index, updatedMode, parentId, unboundId
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
description: Extract `ref readonly` parameters as having `mode` 0 in the params table.
|
||||
compatibility: full
|
||||
params.rel: run params.qlo
|
||||
@@ -46,7 +46,7 @@ namespace Semmle.Extraction.CIL.Driver
|
||||
.ToArray();
|
||||
|
||||
foreach (var missingRef in options.MissingReferences)
|
||||
logger.LogInfo(" Missing assembly " + missingRef);
|
||||
logger.Log(Severity.Info, " Missing assembly " + missingRef);
|
||||
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Semmle.Extraction.CIL
|
||||
}
|
||||
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
|
||||
{
|
||||
logger.LogError(string.Format("Exception extracting {0}: {1}", assemblyPath, ex));
|
||||
logger.Log(Severity.Error, string.Format("Exception extracting {0}: {1}", assemblyPath, ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Semmle.Util;
|
||||
using Semmle.Util.Logging;
|
||||
|
||||
@@ -28,8 +27,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
private readonly List<string> generatedSources;
|
||||
private int dotnetFrameworkVersionVariantCount = 0;
|
||||
private int conflictedReferences = 0;
|
||||
private readonly IDependencyOptions options;
|
||||
private readonly DirectoryInfo sourceDir;
|
||||
private string? dotnetPath;
|
||||
private readonly IDotNet dotnet;
|
||||
private readonly FileContent fileContent;
|
||||
private readonly TemporaryDirectory packageDirectory;
|
||||
@@ -40,17 +39,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
private readonly Lazy<Runtime> runtimeLazy;
|
||||
private Runtime Runtime => runtimeLazy.Value;
|
||||
private readonly int threads = EnvironmentVariables.GetDefaultNumberOfThreads();
|
||||
|
||||
/// <summary>
|
||||
/// Performs C# dependency fetching.
|
||||
/// </summary>
|
||||
/// <param name="options">Dependency fetching options</param>
|
||||
/// <param name="logger">Logger for dependency fetching progress.</param>
|
||||
public DependencyManager(string srcDir, ILogger logger)
|
||||
public DependencyManager(string srcDir, IDependencyOptions options, ILogger logger)
|
||||
{
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
this.options = options;
|
||||
this.logger = logger;
|
||||
this.sourceDir = new DirectoryInfo(srcDir);
|
||||
|
||||
@@ -60,6 +59,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
tempWorkingDirectory = new TemporaryDirectory(FileUtils.GetTemporaryWorkingDirectory(out cleanupTempWorkingDirectory));
|
||||
|
||||
try
|
||||
{
|
||||
this.dotnet = DotNet.Make(options, logger, tempWorkingDirectory);
|
||||
runtimeLazy = new Lazy<Runtime>(() => new Runtime(dotnet, logger));
|
||||
}
|
||||
catch
|
||||
{
|
||||
logger.LogError("Missing dotnet CLI");
|
||||
throw;
|
||||
}
|
||||
|
||||
logger.LogInfo($"Finding files in {srcDir}...");
|
||||
|
||||
var allFiles = GetAllFiles().ToList();
|
||||
@@ -75,33 +85,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
logger.LogInfo($"Found {allFiles.Count} files, {nonGeneratedSources.Count} source files, {allProjects.Count} project files, {allSolutions.Count} solution files, {dllPaths.Count} DLLs.");
|
||||
|
||||
void startCallback(string s, bool silent)
|
||||
{
|
||||
logger.Log(silent ? Severity.Debug : Severity.Info, $"\nRunning {s}");
|
||||
}
|
||||
|
||||
void exitCallback(int ret, string msg, bool silent)
|
||||
{
|
||||
logger.Log(silent ? Severity.Debug : Severity.Info, $"Exit code {ret}{(string.IsNullOrEmpty(msg) ? "" : $": {msg}")}");
|
||||
}
|
||||
|
||||
DotNet.WithDotNet(SystemBuildActions.Instance, logger, smallNonBinaryFiles, tempWorkingDirectory.ToString(), shouldCleanUp: false, ensureDotNetAvailable: true, version: null, installDir =>
|
||||
{
|
||||
this.dotnetPath = installDir;
|
||||
return BuildScript.Success;
|
||||
}).Run(SystemBuildActions.Instance, startCallback, exitCallback);
|
||||
|
||||
try
|
||||
{
|
||||
this.dotnet = DotNet.Make(logger, dotnetPath, tempWorkingDirectory);
|
||||
runtimeLazy = new Lazy<Runtime>(() => new Runtime(dotnet));
|
||||
}
|
||||
catch
|
||||
{
|
||||
logger.LogError("Missing dotnet CLI");
|
||||
throw;
|
||||
}
|
||||
|
||||
RestoreNugetPackages(allNonBinaryFiles, allProjects, allSolutions, dllPaths);
|
||||
// Find DLLs in the .Net / Asp.Net Framework
|
||||
// This needs to come after the nuget restore, because the nuget restore might fetch the .NET Core/Framework reference assemblies.
|
||||
@@ -587,13 +570,15 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
public DependencyManager(string srcDir) : this(srcDir, DependencyOptions.Default, new ConsoleLogger(Verbosity.Info, logThreadId: true)) { }
|
||||
|
||||
private IEnumerable<FileInfo> GetAllFiles()
|
||||
{
|
||||
IEnumerable<FileInfo> files = sourceDir.GetFiles("*.*", new EnumerationOptions { RecurseSubdirectories = true });
|
||||
|
||||
if (dotnetPath != null)
|
||||
if (options.DotNetPath != null)
|
||||
{
|
||||
files = files.Where(f => !f.FullName.StartsWith(dotnetPath, StringComparison.OrdinalIgnoreCase));
|
||||
files = files.Where(f => !f.FullName.StartsWith(options.DotNetPath, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
files = files.Where(f =>
|
||||
@@ -605,12 +590,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.LogWarning($"File {f.FullName} could not be processed.");
|
||||
logger.Log(Severity.Warning, $"File {f.FullName} could not be processed.");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning($"File {f.FullName} could not be processed: {ex.Message}");
|
||||
logger.Log(Severity.Warning, $"File {f.FullName} could not be processed: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@@ -666,7 +651,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
catch (AssemblyLoadException)
|
||||
{
|
||||
logger.LogWarning($"Could not load assembly information from {usedReference.Key}");
|
||||
logger.Log(Severity.Warning, $"Could not load assembly information from {usedReference.Key}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,7 +738,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
private void AnalyseSolutions(IEnumerable<string> solutions)
|
||||
{
|
||||
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = threads }, solutionFile =>
|
||||
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, solutionFile =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -843,7 +828,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var successCount = 0;
|
||||
var assetFiles = new List<string>();
|
||||
var sync = new object();
|
||||
Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = threads }, project =>
|
||||
Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, project =>
|
||||
{
|
||||
logger.LogInfo($"Restoring project {project}...");
|
||||
var res = dotnet.Restore(new(project, packageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true));
|
||||
@@ -943,7 +928,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var successCount = 0;
|
||||
var sync = new object();
|
||||
|
||||
Parallel.ForEach(notYetDownloadedPackages, new ParallelOptions { MaxDegreeOfParallelism = threads }, package =>
|
||||
Parallel.ForEach(notYetDownloadedPackages, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, package =>
|
||||
{
|
||||
var success = TryRestorePackageManually(package.Name, nugetConfig, package.PackageReferenceSource);
|
||||
if (!success)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
/// <summary>
|
||||
/// Dependency fetching related options.
|
||||
/// </summary>
|
||||
public interface IDependencyOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of threads to use.
|
||||
/// </summary>
|
||||
int Threads { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The path to the local ".dotnet" directory, if any.
|
||||
/// </summary>
|
||||
string? DotNetPath { get; }
|
||||
}
|
||||
|
||||
public class DependencyOptions : IDependencyOptions
|
||||
{
|
||||
public static IDependencyOptions Default => new DependencyOptions();
|
||||
|
||||
public int Threads { get; set; } = EnvironmentVariables.GetDefaultNumberOfThreads();
|
||||
|
||||
public string? DotNetPath { get; set; } = null;
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
using Semmle.Util;
|
||||
using Semmle.Util.Logging;
|
||||
|
||||
@@ -13,26 +11,29 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
/// <summary>
|
||||
/// Utilities to run the "dotnet" command.
|
||||
/// </summary>
|
||||
public partial class DotNet : IDotNet
|
||||
internal partial class DotNet : IDotNet
|
||||
{
|
||||
private readonly IDotNetCliInvoker dotnetCliInvoker;
|
||||
private readonly ILogger logger;
|
||||
private readonly TemporaryDirectory? tempWorkingDirectory;
|
||||
|
||||
private DotNet(IDotNetCliInvoker dotnetCliInvoker, ILogger logger, TemporaryDirectory? tempWorkingDirectory = null)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.tempWorkingDirectory = tempWorkingDirectory;
|
||||
this.dotnetCliInvoker = dotnetCliInvoker;
|
||||
Info();
|
||||
}
|
||||
|
||||
private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory) : this(new DotNetCliInvoker(logger, Path.Combine(dotNetPath ?? string.Empty, "dotnet")), logger, tempWorkingDirectory) { }
|
||||
private DotNet(IDependencyOptions options, ILogger logger, TemporaryDirectory tempWorkingDirectory) : this(new DotNetCliInvoker(logger, Path.Combine(options.DotNetPath ?? string.Empty, "dotnet")), logger, tempWorkingDirectory) { }
|
||||
|
||||
internal static IDotNet Make(IDotNetCliInvoker dotnetCliInvoker, ILogger logger) => new DotNet(dotnetCliInvoker, logger);
|
||||
|
||||
public static IDotNet Make(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory) => new DotNet(logger, dotNetPath, tempWorkingDirectory);
|
||||
public static IDotNet Make(IDependencyOptions options, ILogger logger, TemporaryDirectory tempWorkingDirectory) => new DotNet(options, logger, tempWorkingDirectory);
|
||||
|
||||
private void Info()
|
||||
{
|
||||
// TODO: make sure the below `dotnet` version is matching the one specified in global.json
|
||||
var res = dotnetCliInvoker.RunCommand("--info");
|
||||
if (!res)
|
||||
{
|
||||
@@ -107,191 +108,5 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var args = $"exec {execArgs}";
|
||||
return dotnetCliInvoker.RunCommand(args);
|
||||
}
|
||||
|
||||
// The version number should be kept in sync with the version .NET version used for building the application.
|
||||
public const string LatestDotNetSdkVersion = "8.0.101";
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script for downloading relevant versions of the
|
||||
/// .NET SDK. The SDK(s) will be installed at <code>installDir</code>
|
||||
/// (provided that the script succeeds).
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNet(IBuildActions actions, ILogger logger, IEnumerable<string> files, string tempWorkingDirectory, bool shouldCleanUp, string installDir, string? version, bool ensureDotNetAvailable)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
// Specific version requested
|
||||
return DownloadDotNetVersion(actions, logger, tempWorkingDirectory, shouldCleanUp, installDir, [version]);
|
||||
|
||||
// Download versions mentioned in `global.json` files
|
||||
// See https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
|
||||
var versions = new List<string>();
|
||||
|
||||
foreach (var path in files.Where(p => p.EndsWith("global.json", StringComparison.Ordinal)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var o = JObject.Parse(File.ReadAllText(path));
|
||||
versions.Add((string)o?["sdk"]?["version"]!);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// not a valid `global.json` file
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (versions.Count > 0)
|
||||
{
|
||||
return DownloadDotNetVersion(actions, logger, tempWorkingDirectory, shouldCleanUp, installDir, versions);
|
||||
}
|
||||
|
||||
if (ensureDotNetAvailable)
|
||||
{
|
||||
return DownloadDotNetVersion(actions, logger, tempWorkingDirectory, shouldCleanUp, installDir, [LatestDotNetSdkVersion], needExactVersion: false);
|
||||
}
|
||||
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script for downloading specific .NET SDK versions, if the
|
||||
/// versions are not already installed.
|
||||
///
|
||||
/// See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script.
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNetVersion(IBuildActions actions, ILogger logger, string tempWorkingDirectory, bool shouldCleanUp, string path, IEnumerable<string> versions, bool needExactVersion = true)
|
||||
{
|
||||
if (!versions.Any())
|
||||
{
|
||||
logger.LogInfo("No .NET SDK versions requested.");
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
|
||||
return BuildScript.Bind(GetInstalledSdksScript(actions), (sdks, sdksRet) =>
|
||||
{
|
||||
if (
|
||||
needExactVersion &&
|
||||
sdksRet == 0 &&
|
||||
// quadratic; should be OK, given that both `version` and `sdks` are expected to be small
|
||||
versions.All(version => sdks.Any(sdk => sdk.StartsWith(version + " ", StringComparison.Ordinal))))
|
||||
{
|
||||
// The requested SDKs are already installed, so no need to reinstall
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
else if (!needExactVersion && sdksRet == 0 && sdks.Count > 0)
|
||||
{
|
||||
// there's at least one SDK installed, so no need to reinstall
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
else if (!needExactVersion && sdksRet != 0)
|
||||
{
|
||||
logger.LogInfo("No .NET SDK found.");
|
||||
}
|
||||
|
||||
BuildScript prelude;
|
||||
BuildScript postlude;
|
||||
Func<string, BuildScript> getInstall;
|
||||
|
||||
if (actions.IsWindows())
|
||||
{
|
||||
prelude = BuildScript.Success;
|
||||
postlude = BuildScript.Success;
|
||||
|
||||
getInstall = version =>
|
||||
{
|
||||
var psCommand = $"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version {version} -InstallDir {path}";
|
||||
|
||||
BuildScript GetInstall(string pwsh) =>
|
||||
new CommandBuilder(actions).
|
||||
RunCommand(pwsh).
|
||||
Argument("-NoProfile").
|
||||
Argument("-ExecutionPolicy").
|
||||
Argument("unrestricted").
|
||||
Argument("-Command").
|
||||
Argument("\"" + psCommand + "\"").
|
||||
Script;
|
||||
|
||||
return GetInstall("pwsh") | GetInstall("powershell");
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
var dotnetInstallPath = actions.PathCombine(tempWorkingDirectory, ".dotnet", "dotnet-install.sh");
|
||||
|
||||
var downloadDotNetInstallSh = BuildScript.DownloadFile(
|
||||
"https://dot.net/v1/dotnet-install.sh",
|
||||
dotnetInstallPath,
|
||||
e => logger.LogWarning($"Failed to download 'dotnet-install.sh': {e.Message}"));
|
||||
|
||||
var chmod = new CommandBuilder(actions).
|
||||
RunCommand("chmod").
|
||||
Argument("u+x").
|
||||
Argument(dotnetInstallPath);
|
||||
|
||||
prelude = downloadDotNetInstallSh & chmod.Script;
|
||||
postlude = shouldCleanUp ? BuildScript.DeleteFile(dotnetInstallPath) : BuildScript.Success;
|
||||
|
||||
getInstall = version => new CommandBuilder(actions).
|
||||
RunCommand(dotnetInstallPath).
|
||||
Argument("--channel").
|
||||
Argument("release").
|
||||
Argument("--version").
|
||||
Argument(version).
|
||||
Argument("--install-dir").
|
||||
Argument(path).Script;
|
||||
}
|
||||
|
||||
var installScript = prelude & BuildScript.Failure;
|
||||
|
||||
var attempted = new HashSet<string>();
|
||||
foreach (var version in versions)
|
||||
{
|
||||
if (!attempted.Add(version))
|
||||
continue;
|
||||
|
||||
installScript = BuildScript.Bind(installScript, combinedExit =>
|
||||
{
|
||||
logger.LogInfo($"Attempting to download .NET {version}");
|
||||
|
||||
// When there are multiple versions requested, we want to try to fetch them all, reporting
|
||||
// a successful exit code when at least one of them succeeds
|
||||
return combinedExit != 0 ? getInstall(version) : BuildScript.Bind(getInstall(version), _ => BuildScript.Success);
|
||||
});
|
||||
}
|
||||
|
||||
return installScript & postlude;
|
||||
});
|
||||
}
|
||||
|
||||
private static BuildScript GetInstalledSdksScript(IBuildActions actions)
|
||||
{
|
||||
var listSdks = new CommandBuilder(actions, silent: true).
|
||||
RunCommand("dotnet").
|
||||
Argument("--list-sdks");
|
||||
return listSdks.Script;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script that attempts to download relevant version(s) of the
|
||||
/// .NET SDK, followed by running the script generated by <paramref name="f"/>.
|
||||
///
|
||||
/// The argument to <paramref name="f"/> is the path to the directory in which the
|
||||
/// .NET SDK(s) were installed.
|
||||
/// </summary>
|
||||
public static BuildScript WithDotNet(IBuildActions actions, ILogger logger, IEnumerable<string> files, string tempWorkingDirectory, bool shouldCleanUp, bool ensureDotNetAvailable, string? version, Func<string?, BuildScript> f)
|
||||
{
|
||||
var installDir = actions.PathCombine(tempWorkingDirectory, ".dotnet");
|
||||
var installScript = DownloadDotNet(actions, logger, files, tempWorkingDirectory, shouldCleanUp, installDir, version, ensureDotNetAvailable);
|
||||
return BuildScript.Bind(installScript, installed =>
|
||||
{
|
||||
if (installed != 0)
|
||||
{
|
||||
// The .NET SDK was not installed, either because the installation failed or because it was already installed.
|
||||
installDir = null;
|
||||
}
|
||||
|
||||
return f(installDir);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInfo($"Invalid filter: {filter}");
|
||||
logger.Log(Severity.Info, $"Invalid filter: {filter}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var regex = new FilePattern(filterText).RegexPattern;
|
||||
logger.LogInfo($"Filtering {(include ? "in" : "out")} files matching '{regex}'. Original glob filter: '{filter}'");
|
||||
logger.Log(Severity.Info, $"Filtering {(include ? "in" : "out")} files matching '{regex}'. Original glob filter: '{filter}'");
|
||||
pathFilters.Add(new PathFilter(new Regex(regex, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline), include));
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
if (!include)
|
||||
{
|
||||
logger.LogInfo($"Excluding '{f.FileInfo.FullName}'");
|
||||
logger.Log(Severity.Info, $"Excluding '{f.FileInfo.FullName}'");
|
||||
}
|
||||
|
||||
return include;
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
public interface IDotNet
|
||||
internal interface IDotNet
|
||||
{
|
||||
RestoreResult Restore(RestoreSettings restoreSettings);
|
||||
bool New(string folder);
|
||||
@@ -15,9 +15,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
bool Exec(string execArgs);
|
||||
}
|
||||
|
||||
public record class RestoreSettings(string File, string PackageDirectory, bool ForceDotnetRefAssemblyFetching, string? PathToNugetConfig = null, bool ForceReevaluation = false);
|
||||
internal record class RestoreSettings(string File, string PackageDirectory, bool ForceDotnetRefAssemblyFetching, string? PathToNugetConfig = null, bool ForceReevaluation = false);
|
||||
|
||||
public partial record class RestoreResult(bool Success, IList<string> Output)
|
||||
internal partial record class RestoreResult(bool Success, IList<string> Output)
|
||||
{
|
||||
private readonly Lazy<IEnumerable<string>> assetsFilePaths = new(() => GetFirstGroupOnMatch(AssetsFileRegex(), Output));
|
||||
public IEnumerable<string> AssetsFilePaths => Success ? assetsFilePaths.Value : Array.Empty<string>();
|
||||
|
||||
@@ -18,12 +18,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
private const string aspNetCoreApp = "Microsoft.AspNetCore.App";
|
||||
|
||||
private readonly IDotNet dotNet;
|
||||
private readonly ILogger logger;
|
||||
private readonly Lazy<Dictionary<string, DotNetVersion>> newestRuntimes;
|
||||
private Dictionary<string, DotNetVersion> NewestRuntimes => newestRuntimes.Value;
|
||||
|
||||
public Runtime(IDotNet dotNet)
|
||||
public Runtime(IDotNet dotNet, ILogger logger)
|
||||
{
|
||||
this.dotNet = dotNet;
|
||||
this.logger = logger;
|
||||
this.newestRuntimes = new(GetNewestRuntimes);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ using Semmle.Extraction.CSharp.StubGenerator;
|
||||
using Semmle.Util.Logging;
|
||||
|
||||
var logger = new ConsoleLogger(Verbosity.Info, logThreadId: false);
|
||||
using var dependencyManager = new DependencyManager(".", logger);
|
||||
using var dependencyManager = new DependencyManager(".", DependencyOptions.Default, logger);
|
||||
StubGenerator.GenerateStubs(logger, dependencyManager.ReferenceFiles, "codeql_csharp_stubs");
|
||||
|
||||
return 0;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user