Compare commits

..

5 Commits

Author SHA1 Message Date
Cornelius Riemenschneider
8fba481a04 shorter paths 2024-02-26 00:32:46 +01:00
Cornelius Riemenschneider
9433201b58 add bzlmod 2024-02-25 23:51:00 +01:00
Cornelius Riemenschneider
c097397c32 Address review, start accomodating bzlmod. 2024-02-22 22:02:14 +01:00
Cornelius Riemenschneider
3d5d1bc59e Fix windows CI build.
As we're now checking out the `codeql` repo in a sub-path,
we need to enable long paths on Windows.
2024-02-22 21:25:59 +01:00
Cornelius Riemenschneider
007fc89543 Ruby: Start building the language pack using bazel.
This PR introduces a bazel and `rules_rust`-based build system
for the ruby extractor and language pack.
This replacese the existing, `cargo` and `cross`-based build system.

For local development, nothing changes, and the existing `cargo`-based
build still keeps working as-is.

We no longer need to use `cross` to compile our Linux binaries,
as we now can link against our hermetic C++ toolchain, which ships
with an old enough glibc, so that we don't run into symbol version issues
when deploying the binaries to older systems.
Besides the one change in dependency (explained in detail in `Cargo.toml`
and in https://github.com/github/codeql/pull/15595), nothing ought to
change in how we build the extractor.
2024-02-22 21:25:59 +01:00
778 changed files with 48434 additions and 49660 deletions

View File

@@ -1 +1 @@
7.0.2
6.5.0

2
.github/labeler.yml vendored
View File

@@ -20,7 +20,7 @@ JS:
Kotlin:
- java/kotlin-extractor/**/*
- java/ql/test-kotlin*/**/*
- java/ql/test/kotlin/**/*
Python:
- python/**/*

View File

@@ -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
View File

@@ -39,9 +39,6 @@
# local bazel options
/local.bazelrc
# generated cmake directory
/.bazel-cmake
# CLion project files
/.clwb

View File

@@ -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")

View File

@@ -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",

View File

@@ -1,7 +1,5 @@
using System;
using Semmle.Autobuild.Shared;
using Semmle.Util;
namespace Semmle.Autobuild.Cpp
{

View File

@@ -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

View File

@@ -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("//", "/")
}

View File

@@ -1,5 +0,0 @@
## 0.12.7
### Minor Analysis Improvements
* Added destructors for named objects to the intermediate representation.

View File

@@ -1,3 +0,0 @@
## 0.12.8
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.12.8
lastReleaseVersion: 0.12.6

View File

@@ -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

View File

@@ -60,6 +60,4 @@ Element exprEnclosingElement(Expr e) {
)
else result = de.getDeclaration()
)
or
result.(Stmt).getAnImplicitDestructorCall() = e
}

View File

@@ -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

View File

@@ -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.

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*/
private import cpp
private import DataFlowPrivate
private import DataFlowUtil

View File

@@ -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>

View File

@@ -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>

View File

@@ -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.
*/

View File

@@ -1,6 +1,4 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*
* Provides C++-specific definitions for use in the data flow library.
*/

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*/
private import cpp
private import DataFlowUtil
private import DataFlowDispatch

View File

@@ -1,6 +1,4 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*
* Provides C++-specific definitions for use in the data flow library.
*/

View File

@@ -1,6 +1,4 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*
* Provides a class for handling variables in the data flow analysis.
*/

View File

@@ -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

View File

@@ -1,6 +1,4 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*
* Provides C++-specific definitions for use in the taint tracking library.
*/

View File

@@ -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.
*

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
*/
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
module Private {

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
*/
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
module Private {

View File

@@ -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 }

View File

@@ -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

View File

@@ -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 + ")"
)
}

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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() }
}

View File

@@ -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

View File

@@ -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()
}
}

View File

@@ -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

View File

@@ -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."

View File

@@ -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.

View File

@@ -1,3 +0,0 @@
## 0.9.7
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.9.7
lastReleaseVersion: 0.9.5

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.9.7
version: 0.9.6-dev
groups:
- cpp
- queries

View File

@@ -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

View File

@@ -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

View File

@@ -1,2 +1,2 @@
testFailures
failures
testFailures

View File

@@ -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 | |

View File

@@ -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 |

View File

@@ -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

View File

@@ -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) |

View File

@@ -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

View File

@@ -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. |

View File

@@ -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. |

View File

@@ -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

View File

@@ -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;

View File

@@ -1,6 +1,5 @@
using Semmle.Autobuild.Shared;
using Semmle.Extraction.CSharp;
using Semmle.Util;
namespace Semmle.Autobuild.CSharp
{

View File

@@ -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;
});

View File

@@ -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";

View File

@@ -1,7 +1,5 @@
using System;
using Semmle.Autobuild.Shared;
using Semmle.Util;
namespace Semmle.Autobuild.CSharp
{

View File

@@ -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>

View File

@@ -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();
}
}
}

View File

@@ -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();

View File

@@ -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();
}
}
}

View File

@@ -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;

View File

@@ -1,6 +1,4 @@
using Semmle.Util;
namespace Semmle.Autobuild.Shared
namespace Semmle.Autobuild.Shared
{
/// <summary>
/// Execute the build_command rule.

View File

@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Util
namespace Semmle.Autobuild.Shared
{
/// <summary>
/// A build script.

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Semmle.Util;
namespace Semmle.Autobuild.Shared
{

View File

@@ -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.

View File

@@ -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;
});
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -1,7 +0,0 @@
class Modifiable extends @modifiable {
Modifiable() { compiler_generated(this) }
string toString() { none() }
}
select any(Modifiable m)

View File

@@ -1,7 +0,0 @@
class Expression extends @expr {
Expression() { compiler_generated(this) }
string toString() { none() }
}
select any(Expression e)

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +0,0 @@
description: Extract `ref readonly` parameters as having `mode` 0 in the params table.
compatibility: full
params.rel: run params.qlo

View File

@@ -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();

View File

@@ -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));
}
}
}

View File

@@ -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)

View File

@@ -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;
}
}

View File

@@ -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);
});
}
}
}
}

View File

@@ -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;

View File

@@ -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>();

View File

@@ -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);
}

View File

@@ -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