Merge branch 'main' into java/refactor-dataflow-queries-1

This commit is contained in:
Anders Schack-Mulligen
2023-03-10 12:38:06 +01:00
committed by GitHub
777 changed files with 15815 additions and 10885 deletions

View File

@@ -1,5 +1,6 @@
using Xunit; using Xunit;
using Semmle.Autobuild.Shared; using Semmle.Autobuild.Shared;
using Semmle.Util;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
using System.Linq; using System.Linq;
@@ -75,6 +76,15 @@ namespace Semmle.Autobuild.Cpp.Tests
throw new ArgumentException("Missing RunProcess " + pattern); throw new ArgumentException("Missing RunProcess " + pattern);
} }
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? env, BuildOutputHandler onOutput, BuildOutputHandler onError)
{
var ret = (this as IBuildActions).RunProcess(cmd, args, workingDirectory, env, out var stdout);
stdout.ForEach(line => onOutput(line));
return ret;
}
public IList<string> DirectoryDeleteIn = new List<string>(); public IList<string> DirectoryDeleteIn = new List<string>();
void IBuildActions.DirectoryDelete(string dir, bool recursive) void IBuildActions.DirectoryDelete(string dir, bool recursive)
@@ -184,6 +194,15 @@ namespace Semmle.Autobuild.Cpp.Tests
if (!DownloadFiles.Contains((address, fileName))) if (!DownloadFiles.Contains((address, fileName)))
throw new ArgumentException($"Missing DownloadFile, {address}, {fileName}"); throw new ArgumentException($"Missing DownloadFile, {address}, {fileName}");
} }
public IDiagnosticsWriter CreateDiagnosticsWriter(string filename) => new TestDiagnosticWriter();
}
internal class TestDiagnosticWriter : IDiagnosticsWriter
{
public IList<DiagnosticMessage> Diagnostics { get; } = new List<DiagnosticMessage>();
public void AddEntry(DiagnosticMessage message) => this.Diagnostics.Add(message);
} }
/// <summary> /// <summary>
@@ -243,6 +262,7 @@ namespace Semmle.Autobuild.Cpp.Tests
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_TRAP_DIR"] = ""; Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_TRAP_DIR"] = "";
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_SOURCE_ARCHIVE_DIR"] = ""; Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_SOURCE_ARCHIVE_DIR"] = "";
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_ROOT"] = $@"C:\codeql\{codeqlUpperLanguage.ToLowerInvariant()}"; Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_ROOT"] = $@"C:\codeql\{codeqlUpperLanguage.ToLowerInvariant()}";
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_DIAGNOSTIC_DIR"] = "";
Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java"; Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java";
Actions.GetEnvironmentVariable["CODEQL_PLATFORM"] = "win64"; Actions.GetEnvironmentVariable["CODEQL_PLATFORM"] = "win64";
Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa"; Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa";

View File

@@ -1,4 +1,5 @@
using Semmle.Autobuild.Shared; using Semmle.Autobuild.Shared;
using Semmle.Util;
namespace Semmle.Autobuild.Cpp namespace Semmle.Autobuild.Cpp
{ {
@@ -21,7 +22,7 @@ namespace Semmle.Autobuild.Cpp
public class CppAutobuilder : Autobuilder<CppAutobuildOptions> public class CppAutobuilder : Autobuilder<CppAutobuildOptions>
{ {
public CppAutobuilder(IBuildActions actions, CppAutobuildOptions options) : base(actions, options) { } public CppAutobuilder(IBuildActions actions, CppAutobuildOptions options) : base(actions, options, new DiagnosticClassifier()) { }
public override BuildScript GetBuildScript() public override BuildScript GetBuildScript()
{ {

View File

@@ -1,3 +1,7 @@
## 0.5.4
No user-facing changes.
## 0.5.3 ## 0.5.3
No user-facing changes. No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.5.3 lastReleaseVersion: 0.5.4

View File

@@ -456,6 +456,7 @@ module Impl<FullStateConfigSig Config> {
* The Boolean `cc` records whether the node is reached through an * The Boolean `cc` records whether the node is reached through an
* argument in a call. * argument in a call.
*/ */
pragma[assume_small_delta]
private predicate fwdFlow(NodeEx node, Cc cc) { private predicate fwdFlow(NodeEx node, Cc cc) {
sourceNode(node, _) and sourceNode(node, _) and
if hasSourceCallCtx() then cc = true else cc = false if hasSourceCallCtx() then cc = true else cc = false

View File

@@ -7,7 +7,8 @@ import TaintTrackingParameter::Public
private import TaintTrackingParameter::Private private import TaintTrackingParameter::Private
private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> implements private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> implements
DataFlowInternal::FullStateConfigSig { DataFlowInternal::FullStateConfigSig
{
import Config import Config
predicate isBarrier(DataFlow::Node node) { predicate isBarrier(DataFlow::Node node) {

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 0.5.4-dev version: 0.5.5-dev
groups: cpp groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp

View File

@@ -186,7 +186,7 @@ class Declaration extends Locatable, @declaration {
predicate hasDefinition() { exists(this.getDefinition()) } predicate hasDefinition() { exists(this.getDefinition()) }
/** DEPRECATED: Use `hasDefinition` instead. */ /** DEPRECATED: Use `hasDefinition` instead. */
predicate isDefined() { this.hasDefinition() } deprecated predicate isDefined() { this.hasDefinition() }
/** Gets the preferred location of this declaration, if any. */ /** Gets the preferred location of this declaration, if any. */
override Location getLocation() { none() } override Location getLocation() { none() }
@@ -619,11 +619,10 @@ private class DirectAccessHolder extends Element {
/** /**
* Like `couldAccessMember` but only contains derivations in which either * Like `couldAccessMember` but only contains derivations in which either
* (5.2), (5.3) or (5.4) must be invoked. In other words, the `this` * (5.2), (5.3) or (5.4) must be invoked. In other words, the `this`
* parameter is not ignored. This restriction makes it feasible to fully * parameter is not ignored. We check for 11.4 as part of (5.3), since
* enumerate this predicate even on large code bases. We check for 11.4 as * this further limits the number of tuples produced by this predicate.
* part of (5.3), since this further limits the number of tuples produced by
* this predicate.
*/ */
pragma[inline]
predicate thisCouldAccessMember(Class memberClass, AccessSpecifier memberAccess, Class derived) { predicate thisCouldAccessMember(Class memberClass, AccessSpecifier memberAccess, Class derived) {
// Only (5.4) is recursive, and chains of invocations of (5.4) can always // Only (5.4) is recursive, and chains of invocations of (5.4) can always
// be collapsed to one invocation by the transitivity of 11.2/4. // be collapsed to one invocation by the transitivity of 11.2/4.
@@ -665,7 +664,9 @@ private class DirectAccessHolder extends Element {
// bypasses `p`. Then that path must be public, or we are in case 2. // bypasses `p`. Then that path must be public, or we are in case 2.
exists(AccessSpecifier public | public.hasName("public") | exists(AccessSpecifier public | public.hasName("public") |
exists(Class between, Class p | exists(Class between, Class p |
between.accessOfBaseMember(memberClass, memberAccess).hasName("protected") and between
.accessOfBaseMember(pragma[only_bind_into](memberClass), memberAccess)
.hasName("protected") and
this.isFriendOfOrEqualTo(p) and this.isFriendOfOrEqualTo(p) and
( (
// This is case 1 from above. If `p` derives privately from `between` // This is case 1 from above. If `p` derives privately from `between`

View File

@@ -41,7 +41,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* `min<int>(int, int) -> int`, and the full signature of the uninstantiated * `min<int>(int, int) -> int`, and the full signature of the uninstantiated
* template on the first line would be `min<T>(T, T) -> T`. * template on the first line would be `min<T>(T, T) -> T`.
*/ */
string getFullSignature() { deprecated string getFullSignature() {
exists(string name, string templateArgs, string args | exists(string name, string templateArgs, string args |
result = name + templateArgs + args + " -> " + this.getType().toString() and result = name + templateArgs + args + " -> " + this.getType().toString() and
name = this.getQualifiedName() and name = this.getQualifiedName() and

View File

@@ -159,7 +159,8 @@ class NameQualifyingElement extends Element, @namequalifyingelement {
* A special name-qualifying element. For example: `__super`. * A special name-qualifying element. For example: `__super`.
*/ */
library class SpecialNameQualifyingElement extends NameQualifyingElement, library class SpecialNameQualifyingElement extends NameQualifyingElement,
@specialnamequalifyingelement { @specialnamequalifyingelement
{
/** Gets the name of this special qualifying element. */ /** Gets the name of this special qualifying element. */
override string getName() { specialnamequalifyingelements(underlyingElement(this), result) } override string getName() { specialnamequalifyingelements(underlyingElement(this), result) }

View File

@@ -12,7 +12,9 @@ predicate freeFunction(Function f, int argNum) { argNum = f.(DeallocationFunctio
* *
* DEPRECATED: Use `DeallocationExpr` instead (this also includes `delete` expressions). * DEPRECATED: Use `DeallocationExpr` instead (this also includes `delete` expressions).
*/ */
predicate freeCall(FunctionCall fc, Expr arg) { arg = fc.(DeallocationExpr).getFreedExpr() } deprecated predicate freeCall(FunctionCall fc, Expr arg) {
arg = fc.(DeallocationExpr).getFreedExpr()
}
/** /**
* Is e some kind of allocation or deallocation (`new`, `alloc`, `realloc`, `delete`, `free` etc)? * Is e some kind of allocation or deallocation (`new`, `alloc`, `realloc`, `delete`, `free` etc)?

View File

@@ -456,6 +456,7 @@ module Impl<FullStateConfigSig Config> {
* The Boolean `cc` records whether the node is reached through an * The Boolean `cc` records whether the node is reached through an
* argument in a call. * argument in a call.
*/ */
pragma[assume_small_delta]
private predicate fwdFlow(NodeEx node, Cc cc) { private predicate fwdFlow(NodeEx node, Cc cc) {
sourceNode(node, _) and sourceNode(node, _) and
if hasSourceCallCtx() then cc = true else cc = false if hasSourceCallCtx() then cc = true else cc = false

View File

@@ -7,7 +7,8 @@ import TaintTrackingParameter::Public
private import TaintTrackingParameter::Private private import TaintTrackingParameter::Private
private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> implements private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> implements
DataFlowInternal::FullStateConfigSig { DataFlowInternal::FullStateConfigSig
{
import Config import Config
predicate isBarrier(DataFlow::Node node) { predicate isBarrier(DataFlow::Node node) {

View File

@@ -569,7 +569,8 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation,
* ``` * ```
*/ */
class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation, class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation,
@istriviallyconstructibleexpr { @istriviallyconstructibleexpr
{
override string toString() { result = "__is_trivially_constructible" } override string toString() { result = "__is_trivially_constructible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyConstructible" } override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyConstructible" }
@@ -619,7 +620,8 @@ class BuiltInOperationIsNothrowDestructible extends BuiltInOperation, @isnothrow
* bool v = __is_trivially_destructible(MyType); * bool v = __is_trivially_destructible(MyType);
* ``` * ```
*/ */
class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istriviallydestructibleexpr { class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istriviallydestructibleexpr
{
override string toString() { result = "__is_trivially_destructible" } override string toString() { result = "__is_trivially_destructible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyDestructible" } override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyDestructible" }
@@ -738,7 +740,8 @@ class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr
* ``` * ```
*/ */
class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation, class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
@hastrivialmoveconstructorexpr { @hastrivialmoveconstructorexpr
{
override string toString() { result = "__has_trivial_move_constructor" } override string toString() { result = "__has_trivial_move_constructor" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialMoveConstructor" } override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialMoveConstructor" }
@@ -1034,7 +1037,8 @@ class BuiltInOperationIsAggregate extends BuiltInOperation, @isaggregate {
* ``` * ```
*/ */
class BuiltInOperationHasUniqueObjectRepresentations extends BuiltInOperation, class BuiltInOperationHasUniqueObjectRepresentations extends BuiltInOperation,
@hasuniqueobjectrepresentations { @hasuniqueobjectrepresentations
{
override string toString() { result = "__has_unique_object_representations" } override string toString() { result = "__has_unique_object_representations" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasUniqueObjectRepresentations" } override string getAPrimaryQlClass() { result = "BuiltInOperationHasUniqueObjectRepresentations" }
@@ -1107,7 +1111,8 @@ class BuiltInOperationIsLayoutCompatible extends BuiltInOperation, @islayoutcomp
* ``` * ```
*/ */
class BuiltInOperationIsPointerInterconvertibleBaseOf extends BuiltInOperation, class BuiltInOperationIsPointerInterconvertibleBaseOf extends BuiltInOperation,
@ispointerinterconvertiblebaseof { @ispointerinterconvertiblebaseof
{
override string toString() { result = "__is_pointer_interconvertible_base_of" } override string toString() { result = "__is_pointer_interconvertible_base_of" }
override string getAPrimaryQlClass() { override string getAPrimaryQlClass() {

View File

@@ -456,6 +456,7 @@ module Impl<FullStateConfigSig Config> {
* The Boolean `cc` records whether the node is reached through an * The Boolean `cc` records whether the node is reached through an
* argument in a call. * argument in a call.
*/ */
pragma[assume_small_delta]
private predicate fwdFlow(NodeEx node, Cc cc) { private predicate fwdFlow(NodeEx node, Cc cc) {
sourceNode(node, _) and sourceNode(node, _) and
if hasSourceCallCtx() then cc = true else cc = false if hasSourceCallCtx() then cc = true else cc = false

View File

@@ -7,7 +7,8 @@ import TaintTrackingParameter::Public
private import TaintTrackingParameter::Private private import TaintTrackingParameter::Private
private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> implements private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> implements
DataFlowInternal::FullStateConfigSig { DataFlowInternal::FullStateConfigSig
{
import Config import Config
predicate isBarrier(DataFlow::Node node) { predicate isBarrier(DataFlow::Node node) {

View File

@@ -1082,7 +1082,8 @@ module Opcode {
* See the `CallSideEffectInstruction` documentation for more details. * See the `CallSideEffectInstruction` documentation for more details.
*/ */
class CallSideEffect extends WriteSideEffectOpcode, EscapedWriteOpcode, MayWriteOpcode, class CallSideEffect extends WriteSideEffectOpcode, EscapedWriteOpcode, MayWriteOpcode,
ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, TCallSideEffect { ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, TCallSideEffect
{
final override string toString() { result = "CallSideEffect" } final override string toString() { result = "CallSideEffect" }
} }
@@ -1092,7 +1093,8 @@ module Opcode {
* See the `CallReadSideEffectInstruction` documentation for more details. * See the `CallReadSideEffectInstruction` documentation for more details.
*/ */
class CallReadSideEffect extends ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, class CallReadSideEffect extends ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode,
TCallReadSideEffect { TCallReadSideEffect
{
final override string toString() { result = "CallReadSideEffect" } final override string toString() { result = "CallReadSideEffect" }
} }
@@ -1102,7 +1104,8 @@ module Opcode {
* See the `IndirectReadSideEffectInstruction` documentation for more details. * See the `IndirectReadSideEffectInstruction` documentation for more details.
*/ */
class IndirectReadSideEffect extends ReadSideEffectOpcode, IndirectReadOpcode, class IndirectReadSideEffect extends ReadSideEffectOpcode, IndirectReadOpcode,
TIndirectReadSideEffect { TIndirectReadSideEffect
{
final override string toString() { result = "IndirectReadSideEffect" } final override string toString() { result = "IndirectReadSideEffect" }
} }
@@ -1112,7 +1115,8 @@ module Opcode {
* See the `IndirectMustWriteSideEffectInstruction` documentation for more details. * See the `IndirectMustWriteSideEffectInstruction` documentation for more details.
*/ */
class IndirectMustWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode, class IndirectMustWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode,
TIndirectMustWriteSideEffect { TIndirectMustWriteSideEffect
{
final override string toString() { result = "IndirectMustWriteSideEffect" } final override string toString() { result = "IndirectMustWriteSideEffect" }
} }
@@ -1122,7 +1126,8 @@ module Opcode {
* See the `IndirectMayWriteSideEffectInstruction` documentation for more details. * See the `IndirectMayWriteSideEffectInstruction` documentation for more details.
*/ */
class IndirectMayWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode, class IndirectMayWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode,
MayWriteOpcode, TIndirectMayWriteSideEffect { MayWriteOpcode, TIndirectMayWriteSideEffect
{
final override string toString() { result = "IndirectMayWriteSideEffect" } final override string toString() { result = "IndirectMayWriteSideEffect" }
} }
@@ -1132,7 +1137,8 @@ module Opcode {
* See the `BufferReadSideEffectInstruction` documentation for more details. * See the `BufferReadSideEffectInstruction` documentation for more details.
*/ */
class BufferReadSideEffect extends ReadSideEffectOpcode, UnsizedBufferReadOpcode, class BufferReadSideEffect extends ReadSideEffectOpcode, UnsizedBufferReadOpcode,
TBufferReadSideEffect { TBufferReadSideEffect
{
final override string toString() { result = "BufferReadSideEffect" } final override string toString() { result = "BufferReadSideEffect" }
} }
@@ -1142,7 +1148,8 @@ module Opcode {
* See the `BufferMustWriteSideEffectInstruction` documentation for more details. * See the `BufferMustWriteSideEffectInstruction` documentation for more details.
*/ */
class BufferMustWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode, class BufferMustWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode,
TBufferMustWriteSideEffect { TBufferMustWriteSideEffect
{
final override string toString() { result = "BufferMustWriteSideEffect" } final override string toString() { result = "BufferMustWriteSideEffect" }
} }
@@ -1152,7 +1159,8 @@ module Opcode {
* See the `BufferMayWriteSideEffectInstruction` documentation for more details. * See the `BufferMayWriteSideEffectInstruction` documentation for more details.
*/ */
class BufferMayWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode, class BufferMayWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode,
MayWriteOpcode, TBufferMayWriteSideEffect { MayWriteOpcode, TBufferMayWriteSideEffect
{
final override string toString() { result = "BufferMayWriteSideEffect" } final override string toString() { result = "BufferMayWriteSideEffect" }
} }
@@ -1162,7 +1170,8 @@ module Opcode {
* See the `SizedBufferReadSideEffectInstruction` documentation for more details. * See the `SizedBufferReadSideEffectInstruction` documentation for more details.
*/ */
class SizedBufferReadSideEffect extends ReadSideEffectOpcode, SizedBufferReadOpcode, class SizedBufferReadSideEffect extends ReadSideEffectOpcode, SizedBufferReadOpcode,
TSizedBufferReadSideEffect { TSizedBufferReadSideEffect
{
final override string toString() { result = "SizedBufferReadSideEffect" } final override string toString() { result = "SizedBufferReadSideEffect" }
} }
@@ -1172,7 +1181,8 @@ module Opcode {
* See the `SizedBufferMustWriteSideEffectInstruction` documentation for more details. * See the `SizedBufferMustWriteSideEffectInstruction` documentation for more details.
*/ */
class SizedBufferMustWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode, class SizedBufferMustWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode,
TSizedBufferMustWriteSideEffect { TSizedBufferMustWriteSideEffect
{
final override string toString() { result = "SizedBufferMustWriteSideEffect" } final override string toString() { result = "SizedBufferMustWriteSideEffect" }
} }
@@ -1182,7 +1192,8 @@ module Opcode {
* See the `SizedBufferMayWriteSideEffectInstruction` documentation for more details. * See the `SizedBufferMayWriteSideEffectInstruction` documentation for more details.
*/ */
class SizedBufferMayWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode, class SizedBufferMayWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode,
MayWriteOpcode, TSizedBufferMayWriteSideEffect { MayWriteOpcode, TSizedBufferMayWriteSideEffect
{
final override string toString() { result = "SizedBufferMayWriteSideEffect" } final override string toString() { result = "SizedBufferMayWriteSideEffect" }
} }
@@ -1192,7 +1203,8 @@ module Opcode {
* See the `InitializeDynamicAllocationInstruction` documentation for more details. * See the `InitializeDynamicAllocationInstruction` documentation for more details.
*/ */
class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode, class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode,
TInitializeDynamicAllocation { TInitializeDynamicAllocation
{
final override string toString() { result = "InitializeDynamicAllocation" } final override string toString() { result = "InitializeDynamicAllocation" }
} }
@@ -1221,7 +1233,8 @@ module Opcode {
* See the `InlineAsmInstruction` documentation for more details. * See the `InlineAsmInstruction` documentation for more details.
*/ */
class InlineAsm extends Opcode, EscapedWriteOpcode, MayWriteOpcode, EscapedReadOpcode, class InlineAsm extends Opcode, EscapedWriteOpcode, MayWriteOpcode, EscapedReadOpcode,
MayReadOpcode, TInlineAsm { MayReadOpcode, TInlineAsm
{
final override string toString() { result = "InlineAsm" } final override string toString() { result = "InlineAsm" }
final override predicate hasOperandInternal(OperandTag tag) { final override predicate hasOperandInternal(OperandTag tag) {

View File

@@ -246,7 +246,8 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
} }
class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation, class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation,
AllocationMemoryLocation { AllocationMemoryLocation
{
EntireAllocationMemoryLocation() { this = TEntireAllocationMemoryLocation(var, isMayAccess) } EntireAllocationMemoryLocation() { this = TEntireAllocationMemoryLocation(var, isMayAccess) }
final override string toStringInternal() { result = var.toString() } final override string toStringInternal() { result = var.toString() }

View File

@@ -511,7 +511,8 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
* calls other than constructor calls. * calls other than constructor calls.
*/ */
class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect, class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
TTranslatedArgumentExprSideEffect { TTranslatedArgumentExprSideEffect
{
Expr arg; Expr arg;
TranslatedArgumentExprSideEffect() { TranslatedArgumentExprSideEffect() {
@@ -546,7 +547,8 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
* calls to non-static member functions. * calls to non-static member functions.
*/ */
class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect, class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect,
TTranslatedStructorQualifierSideEffect { TTranslatedStructorQualifierSideEffect
{
TranslatedStructorQualifierSideEffect() { TranslatedStructorQualifierSideEffect() {
this = TTranslatedStructorQualifierSideEffect(call, sideEffectOpcode) and this = TTranslatedStructorQualifierSideEffect(call, sideEffectOpcode) and
index = -1 index = -1

View File

@@ -34,7 +34,8 @@ abstract class TranslatedCondition extends TranslatedElement {
} }
abstract class TranslatedFlexibleCondition extends TranslatedCondition, ConditionContext, abstract class TranslatedFlexibleCondition extends TranslatedCondition, ConditionContext,
TTranslatedFlexibleCondition { TTranslatedFlexibleCondition
{
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) } TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() }

View File

@@ -75,7 +75,8 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
* The IR translation of a local variable declaration within a declaration statement. * The IR translation of a local variable declaration within a declaration statement.
*/ */
class TranslatedAutoVariableDeclarationEntry extends TranslatedLocalVariableDeclaration, class TranslatedAutoVariableDeclarationEntry extends TranslatedLocalVariableDeclaration,
TranslatedDeclarationEntry { TranslatedDeclarationEntry
{
StackVariable var; StackVariable var;
TranslatedAutoVariableDeclarationEntry() { var = entry.getDeclaration() } TranslatedAutoVariableDeclarationEntry() { var = entry.getDeclaration() }
@@ -217,7 +218,8 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
* with a dynamic initializer. * with a dynamic initializer.
*/ */
class TranslatedStaticLocalVariableInitialization extends TranslatedElement, class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
TranslatedLocalVariableDeclaration, TTranslatedStaticLocalVariableInitialization { TranslatedLocalVariableDeclaration, TTranslatedStaticLocalVariableInitialization
{
IRVariableDeclarationEntry entry; IRVariableDeclarationEntry entry;
StaticLocalVariable var; StaticLocalVariable var;

View File

@@ -131,7 +131,8 @@ abstract class TranslatedCoreExpr extends TranslatedExpr {
} }
class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext,
TTranslatedConditionValue { TTranslatedConditionValue
{
TranslatedConditionValue() { this = TTranslatedConditionValue(expr) } TranslatedConditionValue() { this = TTranslatedConditionValue(expr) }
override TranslatedElement getChild(int id) { id = 0 and result = this.getCondition() } override TranslatedElement getChild(int id) { id = 0 and result = this.getCondition() }
@@ -326,7 +327,8 @@ class TranslatedLoad extends TranslatedValueCategoryAdjustment, TTranslatedLoad
* from the AST. * from the AST.
*/ */
class TranslatedSyntheticTemporaryObject extends TranslatedValueCategoryAdjustment, class TranslatedSyntheticTemporaryObject extends TranslatedValueCategoryAdjustment,
TTranslatedSyntheticTemporaryObject { TTranslatedSyntheticTemporaryObject
{
TranslatedSyntheticTemporaryObject() { this = TTranslatedSyntheticTemporaryObject(expr) } TranslatedSyntheticTemporaryObject() { this = TTranslatedSyntheticTemporaryObject(expr) }
override string toString() { result = "Temporary materialization of " + expr.toString() } override string toString() { result = "Temporary materialization of " + expr.toString() }
@@ -2302,7 +2304,8 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr {
* its initializer. * its initializer.
*/ */
class TranslatedTemporaryObjectExpr extends TranslatedNonConstantExpr, class TranslatedTemporaryObjectExpr extends TranslatedNonConstantExpr,
TranslatedVariableInitialization { TranslatedVariableInitialization
{
override TemporaryObjectExpr expr; override TemporaryObjectExpr expr;
final override predicate hasTempVariable(TempVariableTag tag, CppType type) { final override predicate hasTempVariable(TempVariableTag tag, CppType type) {

View File

@@ -566,7 +566,8 @@ private TranslatedConstructorInitList getTranslatedConstructorInitList(Function
* instances for constructors can actually contain initializers. * instances for constructors can actually contain initializers.
*/ */
class TranslatedConstructorInitList extends TranslatedElement, InitializationContext, class TranslatedConstructorInitList extends TranslatedElement, InitializationContext,
TTranslatedConstructorInitList { TTranslatedConstructorInitList
{
Function func; Function func;
TranslatedConstructorInitList() { this = TTranslatedConstructorInitList(func) } TranslatedConstructorInitList() { this = TTranslatedConstructorInitList(func) }
@@ -637,7 +638,8 @@ private TranslatedDestructorDestructionList getTranslatedDestructorDestructionLi
* destructions. * destructions.
*/ */
class TranslatedDestructorDestructionList extends TranslatedElement, class TranslatedDestructorDestructionList extends TranslatedElement,
TTranslatedDestructorDestructionList { TTranslatedDestructorDestructionList
{
Function func; Function func;
TranslatedDestructorDestructionList() { this = TTranslatedDestructorDestructionList(func) } TranslatedDestructorDestructionList() { this = TTranslatedDestructorDestructionList(func) }

View File

@@ -9,7 +9,8 @@ private import InstructionTag
private import semmle.code.cpp.ir.internal.IRUtilities private import semmle.code.cpp.ir.internal.IRUtilities
class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement, class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
TTranslatedGlobalOrNamespaceVarInit, InitializationContext { TTranslatedGlobalOrNamespaceVarInit, InitializationContext
{
GlobalOrNamespaceVariable var; GlobalOrNamespaceVariable var;
TranslatedGlobalOrNamespaceVarInit() { this = TTranslatedGlobalOrNamespaceVarInit(var) } TranslatedGlobalOrNamespaceVarInit() { this = TTranslatedGlobalOrNamespaceVarInit(var) }

View File

@@ -440,7 +440,8 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
} }
class TranslatedConstructorInitialization extends TranslatedDirectInitialization, class TranslatedConstructorInitialization extends TranslatedDirectInitialization,
StructorCallContext { StructorCallContext
{
override ConstructorCall expr; override ConstructorCall expr;
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -528,7 +529,8 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
* explicit element in an initializer list. * explicit element in an initializer list.
*/ */
class TranslatedExplicitFieldInitialization extends TranslatedFieldInitialization, class TranslatedExplicitFieldInitialization extends TranslatedFieldInitialization,
InitializationContext, TTranslatedExplicitFieldInitialization { InitializationContext, TTranslatedExplicitFieldInitialization
{
Expr expr; Expr expr;
TranslatedExplicitFieldInitialization() { TranslatedExplicitFieldInitialization() {
@@ -565,7 +567,8 @@ private string getZeroValue(Type type) {
* corresponding element in the initializer list. * corresponding element in the initializer list.
*/ */
class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
TTranslatedFieldValueInitialization { TTranslatedFieldValueInitialization
{
TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) } TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -700,7 +703,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
* an explicit element in an initializer list. * an explicit element in an initializer list.
*/ */
class TranslatedExplicitElementInitialization extends TranslatedElementInitialization, class TranslatedExplicitElementInitialization extends TranslatedElementInitialization,
TTranslatedExplicitElementInitialization, InitializationContext { TTranslatedExplicitElementInitialization, InitializationContext
{
int elementIndex; int elementIndex;
TranslatedExplicitElementInitialization() { TranslatedExplicitElementInitialization() {
@@ -737,7 +741,8 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
* elements without corresponding elements in the initializer list. * elements without corresponding elements in the initializer list.
*/ */
class TranslatedElementValueInitialization extends TranslatedElementInitialization, class TranslatedElementValueInitialization extends TranslatedElementInitialization,
TTranslatedElementValueInitialization { TTranslatedElementValueInitialization
{
int elementIndex; int elementIndex;
int elementCount; int elementCount;
@@ -881,7 +886,8 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
* Represents a call to a delegating or base class constructor from within a constructor. * Represents a call to a delegating or base class constructor from within a constructor.
*/ */
abstract class TranslatedConstructorCallFromConstructor extends TranslatedStructorCallFromStructor, abstract class TranslatedConstructorCallFromConstructor extends TranslatedStructorCallFromStructor,
TTranslatedConstructorBaseInit { TTranslatedConstructorBaseInit
{
TranslatedConstructorCallFromConstructor() { this = TTranslatedConstructorBaseInit(call) } TranslatedConstructorCallFromConstructor() { this = TTranslatedConstructorBaseInit(call) }
} }
@@ -917,7 +923,8 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
* derived class constructor * derived class constructor
*/ */
class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstructor, class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstructor,
TranslatedBaseStructorCall { TranslatedBaseStructorCall
{
TranslatedConstructorBaseInit() { not call instanceof ConstructorDelegationInit } TranslatedConstructorBaseInit() { not call instanceof ConstructorDelegationInit }
final override string toString() { result = "construct base: " + call.toString() } final override string toString() { result = "construct base: " + call.toString() }
@@ -934,7 +941,8 @@ TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(
* derived class destructor. * derived class destructor.
*/ */
class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall, class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall,
TTranslatedDestructorBaseDestruction { TTranslatedDestructorBaseDestruction
{
TranslatedDestructorBaseDestruction() { this = TTranslatedDestructorBaseDestruction(call) } TranslatedDestructorBaseDestruction() { this = TTranslatedDestructorBaseDestruction(call) }
final override string toString() { result = "destroy base: " + call.toString() } final override string toString() { result = "destroy base: " + call.toString() }

View File

@@ -20,7 +20,8 @@ TranslatedMicrosoftTryExceptHandler getTranslatedMicrosoftTryExceptHandler(
} }
class TranslatedMicrosoftTryExceptHandler extends TranslatedElement, class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
TTranslatedMicrosoftTryExceptHandler { TTranslatedMicrosoftTryExceptHandler
{
MicrosoftTryExceptStmt tryExcept; MicrosoftTryExceptStmt tryExcept;
TranslatedMicrosoftTryExceptHandler() { this = TTranslatedMicrosoftTryExceptHandler(tryExcept) } TranslatedMicrosoftTryExceptHandler() { this = TTranslatedMicrosoftTryExceptHandler(tryExcept) }

View File

@@ -389,7 +389,8 @@ private class NewArrayAllocationExpr extends AllocationExpr, NewArrayExpr {
private module HeuristicAllocation { private module HeuristicAllocation {
/** A class that maps an `AllocationExpr` to an `HeuristicAllocationExpr`. */ /** A class that maps an `AllocationExpr` to an `HeuristicAllocationExpr`. */
private class HeuristicAllocationModeled extends HeuristicAllocationExpr instanceof AllocationExpr { private class HeuristicAllocationModeled extends HeuristicAllocationExpr instanceof AllocationExpr
{
override Expr getSizeExpr() { result = AllocationExpr.super.getSizeExpr() } override Expr getSizeExpr() { result = AllocationExpr.super.getSizeExpr() }
override int getSizeMult() { result = AllocationExpr.super.getSizeMult() } override int getSizeMult() { result = AllocationExpr.super.getSizeMult() }
@@ -406,7 +407,8 @@ private module HeuristicAllocation {
} }
/** A class that maps an `AllocationFunction` to an `HeuristicAllocationFunction`. */ /** A class that maps an `AllocationFunction` to an `HeuristicAllocationFunction`. */
private class HeuristicAllocationFunctionModeled extends HeuristicAllocationFunction instanceof AllocationFunction { private class HeuristicAllocationFunctionModeled extends HeuristicAllocationFunction instanceof AllocationFunction
{
override int getSizeArg() { result = AllocationFunction.super.getSizeArg() } override int getSizeArg() { result = AllocationFunction.super.getSizeArg() }
override int getSizeMult() { result = AllocationFunction.super.getSizeMult() } override int getSizeMult() { result = AllocationFunction.super.getSizeMult() }
@@ -430,7 +432,8 @@ private module HeuristicAllocation {
* 2. The function must return a pointer type * 2. The function must return a pointer type
* 3. There must be a unique parameter of unsigned integral type. * 3. There must be a unique parameter of unsigned integral type.
*/ */
private class HeuristicAllocationFunctionByName extends HeuristicAllocationFunction instanceof Function { private class HeuristicAllocationFunctionByName extends HeuristicAllocationFunction instanceof Function
{
int sizeArg; int sizeArg;
HeuristicAllocationFunctionByName() { HeuristicAllocationFunctionByName() {

View File

@@ -7,7 +7,8 @@ import semmle.code.cpp.models.interfaces.FlowSource
* The standard functions `getdelim`, `getwdelim` and the glibc variant `__getdelim`. * The standard functions `getdelim`, `getwdelim` and the glibc variant `__getdelim`.
*/ */
private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction, private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction,
RemoteFlowSourceFunction { RemoteFlowSourceFunction
{
GetDelimFunction() { this.hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) } GetDelimFunction() { this.hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) }
override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) { override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) {

View File

@@ -14,7 +14,8 @@ import semmle.code.cpp.models.interfaces.FlowSource
* The standard functions `fgets` and `fgetws`. * The standard functions `fgets` and `fgetws`.
*/ */
private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction, private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
SideEffectFunction, RemoteFlowSourceFunction { SideEffectFunction, RemoteFlowSourceFunction
{
FgetsFunction() { FgetsFunction() {
// fgets(str, num, stream) // fgets(str, num, stream)
// fgetws(wstr, num, stream) // fgetws(wstr, num, stream)
@@ -69,7 +70,8 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti
* The standard functions `gets`. * The standard functions `gets`.
*/ */
private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunction, private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunction,
SideEffectFunction, LocalFlowSourceFunction { SideEffectFunction, LocalFlowSourceFunction
{
GetsFunction() { GetsFunction() {
// gets(str) // gets(str)
this.hasGlobalOrStdOrBslName("gets") this.hasGlobalOrStdOrBslName("gets")

View File

@@ -7,7 +7,8 @@ import semmle.code.cpp.models.interfaces.SideEffect
* The standard function templates `std::move` and `std::forward`. * The standard function templates `std::move` and `std::forward`.
*/ */
private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction, private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction,
FunctionTemplateInstantiation { FunctionTemplateInstantiation
{
IdentityFunction() { this.hasQualifiedName("std", ["move", "forward"]) } IdentityFunction() { this.hasQualifiedName("std", ["move", "forward"]) }
override predicate hasOnlySpecificReadSideEffects() { any() } override predicate hasOnlySpecificReadSideEffects() { any() }

View File

@@ -121,7 +121,8 @@ class IteratorCrementNonMemberOperator extends Operator {
} }
private class IteratorCrementNonMemberOperatorModel extends IteratorCrementNonMemberOperator, private class IteratorCrementNonMemberOperatorModel extends IteratorCrementNonMemberOperator,
DataFlowFunction { DataFlowFunction
{
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input = getIteratorArgumentInput(this, 0) and input = getIteratorArgumentInput(this, 0) and
output.isReturnValue() output.isReturnValue()
@@ -143,7 +144,8 @@ class IteratorCrementMemberOperator extends MemberFunction {
} }
private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOperator, private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOperator,
DataFlowFunction, TaintFunction { DataFlowFunction, TaintFunction
{
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and input.isQualifierAddress() and
output.isReturnValue() output.isReturnValue()
@@ -204,7 +206,8 @@ class IteratorBinaryArithmeticMemberOperator extends MemberFunction {
} }
private class IteratorBinaryArithmeticMemberOperatorModel extends IteratorBinaryArithmeticMemberOperator, private class IteratorBinaryArithmeticMemberOperatorModel extends IteratorBinaryArithmeticMemberOperator,
TaintFunction { TaintFunction
{
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and input.isQualifierObject() and
output.isReturnValue() output.isReturnValue()
@@ -258,7 +261,8 @@ class IteratorAssignArithmeticNonMemberOperator extends Operator {
} }
private class IteratorAssignArithmeticNonMemberOperatorModel extends IteratorAssignArithmeticNonMemberOperator, private class IteratorAssignArithmeticNonMemberOperatorModel extends IteratorAssignArithmeticNonMemberOperator,
DataFlowFunction, TaintFunction { DataFlowFunction, TaintFunction
{
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and input.isParameter(0) and
output.isReturnValue() output.isReturnValue()
@@ -289,7 +293,8 @@ class IteratorAssignArithmeticMemberOperator extends MemberFunction {
} }
private class IteratorAssignArithmeticMemberOperatorModel extends IteratorAssignArithmeticMemberOperator, private class IteratorAssignArithmeticMemberOperatorModel extends IteratorAssignArithmeticMemberOperator,
DataFlowFunction, TaintFunction { DataFlowFunction, TaintFunction
{
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and input.isQualifierAddress() and
output.isReturnValue() output.isReturnValue()
@@ -325,7 +330,8 @@ class IteratorAssignArithmeticOperator extends Function {
* non-member and member versions, use `IteratorPointerDereferenceOperator`. * non-member and member versions, use `IteratorPointerDereferenceOperator`.
*/ */
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction, class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction,
IteratorReferenceFunction { IteratorReferenceFunction
{
IteratorPointerDereferenceMemberOperator() { IteratorPointerDereferenceMemberOperator() {
this.getClassAndName("operator*") instanceof Iterator this.getClassAndName("operator*") instanceof Iterator
} }
@@ -353,7 +359,8 @@ class IteratorPointerDereferenceNonMemberOperator extends Operator, IteratorRefe
} }
private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorPointerDereferenceNonMemberOperator, private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorPointerDereferenceNonMemberOperator,
TaintFunction { TaintFunction
{
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = getIteratorArgumentInput(this, 0) and input = getIteratorArgumentInput(this, 0) and
output.isReturnValue() output.isReturnValue()
@@ -389,7 +396,8 @@ private class IteratorFieldMemberOperator extends Operator, TaintFunction {
* An `operator[]` member function of an iterator class. * An `operator[]` member function of an iterator class.
*/ */
private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction, private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction,
IteratorReferenceFunction { IteratorReferenceFunction
{
IteratorArrayMemberOperator() { this.getClassAndName("operator[]") instanceof Iterator } IteratorArrayMemberOperator() { this.getClassAndName("operator[]") instanceof Iterator }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -418,7 +426,8 @@ class IteratorAssignmentMemberOperator extends MemberFunction {
* `operator*` and use their own `operator=` to assign to the container. * `operator*` and use their own `operator=` to assign to the container.
*/ */
private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMemberOperator, private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMemberOperator,
TaintFunction { TaintFunction
{
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(0) and input.isParameterDeref(0) and
output.isQualifierObject() output.isQualifierObject()

View File

@@ -15,7 +15,8 @@ import semmle.code.cpp.models.interfaces.Taint
* `__builtin___memcpy_chk`. * `__builtin___memcpy_chk`.
*/ */
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction, private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction,
AliasFunction { AliasFunction
{
MemcpyFunction() { MemcpyFunction() {
// memcpy(dest, src, num) // memcpy(dest, src, num)
// memmove(dest, src, num) // memmove(dest, src, num)

View File

@@ -13,7 +13,8 @@ import semmle.code.cpp.models.interfaces.SideEffect
* The standard function `memset` and its assorted variants * The standard function `memset` and its assorted variants
*/ */
private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
SideEffectFunction { SideEffectFunction
{
MemsetFunction() { MemsetFunction() {
this.hasGlobalOrStdOrBslName("memset") this.hasGlobalOrStdOrBslName("memset")
or or

View File

@@ -8,7 +8,8 @@ import semmle.code.cpp.models.interfaces.SideEffect
* guaranteed to be side-effect free. * guaranteed to be side-effect free.
*/ */
private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction,
SideEffectFunction { SideEffectFunction
{
PureStrFunction() { PureStrFunction() {
this.hasGlobalOrStdOrBslName([ this.hasGlobalOrStdOrBslName([
atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr", atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr",
@@ -153,7 +154,8 @@ private class PureFunction extends TaintFunction, SideEffectFunction {
* evaluation is guaranteed to be side-effect free. * evaluation is guaranteed to be side-effect free.
*/ */
private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction, private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction,
SideEffectFunction { SideEffectFunction
{
PureMemFunction() { PureMemFunction() {
this.hasGlobalOrStdOrBslName([ this.hasGlobalOrStdOrBslName([
"memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem" "memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem"

View File

@@ -11,7 +11,8 @@ import semmle.code.cpp.models.interfaces.SideEffect
/** The function `recv` and its assorted variants */ /** The function `recv` and its assorted variants */
private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction,
RemoteFlowSourceFunction { RemoteFlowSourceFunction
{
Recv() { Recv() {
this.hasGlobalName([ this.hasGlobalName([
"recv", // recv(socket, dest, len, flags) "recv", // recv(socket, dest, len, flags)

View File

@@ -15,7 +15,8 @@ import semmle.code.cpp.models.interfaces.FlowSource
* The `scanf` family of functions. * The `scanf` family of functions.
*/ */
abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction, AliasFunction, abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction, AliasFunction,
SideEffectFunction { SideEffectFunction
{
override predicate hasArrayWithNullTerminator(int bufParam) { override predicate hasArrayWithNullTerminator(int bufParam) {
bufParam = this.(ScanfFunction).getFormatParameterIndex() bufParam = this.(ScanfFunction).getFormatParameterIndex()
} }

View File

@@ -29,7 +29,8 @@ private class SmartPtr extends Class, PointerWrapper {
* - `std::weak_ptr<T>::operator*()` * - `std::weak_ptr<T>::operator*()`
*/ */
private class PointerUnwrapperFunction extends MemberFunction, TaintFunction, DataFlowFunction, private class PointerUnwrapperFunction extends MemberFunction, TaintFunction, DataFlowFunction,
SideEffectFunction, AliasFunction { SideEffectFunction, AliasFunction
{
PointerUnwrapperFunction() { PointerUnwrapperFunction() {
exists(PointerWrapper wrapper | wrapper.getAnUnwrapperFunction() = this) exists(PointerWrapper wrapper | wrapper.getAnUnwrapperFunction() = this)
} }

View File

@@ -13,7 +13,8 @@ import semmle.code.cpp.models.interfaces.SideEffect
* The standard function `strset` and its assorted variants * The standard function `strset` and its assorted variants
*/ */
private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
SideEffectFunction { SideEffectFunction
{
StrsetFunction() { StrsetFunction() {
hasGlobalName([ hasGlobalName([
"strset", "_strset", "_strset_l", "_wcsset", "_wcsset_l", "_mbsset", "_mbsset_l", "strset", "_strset", "_strset_l", "_wcsset", "_wcsset_l", "_mbsset", "_mbsset_l",

View File

@@ -7,7 +7,8 @@ import semmle.code.cpp.models.interfaces.CommandExecution
* A function for running a command using a command interpreter. * A function for running a command using a command interpreter.
*/ */
private class SystemFunction extends CommandExecutionFunction, ArrayFunction, AliasFunction, private class SystemFunction extends CommandExecutionFunction, ArrayFunction, AliasFunction,
SideEffectFunction { SideEffectFunction
{
SystemFunction() { SystemFunction() {
hasGlobalOrStdName("system") or // system(command) hasGlobalOrStdName("system") or // system(command)
hasGlobalName("popen") or // popen(command, mode) hasGlobalName("popen") or // popen(command, mode)

View File

@@ -591,7 +591,8 @@ deprecated library class DataSensitiveExprCall extends DataSensitiveCallExpr, Ex
/** Call to a virtual function. */ /** Call to a virtual function. */
deprecated library class DataSensitiveOverriddenFunctionCall extends DataSensitiveCallExpr, deprecated library class DataSensitiveOverriddenFunctionCall extends DataSensitiveCallExpr,
FunctionCall { FunctionCall
{
DataSensitiveOverriddenFunctionCall() { DataSensitiveOverriddenFunctionCall() {
exists(getTarget().(VirtualFunction).getAnOverridingFunction()) exists(getTarget().(VirtualFunction).getAnOverridingFunction())
} }

View File

@@ -1,3 +1,7 @@
## 0.5.4
No user-facing changes.
## 0.5.3 ## 0.5.3
No user-facing changes. No user-facing changes.

View File

@@ -1,11 +1,11 @@
int write_default_config_bad() { void write_default_config_bad() {
// BAD - this is world-writable so any user can overwrite the config // BAD - this is world-writable so any user can overwrite the config
FILE* out = creat(OUTFILE, 0666); int out = creat(OUTFILE, 0666);
fprintf(out, DEFAULT_CONFIG); dprintf(out, DEFAULT_CONFIG);
} }
int write_default_config_good() { void write_default_config_good() {
// GOOD - this allows only the current user to modify the file // GOOD - this allows only the current user to modify the file
FILE* out = creat(OUTFILE, S_IWUSR | S_IRUSR); int out = creat(OUTFILE, S_IWUSR | S_IRUSR);
fprintf(out, DEFAULT_CONFIG); dprintf(out, DEFAULT_CONFIG);
} }

View File

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

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.5.3 lastReleaseVersion: 0.5.4

View File

@@ -14,8 +14,8 @@ import cpp
from FunctionCall fc, FunctionCall fc2, LocalScopeVariable v from FunctionCall fc, FunctionCall fc2, LocalScopeVariable v
where where
freeCall(fc, v.getAnAccess()) and fc.(DeallocationExpr).getFreedExpr() = v.getAnAccess() and
freeCall(fc2, v.getAnAccess()) and fc2.(DeallocationExpr).getFreedExpr() = v.getAnAccess() and
fc != fc2 and fc != fc2 and
fc.getASuccessor*() = fc2 and fc.getASuccessor*() = fc2 and
not exists(Expr exptmp | not exists(Expr exptmp |

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 0.5.4-dev version: 0.5.5-dev
groups: groups:
- cpp - cpp
- queries - queries

View File

@@ -1,14 +1,14 @@
| CPP-205.cpp:0:0:0:0 | CPP-205.cpp | | | CPP-205.cpp:0:0:0:0 | CPP-205.cpp | |
| CPP-205.cpp:1:20:1:20 | T | | | CPP-205.cpp:1:20:1:20 | T | |
| CPP-205.cpp:1:20:1:20 | definition of T | | | CPP-205.cpp:1:20:1:20 | definition of T | |
| CPP-205.cpp:2:5:2:5 | definition of fn | function declaration entry for fn<int>(int) -> int | | CPP-205.cpp:2:5:2:5 | definition of fn | function declaration entry for int fn<int>(int) |
| CPP-205.cpp:2:5:2:5 | fn | function fn<int>(int) -> int | | CPP-205.cpp:2:5:2:5 | fn | function int fn<int>(int) |
| CPP-205.cpp:2:5:2:6 | definition of fn | function declaration entry for fn<T>(T) -> int | | CPP-205.cpp:2:5:2:6 | definition of fn | function declaration entry for int fn<T>(T) |
| CPP-205.cpp:2:5:2:6 | fn | function fn<T>(T) -> int | | CPP-205.cpp:2:5:2:6 | fn | function int fn<T>(T) |
| CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for fn<T>(T) -> int | | CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for int fn<T>(T) |
| CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for fn<int>(int) -> int | | CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for int fn<int>(int) |
| CPP-205.cpp:2:10:2:12 | out | parameter for fn<T>(T) -> int | | CPP-205.cpp:2:10:2:12 | out | parameter for int fn<T>(T) |
| CPP-205.cpp:2:10:2:12 | out | parameter for fn<int>(int) -> int | | CPP-205.cpp:2:10:2:12 | out | parameter for int fn<int>(int) |
| CPP-205.cpp:2:15:5:1 | { ... } | | | CPP-205.cpp:2:15:5:1 | { ... } | |
| CPP-205.cpp:2:15:5:1 | { ... } | | | CPP-205.cpp:2:15:5:1 | { ... } | |
| CPP-205.cpp:3:3:3:33 | declaration | | | CPP-205.cpp:3:3:3:33 | declaration | |
@@ -20,16 +20,16 @@
| CPP-205.cpp:4:3:4:11 | return ... | | | CPP-205.cpp:4:3:4:11 | return ... | |
| CPP-205.cpp:4:10:4:10 | 0 | | | CPP-205.cpp:4:10:4:10 | 0 | |
| CPP-205.cpp:4:10:4:10 | 0 | | | CPP-205.cpp:4:10:4:10 | 0 | |
| CPP-205.cpp:7:5:7:8 | definition of main | function declaration entry for main() -> int | | CPP-205.cpp:7:5:7:8 | definition of main | function declaration entry for int main() |
| CPP-205.cpp:7:5:7:8 | main | function main() -> int | | CPP-205.cpp:7:5:7:8 | main | function int main() |
| CPP-205.cpp:7:12:9:1 | { ... } | | | CPP-205.cpp:7:12:9:1 | { ... } | |
| CPP-205.cpp:8:3:8:15 | return ... | | | CPP-205.cpp:8:3:8:15 | return ... | |
| CPP-205.cpp:8:10:8:11 | call to fn | | | CPP-205.cpp:8:10:8:11 | call to fn | |
| CPP-205.cpp:8:13:8:13 | 0 | | | CPP-205.cpp:8:13:8:13 | 0 | |
| file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag::operator=(__va_list_tag &&) -> __va_list_tag & | | file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) |
| file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag::operator=(const __va_list_tag &) -> __va_list_tag & | | file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) |
| file://:0:0:0:0 | __super | | | file://:0:0:0:0 | __super | |
| file://:0:0:0:0 | __va_list_tag | | | file://:0:0:0:0 | __va_list_tag | |
| file://:0:0:0:0 | operator= | function __va_list_tag::operator=(__va_list_tag &&) -> __va_list_tag & | | file://:0:0:0:0 | operator= | function __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) |
| file://:0:0:0:0 | operator= | function __va_list_tag::operator=(const __va_list_tag &) -> __va_list_tag & | | file://:0:0:0:0 | operator= | function __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) |
| file://:0:0:0:0 | y | | | file://:0:0:0:0 | y | |

View File

@@ -1,17 +1,19 @@
import cpp import cpp
import semmle.code.cpp.Print
string describe(Element e) { string describe(Element e) {
result = "function " + e.(Function).getFullSignature() e instanceof Function and
result = "function " + getIdentityString(e)
or or
result = result =
"function declaration entry for " + "function declaration entry for " +
e.(FunctionDeclarationEntry).getFunction().getFullSignature() getIdentityString(e.(FunctionDeclarationEntry).getFunction())
or or
result = "parameter for " + e.(Parameter).getFunction().getFullSignature() result = "parameter for " + getIdentityString(e.(Parameter).getFunction())
or or
result = result =
"parameter declaration entry for " + "parameter declaration entry for " +
e.(ParameterDeclarationEntry).getFunctionDeclarationEntry().getFunction().getFullSignature() getIdentityString(e.(ParameterDeclarationEntry).getFunctionDeclarationEntry().getFunction())
} }
from Element e from Element e

View File

@@ -1,51 +1,51 @@
newExprs newExprs
| allocators.cpp:49:3:49:9 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | | | allocators.cpp:49:3:49:9 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
| allocators.cpp:50:3:50:15 | new | int | operator new(size_t, float) -> void * | 4 | 4 | | | | allocators.cpp:50:3:50:15 | new | int | void* operator new(size_t, float) | 4 | 4 | | |
| allocators.cpp:51:3:51:11 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | | | allocators.cpp:51:3:51:11 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
| allocators.cpp:52:3:52:14 | new | String | operator new(unsigned long) -> void * | 8 | 8 | | | | allocators.cpp:52:3:52:14 | new | String | void* operator new(unsigned long) | 8 | 8 | | |
| allocators.cpp:53:3:53:27 | new | String | operator new(size_t, float) -> void * | 8 | 8 | | | | allocators.cpp:53:3:53:27 | new | String | void* operator new(size_t, float) | 8 | 8 | | |
| allocators.cpp:54:3:54:17 | new | Overaligned | operator new(unsigned long, align_val_t) -> void * | 256 | 128 | aligned | | | allocators.cpp:54:3:54:17 | new | Overaligned | void* operator new(unsigned long, std::align_val_t) | 256 | 128 | aligned | |
| allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned | | | allocators.cpp:55:3:55:25 | new | Overaligned | void* operator new(size_t, std::align_val_t, float) | 256 | 128 | aligned | |
| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | | | | allocators.cpp:107:3:107:18 | new | FailedInit | void* FailedInit::operator new(size_t) | 1 | 1 | | |
| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | | allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | void* FailedInitOveraligned::operator new(size_t, std::align_val_t, float) | 128 | 128 | aligned | |
| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | | & ... | | allocators.cpp:129:3:129:21 | new | int | void* operator new(std::size_t, void*) | 4 | 4 | | & ... |
| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | | | | allocators.cpp:135:3:135:26 | new | int | void* operator new(std::size_t, std::nothrow_t const&) | 4 | 4 | | |
newArrayExprs newArrayExprs
| allocators.cpp:68:3:68:12 | new[] | int[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | n | | | allocators.cpp:68:3:68:12 | new[] | int[] | int | void* operator new[](unsigned long) | 4 | 4 | | n | |
| allocators.cpp:69:3:69:18 | new[] | int[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | n | | | allocators.cpp:69:3:69:18 | new[] | int[] | int | void* operator new[](size_t, float) | 4 | 4 | | n | |
| allocators.cpp:70:3:70:15 | new[] | String[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | n | | | allocators.cpp:70:3:70:15 | new[] | String[] | String | void* operator new[](unsigned long) | 8 | 8 | | n | |
| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | operator new[](unsigned long, align_val_t) -> void * | 256 | 128 | aligned | n | | | allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | void* operator new[](unsigned long, std::align_val_t) | 256 | 128 | aligned | n | |
| allocators.cpp:72:3:72:16 | new[] | String[10] | String | operator new[](unsigned long) -> void * | 8 | 8 | | | | | allocators.cpp:72:3:72:16 | new[] | String[10] | String | void* operator new[](unsigned long) | 8 | 8 | | | |
| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | n | | | allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | void* FailedInit::operator new[](size_t) | 1 | 1 | | n | |
| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | | | allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | void* FailedInitOveraligned::operator new[](size_t, std::align_val_t, float) | 128 | 128 | aligned | | |
| allocators.cpp:132:3:132:17 | new[] | int[1] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | | buf | | allocators.cpp:132:3:132:17 | new[] | int[1] | int | void* operator new[](std::size_t, void*) | 4 | 4 | | | buf |
| allocators.cpp:136:3:136:26 | new[] | int[2] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | | | | allocators.cpp:136:3:136:26 | new[] | int[2] | int | void* operator new[](std::size_t, std::nothrow_t const&) | 4 | 4 | | | |
| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | operator new[](unsigned long) -> void * | 10 | 1 | | x | | | allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | void* operator new[](unsigned long) | 10 | 1 | | x | |
| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | operator new[](unsigned long) -> void * | 20 | 1 | | | | | allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | void* operator new[](unsigned long) | 20 | 1 | | | |
| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | operator new[](unsigned long) -> void * | 900 | 1 | | x | | | allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | void* operator new[](unsigned long) | 900 | 1 | | x | |
newExprDeallocators newExprDeallocators
| allocators.cpp:52:3:52:14 | new | String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:52:3:52:14 | new | String | void operator delete(void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:53:3:53:27 | new | String | operator delete(void *, float) -> void | 8 | 8 | | | allocators.cpp:53:3:53:27 | new | String | void operator delete(void*, float) | 8 | 8 | |
| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator delete(void *, size_t) -> void | 1 | 1 | sized | | allocators.cpp:107:3:107:18 | new | FailedInit | void FailedInit::operator delete(void*, size_t) | 1 | 1 | sized |
| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator delete(void *, align_val_t, float) -> void | 128 | 128 | aligned | | allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | void FailedInitOveraligned::operator delete(void*, std::align_val_t, float) | 128 | 128 | aligned |
newArrayExprDeallocators newArrayExprDeallocators
| allocators.cpp:70:3:70:15 | new[] | String | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:70:3:70:15 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:72:3:72:16 | new[] | String | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:72:3:72:16 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:108:3:108:19 | new[] | FailedInit | FailedInit::operator delete[](void *, size_t) -> void | 1 | 1 | sized | | allocators.cpp:108:3:108:19 | new[] | FailedInit | void FailedInit::operator delete[](void*, size_t) | 1 | 1 | sized |
| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned | FailedInitOveraligned::operator delete[](void *, align_val_t, float) -> void | 128 | 128 | aligned | | allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned | void FailedInitOveraligned::operator delete[](void*, std::align_val_t, float) | 128 | 128 | aligned |
deleteExprs deleteExprs
| allocators.cpp:59:3:59:35 | delete | int | operator delete(void *, unsigned long) -> void | 4 | 4 | sized | | allocators.cpp:59:3:59:35 | delete | int | void operator delete(void*, unsigned long) | 4 | 4 | sized |
| allocators.cpp:60:3:60:38 | delete | String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:60:3:60:38 | delete | String | void operator delete(void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:61:3:61:44 | delete | SizedDealloc | SizedDealloc::operator delete(void *, size_t) -> void | 32 | 1 | sized | | allocators.cpp:61:3:61:44 | delete | SizedDealloc | void SizedDealloc::operator delete(void*, size_t) | 32 | 1 | sized |
| allocators.cpp:62:3:62:43 | delete | Overaligned | operator delete(void *, unsigned long, align_val_t) -> void | 256 | 128 | sized aligned | | allocators.cpp:62:3:62:43 | delete | Overaligned | void operator delete(void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned |
| allocators.cpp:64:3:64:44 | delete | const String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:64:3:64:44 | delete | const String | void operator delete(void*, unsigned long) | 8 | 8 | sized |
deleteArrayExprs deleteArrayExprs
| allocators.cpp:78:3:78:37 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized | | allocators.cpp:78:3:78:37 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
| allocators.cpp:79:3:79:40 | delete[] | String | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:79:3:79:40 | delete[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:80:3:80:46 | delete[] | SizedDealloc | SizedDealloc::operator delete[](void *, size_t) -> void | 32 | 1 | sized | | allocators.cpp:80:3:80:46 | delete[] | SizedDealloc | void SizedDealloc::operator delete[](void*, size_t) | 32 | 1 | sized |
| allocators.cpp:81:3:81:45 | delete[] | Overaligned | operator delete[](void *, unsigned long, align_val_t) -> void | 256 | 128 | sized aligned | | allocators.cpp:81:3:81:45 | delete[] | Overaligned | void operator delete[](void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned |
| allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
| allocators.cpp:83:3:83:23 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized | | allocators.cpp:83:3:83:23 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
allocationFunctions allocationFunctions
| allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc | | allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc |
| allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc | | allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc |

View File

@@ -1,12 +1,13 @@
import cpp import cpp
import semmle.code.cpp.models.implementations.Allocation import semmle.code.cpp.models.implementations.Allocation
import semmle.code.cpp.Print
query predicate newExprs( query predicate newExprs(
NewExpr expr, string type, string sig, int size, int alignment, string form, string placement NewExpr expr, string type, string sig, int size, int alignment, string form, string placement
) { ) {
exists(Function allocator, Type allocatedType | exists(Function allocator, Type allocatedType |
expr.getAllocator() = allocator and expr.getAllocator() = allocator and
sig = allocator.getFullSignature() and sig = getIdentityString(allocator) and
allocatedType = expr.getAllocatedType() and allocatedType = expr.getAllocatedType() and
type = allocatedType.toString() and type = allocatedType.toString() and
size = allocatedType.getSize() and size = allocatedType.getSize() and
@@ -24,7 +25,7 @@ query predicate newArrayExprs(
) { ) {
exists(Function allocator, Type arrayType, Type elementType | exists(Function allocator, Type arrayType, Type elementType |
expr.getAllocator() = allocator and expr.getAllocator() = allocator and
sig = allocator.getFullSignature() and sig = getIdentityString(allocator) and
arrayType = expr.getAllocatedType() and arrayType = expr.getAllocatedType() and
t1 = arrayType.toString() and t1 = arrayType.toString() and
elementType = expr.getAllocatedElementType() and elementType = expr.getAllocatedElementType() and
@@ -44,7 +45,7 @@ query predicate newExprDeallocators(
) { ) {
exists(Function deallocator, Type allocatedType | exists(Function deallocator, Type allocatedType |
expr.getDeallocator() = deallocator and expr.getDeallocator() = deallocator and
sig = deallocator.getFullSignature() and sig = getIdentityString(deallocator) and
allocatedType = expr.getAllocatedType() and allocatedType = expr.getAllocatedType() and
type = allocatedType.toString() and type = allocatedType.toString() and
size = allocatedType.getSize() and size = allocatedType.getSize() and
@@ -62,7 +63,7 @@ query predicate newArrayExprDeallocators(
) { ) {
exists(Function deallocator, Type elementType | exists(Function deallocator, Type elementType |
expr.getDeallocator() = deallocator and expr.getDeallocator() = deallocator and
sig = deallocator.getFullSignature() and sig = getIdentityString(deallocator) and
elementType = expr.getAllocatedElementType() and elementType = expr.getAllocatedElementType() and
type = elementType.toString() and type = elementType.toString() and
size = elementType.getSize() and size = elementType.getSize() and
@@ -80,7 +81,7 @@ query predicate deleteExprs(
) { ) {
exists(Function deallocator, Type deletedType | exists(Function deallocator, Type deletedType |
expr.getDeallocator() = deallocator and expr.getDeallocator() = deallocator and
sig = deallocator.getFullSignature() and sig = getIdentityString(deallocator) and
deletedType = expr.getDeletedObjectType() and deletedType = expr.getDeletedObjectType() and
type = deletedType.toString() and type = deletedType.toString() and
size = deletedType.getSize() and size = deletedType.getSize() and
@@ -98,7 +99,7 @@ query predicate deleteArrayExprs(
) { ) {
exists(Function deallocator, Type elementType | exists(Function deallocator, Type elementType |
expr.getDeallocator() = deallocator and expr.getDeallocator() = deallocator and
sig = deallocator.getFullSignature() and sig = getIdentityString(deallocator) and
elementType = expr.getDeletedElementType() and elementType = expr.getDeletedElementType() and
type = elementType.toString() and type = elementType.toString() and
size = elementType.getSize() and size = elementType.getSize() and

View File

@@ -1,30 +1,30 @@
| copy_from_prototype.cpp:3:7:3:7 | a | a<int>::a(a<int> &&) -> void | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> | | copy_from_prototype.cpp:3:7:3:7 | a | void a<int>::a(a<int> const&) | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:3:7:3:7 | a | a<int>::a(const a<int> &) -> void | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> | | copy_from_prototype.cpp:3:7:3:7 | a | void a<int>::a(a<int>&&) | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:3:7:3:7 | operator= | a<int>::operator=(a<int> &&) -> a<int> & | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> | | copy_from_prototype.cpp:3:7:3:7 | operator= | a<int>& a<int>::operator=(a<int> const&) | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:3:7:3:7 | operator= | a<int>::operator=(const a<int> &) -> a<int> & | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> | | copy_from_prototype.cpp:3:7:3:7 | operator= | a<int>& a<int>::operator=(a<int>&&) | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:4:26:4:26 | a | a<<unnamed>>::a<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:3:7:3:7 | a<<unnamed>> | 123 | | copy_from_prototype.cpp:4:26:4:26 | a | void a<(unnamed template parameter)>::a<(unnamed template parameter)>() | copy_from_prototype.cpp:3:7:3:7 | a<<unnamed>> | 123 |
| copy_from_prototype.cpp:4:26:4:26 | a | a<int>::a<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> | | copy_from_prototype.cpp:4:26:4:26 | a | void a<int>::a<(unnamed template parameter)>() | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:7:7:7:7 | b | b::b() -> void | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> | | copy_from_prototype.cpp:7:7:7:7 | b | void b::b() | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
| copy_from_prototype.cpp:7:7:7:7 | b | b::b(b &&) -> void | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> | | copy_from_prototype.cpp:7:7:7:7 | b | void b::b(b const&) | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
| copy_from_prototype.cpp:7:7:7:7 | b | b::b(const b &) -> void | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> | | copy_from_prototype.cpp:7:7:7:7 | b | void b::b(b&&) | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
| copy_from_prototype.cpp:7:7:7:7 | operator= | b::operator=(b &&) -> b & | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> | | copy_from_prototype.cpp:7:7:7:7 | operator= | b& b::operator=(b const&) | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
| copy_from_prototype.cpp:7:7:7:7 | operator= | b::operator=(const b &) -> b & | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> | | copy_from_prototype.cpp:7:7:7:7 | operator= | b& b::operator=(b&&) | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
| copy_from_prototype.cpp:13:7:13:7 | c | c<int>::c(c<int> &&) -> void | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> | | copy_from_prototype.cpp:13:7:13:7 | c | void c<int>::c(c<int> const&) | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:13:7:13:7 | c | c<int>::c(const c<int> &) -> void | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> | | copy_from_prototype.cpp:13:7:13:7 | c | void c<int>::c(c<int>&&) | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:13:7:13:7 | operator= | c<int>::operator=(c<int> &&) -> c<int> & | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> | | copy_from_prototype.cpp:13:7:13:7 | operator= | c<int>& c<int>::operator=(c<int> const&) | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:13:7:13:7 | operator= | c<int>::operator=(const c<int> &) -> c<int> & | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> | | copy_from_prototype.cpp:13:7:13:7 | operator= | c<int>& c<int>::operator=(c<int>&&) | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:14:26:14:26 | c | c<T>::c<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c<T> | X | | copy_from_prototype.cpp:14:26:14:26 | c | void c<T>::c<(unnamed template parameter)>() | copy_from_prototype.cpp:13:7:13:7 | c<T> | X |
| copy_from_prototype.cpp:14:26:14:26 | c | c<int>::c<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> | | copy_from_prototype.cpp:14:26:14:26 | c | void c<int>::c<(unnamed template parameter)>() | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:17:7:17:7 | d | d::d() -> void | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> | | copy_from_prototype.cpp:17:7:17:7 | d | void d::d() | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
| copy_from_prototype.cpp:17:7:17:7 | d | d::d(const d &) -> void | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> | | copy_from_prototype.cpp:17:7:17:7 | d | void d::d(d const&) | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
| copy_from_prototype.cpp:17:7:17:7 | d | d::d(d &&) -> void | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> | | copy_from_prototype.cpp:17:7:17:7 | d | void d::d(d&&) | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
| copy_from_prototype.cpp:17:7:17:7 | operator= | d::operator=(const d &) -> d & | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> | | copy_from_prototype.cpp:17:7:17:7 | operator= | d& d::operator=(d const&) | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
| copy_from_prototype.cpp:17:7:17:7 | operator= | d::operator=(d &&) -> d & | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> | | copy_from_prototype.cpp:17:7:17:7 | operator= | d& d::operator=(d&&) | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
| copy_from_prototype.cpp:22:8:22:8 | e | e<int>::e(const e<int> &) -> void | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> | | copy_from_prototype.cpp:22:8:22:8 | e | void e<int>::e(e<int> const&) | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> |
| copy_from_prototype.cpp:22:8:22:8 | e | e<int>::e(e<int> &&) -> void | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> | | copy_from_prototype.cpp:22:8:22:8 | e | void e<int>::e(e<int>&&) | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> |
| copy_from_prototype.cpp:22:8:22:8 | operator= | e<int>::operator=(const e<int> &) -> e<int> & | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> | | copy_from_prototype.cpp:22:8:22:8 | operator= | e<int>& e<int>::operator=(e<int> const&) | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> |
| copy_from_prototype.cpp:22:8:22:8 | operator= | e<int>::operator=(e<int> &&) -> e<int> & | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> | | copy_from_prototype.cpp:22:8:22:8 | operator= | e<int>& e<int>::operator=(e<int>&&) | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> |
| copy_from_prototype.cpp:23:26:23:26 | e | e<T>::e<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:22:8:22:8 | e<T> | 456 | | copy_from_prototype.cpp:23:26:23:26 | e | void e<T>::e<(unnamed template parameter)>() | copy_from_prototype.cpp:22:8:22:8 | e<T> | 456 |
| copy_from_prototype.cpp:26:35:26:43 | e | e<int>::e<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:22:8:22:8 | e<int> | 456 | | copy_from_prototype.cpp:26:35:26:43 | e | void e<int>::e<(unnamed template parameter)>() | copy_from_prototype.cpp:22:8:22:8 | e<int> | 456 |
| file://:0:0:0:0 | operator= | __va_list_tag::operator=(__va_list_tag &&) -> __va_list_tag & | file://:0:0:0:0 | __va_list_tag | <none> | | file://:0:0:0:0 | operator= | __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) | file://:0:0:0:0 | __va_list_tag | <none> |
| file://:0:0:0:0 | operator= | __va_list_tag::operator=(const __va_list_tag &) -> __va_list_tag & | file://:0:0:0:0 | __va_list_tag | <none> | | file://:0:0:0:0 | operator= | __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) | file://:0:0:0:0 | __va_list_tag | <none> |

View File

@@ -1,4 +1,5 @@
import cpp import cpp
import semmle.code.cpp.Print
from Function f, string e from Function f, string e
where where
@@ -8,4 +9,4 @@ where
then e = f.getADeclarationEntry().getNoExceptExpr().toString() then e = f.getADeclarationEntry().getNoExceptExpr().toString()
else e = "<no expr>" else e = "<no expr>"
else e = "<none>" else e = "<none>"
select f, f.getFullSignature(), f.getDeclaringType(), e select f, getIdentityString(f), f.getDeclaringType(), e

View File

@@ -19,3 +19,6 @@
| test.cpp:302:8:302:12 | ptr_i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:301:3:301:7 | call to scanf | call to scanf | | test.cpp:302:8:302:12 | ptr_i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:301:3:301:7 | call to scanf | call to scanf |
| test.cpp:310:7:310:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:309:3:309:7 | call to scanf | call to scanf | | test.cpp:310:7:310:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:309:3:309:7 | call to scanf | call to scanf |
| test.cpp:404:25:404:25 | u | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:403:6:403:11 | call to sscanf | call to sscanf | | test.cpp:404:25:404:25 | u | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:403:6:403:11 | call to sscanf | call to sscanf |
| test.cpp:416:7:416:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:413:7:413:11 | call to scanf | call to scanf |
| test.cpp:423:7:423:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:420:7:420:11 | call to scanf | call to scanf |
| test.cpp:430:6:430:6 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:429:2:429:6 | call to scanf | call to scanf |

View File

@@ -406,3 +406,26 @@ char *my_string_copy() {
*ptr++ = 0; *ptr++ = 0;
return DST_STRING; return DST_STRING;
} }
void scan_and_write() {
{
int i;
if (scanf("%d", &i) < 1) {
i = 0;
}
use(i); // GOOD [FALSE POSITIVE]: variable is overwritten with a default value when scanf fails
}
{
int i;
if (scanf("%d", &i) != 1) {
i = 0;
}
use(i); // GOOD [FALSE POSITIVE]: variable is overwritten with a default value when scanf fails
}
}
void scan_and_static_variable() {
static int i;
scanf("%d", &i);
use(i); // GOOD [FALSE POSITIVE]: static variables are always 0-initialized
}

View File

@@ -1,5 +1,6 @@
using Xunit; using Xunit;
using Semmle.Autobuild.Shared; using Semmle.Autobuild.Shared;
using Semmle.Util;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
using System.Linq; using System.Linq;
@@ -85,6 +86,15 @@ namespace Semmle.Autobuild.CSharp.Tests
return ret; return ret;
} }
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? env, BuildOutputHandler onOutput, BuildOutputHandler onError)
{
var ret = (this as IBuildActions).RunProcess(cmd, args, workingDirectory, env, out var stdout);
stdout.ForEach(line => onOutput(line));
return ret;
}
public IList<string> DirectoryDeleteIn { get; } = new List<string>(); public IList<string> DirectoryDeleteIn { get; } = new List<string>();
void IBuildActions.DirectoryDelete(string dir, bool recursive) void IBuildActions.DirectoryDelete(string dir, bool recursive)
@@ -200,6 +210,16 @@ namespace Semmle.Autobuild.CSharp.Tests
if (!DownloadFiles.Contains((address, fileName))) if (!DownloadFiles.Contains((address, fileName)))
throw new ArgumentException($"Missing DownloadFile, {address}, {fileName}"); throw new ArgumentException($"Missing DownloadFile, {address}, {fileName}");
} }
public IDiagnosticsWriter CreateDiagnosticsWriter(string filename) => new TestDiagnosticWriter();
}
internal class TestDiagnosticWriter : IDiagnosticsWriter
{
public IList<DiagnosticMessage> Diagnostics { get; } = new List<DiagnosticMessage>();
public void AddEntry(DiagnosticMessage message) => this.Diagnostics.Add(message);
} }
/// <summary> /// <summary>
@@ -391,6 +411,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_TRAP_DIR"] = ""; actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_TRAP_DIR"] = "";
actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_SOURCE_ARCHIVE_DIR"] = ""; actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_SOURCE_ARCHIVE_DIR"] = "";
actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_ROOT"] = $@"C:\codeql\{codeqlUpperLanguage.ToLowerInvariant()}"; actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_ROOT"] = $@"C:\codeql\{codeqlUpperLanguage.ToLowerInvariant()}";
actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_DIAGNOSTIC_DIR"] = "";
actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java"; actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java";
actions.GetEnvironmentVariable["CODEQL_PLATFORM"] = isWindows ? "win64" : "linux64"; actions.GetEnvironmentVariable["CODEQL_PLATFORM"] = isWindows ? "win64" : "linux64";
actions.GetEnvironmentVariable["LGTM_INDEX_VSTOOLS_VERSION"] = vsToolsVersion; actions.GetEnvironmentVariable["LGTM_INDEX_VSTOOLS_VERSION"] = vsToolsVersion;

View File

@@ -0,0 +1,69 @@
using Semmle.Autobuild.Shared;
using Semmle.Extraction.CSharp;
namespace Semmle.Autobuild.CSharp
{
internal class AutoBuildRule : IBuildRule<CSharpAutobuildOptions>
{
private readonly CSharpAutobuilder autobuilder;
public DotNetRule DotNetRule { get; }
public MsBuildRule MsBuildRule { get; }
public BuildCommandAutoRule BuildCommandAutoRule { get; }
public AutoBuildRule(CSharpAutobuilder autobuilder)
{
this.autobuilder = autobuilder;
this.DotNetRule = new DotNetRule();
this.MsBuildRule = new MsBuildRule();
this.BuildCommandAutoRule = new BuildCommandAutoRule(DotNetRule.WithDotNet);
}
public BuildScript Analyse(IAutobuilder<CSharpAutobuildOptions> builder, bool auto)
{
var cleanTrapFolder =
BuildScript.DeleteDirectory(this.autobuilder.TrapDir);
var cleanSourceArchive =
BuildScript.DeleteDirectory(this.autobuilder.SourceArchiveDir);
var tryCleanExtractorArgsLogs =
BuildScript.Create(actions =>
{
foreach (var file in Extractor.GetCSharpArgsLogs())
{
try
{
actions.FileDelete(file);
}
catch // lgtm[cs/catch-of-all-exceptions] lgtm[cs/empty-catch-block]
{ }
}
return 0;
});
var attemptExtractorCleanup =
BuildScript.Try(cleanTrapFolder) &
BuildScript.Try(cleanSourceArchive) &
tryCleanExtractorArgsLogs &
BuildScript.DeleteFile(Extractor.GetCSharpLogPath());
/// <summary>
/// Execute script `s` and check that the C# extractor has been executed.
/// If either fails, attempt to cleanup any artifacts produced by the extractor,
/// and exit with code 1, in order to proceed to the next attempt.
/// </summary>
BuildScript IntermediateAttempt(BuildScript s) =>
(s & this.autobuilder.CheckExtractorRun(false)) |
(attemptExtractorCleanup & BuildScript.Failure);
return
// First try .NET Core
IntermediateAttempt(this.DotNetRule.Analyse(this.autobuilder, true)) |
// Then MSBuild
(() => IntermediateAttempt(this.MsBuildRule.Analyse(this.autobuilder, true))) |
// And finally look for a script that might be a build script
(() => this.BuildCommandAutoRule.Analyse(this.autobuilder, true) & this.autobuilder.CheckExtractorRun(true));
}
}
}

View File

@@ -1,6 +1,8 @@
using Semmle.Extraction.CSharp; using Semmle.Extraction.CSharp;
using Semmle.Util.Logging; using Semmle.Util.Logging;
using Semmle.Autobuild.Shared; using Semmle.Autobuild.Shared;
using Semmle.Util;
using System.Linq;
namespace Semmle.Autobuild.CSharp namespace Semmle.Autobuild.CSharp
{ {
@@ -29,25 +31,16 @@ namespace Semmle.Autobuild.CSharp
public class CSharpAutobuilder : Autobuilder<CSharpAutobuildOptions> public class CSharpAutobuilder : Autobuilder<CSharpAutobuildOptions>
{ {
public CSharpAutobuilder(IBuildActions actions, CSharpAutobuildOptions options) : base(actions, options) { } private const string buildCommandDocsUrl =
"https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages";
private readonly AutoBuildRule autoBuildRule;
public CSharpAutobuilder(IBuildActions actions, CSharpAutobuildOptions options) : base(actions, options, new CSharpDiagnosticClassifier()) =>
this.autoBuildRule = new AutoBuildRule(this);
public override BuildScript GetBuildScript() public override BuildScript GetBuildScript()
{ {
/// <summary>
/// A script that checks that the C# extractor has been executed.
/// </summary>
BuildScript CheckExtractorRun(bool warnOnFailure) =>
BuildScript.Create(actions =>
{
if (actions.FileExists(Extractor.GetCSharpLogPath()))
return 0;
if (warnOnFailure)
Log(Severity.Error, "No C# code detected during build.");
return 1;
});
var attempt = BuildScript.Failure; var attempt = BuildScript.Failure;
switch (GetCSharpBuildStrategy()) switch (GetCSharpBuildStrategy())
{ {
@@ -65,47 +58,9 @@ namespace Semmle.Autobuild.CSharp
attempt = new DotNetRule().Analyse(this, false) & CheckExtractorRun(true); attempt = new DotNetRule().Analyse(this, false) & CheckExtractorRun(true);
break; break;
case CSharpBuildStrategy.Auto: case CSharpBuildStrategy.Auto:
var cleanTrapFolder =
BuildScript.DeleteDirectory(TrapDir);
var cleanSourceArchive =
BuildScript.DeleteDirectory(SourceArchiveDir);
var tryCleanExtractorArgsLogs =
BuildScript.Create(actions =>
{
foreach (var file in Extractor.GetCSharpArgsLogs())
{
try
{
actions.FileDelete(file);
}
catch // lgtm[cs/catch-of-all-exceptions] lgtm[cs/empty-catch-block]
{ }
}
return 0;
});
var attemptExtractorCleanup =
BuildScript.Try(cleanTrapFolder) &
BuildScript.Try(cleanSourceArchive) &
tryCleanExtractorArgsLogs &
BuildScript.DeleteFile(Extractor.GetCSharpLogPath());
/// <summary>
/// Execute script `s` and check that the C# extractor has been executed.
/// If either fails, attempt to cleanup any artifacts produced by the extractor,
/// and exit with code 1, in order to proceed to the next attempt.
/// </summary>
BuildScript IntermediateAttempt(BuildScript s) =>
(s & CheckExtractorRun(false)) |
(attemptExtractorCleanup & BuildScript.Failure);
attempt = attempt =
// First try .NET Core // Attempt a few different build strategies to see if one works
IntermediateAttempt(new DotNetRule().Analyse(this, true)) | this.autoBuildRule.Analyse(this, true) |
// Then MSBuild
(() => IntermediateAttempt(new MsBuildRule().Analyse(this, true))) |
// And finally look for a script that might be a build script
(() => new BuildCommandAutoRule(DotNetRule.WithDotNet).Analyse(this, true) & CheckExtractorRun(true)) |
// All attempts failed: print message // All attempts failed: print message
AutobuildFailure(); AutobuildFailure();
break; break;
@@ -114,6 +69,127 @@ namespace Semmle.Autobuild.CSharp
return attempt; return attempt;
} }
/// <summary>
/// A script that checks that the C# extractor has been executed.
/// </summary>
public BuildScript CheckExtractorRun(bool warnOnFailure) =>
BuildScript.Create(actions =>
{
if (actions.FileExists(Extractor.GetCSharpLogPath()))
return 0;
if (warnOnFailure)
Log(Severity.Error, "No C# code detected during build.");
return 1;
});
protected override void AutobuildFailureDiagnostic()
{
// if `ScriptPath` is not null here, the `BuildCommandAuto` rule was
// run and found at least one script to execute
if (this.autoBuildRule.BuildCommandAutoRule.ScriptPath is not null)
{
var relScriptPath = this.MakeRelative(autoBuildRule.BuildCommandAutoRule.ScriptPath);
// if we found multiple build scripts in the project directory, then we can say
// as much to indicate that we may have picked the wrong one;
// otherwise, we just report that the one script we found didn't work
DiagnosticMessage message =
this.autoBuildRule.BuildCommandAutoRule.CandidatePaths.Count() > 1 ?
new(
this.Options.Language,
"multiple-build-scripts",
"There are multiple potential build scripts",
markdownMessage:
"CodeQL found multiple potential build scripts for your project and " +
$"attempted to run `{relScriptPath}`, which failed. " +
"This may not be the right build script for your project. " +
$"Set up a [manual build command]({buildCommandDocsUrl})."
) :
new(
this.Options.Language,
"script-failure",
"Unable to build project using build script",
markdownMessage:
"CodeQL attempted to build your project using a script located at " +
$"`{relScriptPath}`, which failed. " +
$"Set up a [manual build command]({buildCommandDocsUrl})."
);
AddDiagnostic(message);
}
// project files which don't exist get marked as not .NET core projects, but we don't want
// to show an error for this if the files don't exist
var foundNotDotNetProjects = autoBuildRule.DotNetRule.NotDotNetProjects.Where(
proj => this.Actions.FileExists(proj.FullPath)
);
// both dotnet and msbuild builds require project or solution files; if we haven't found any
// then neither of those rules would've worked
if (this.ProjectsOrSolutionsToBuild.Count == 0)
{
this.AddDiagnostic(new(
this.Options.Language,
"no-projects-or-solutions",
"No project or solutions files found",
markdownMessage:
"CodeQL could not find any project or solution files in your repository. " +
$"Set up a [manual build command]({buildCommandDocsUrl})."
));
}
// show a warning if there are projects which are not compatible with .NET Core, in case that is unintentional
else if (foundNotDotNetProjects.Any())
{
this.AddDiagnostic(new(
this.Options.Language,
"dotnet-incompatible-projects",
"Some projects are incompatible with .NET Core",
severity: DiagnosticMessage.TspSeverity.Warning,
markdownMessage: $"""
CodeQL found some projects which cannot be built with .NET Core:
{autoBuildRule.DotNetRule.NotDotNetProjects.Select(p => this.MakeRelative(p.FullPath)).ToMarkdownList(MarkdownUtil.CodeFormatter, 5)}
"""
));
}
// report any projects that failed to build with .NET Core
if (autoBuildRule.DotNetRule.FailedProjectsOrSolutions.Any())
{
this.AddDiagnostic(new(
this.Options.Language,
"dotnet-build-failure",
"Some projects or solutions failed to build using .NET Core",
markdownMessage: $"""
CodeQL was unable to build the following projects using .NET Core:
{autoBuildRule.DotNetRule.FailedProjectsOrSolutions.Select(p => this.MakeRelative(p.FullPath)).ToMarkdownList(MarkdownUtil.CodeFormatter, 10)}
Set up a [manual build command]({buildCommandDocsUrl}).
"""
));
}
// report any projects that failed to build with MSBuild
if (autoBuildRule.MsBuildRule.FailedProjectsOrSolutions.Any())
{
this.AddDiagnostic(new(
this.Options.Language,
"msbuild-build-failure",
"Some projects or solutions failed to build using MSBuild",
markdownMessage: $"""
CodeQL was unable to build the following projects using MSBuild:
{autoBuildRule.MsBuildRule.FailedProjectsOrSolutions.Select(p => this.MakeRelative(p.FullPath)).ToMarkdownList(MarkdownUtil.CodeFormatter, 10)}
Set up a [manual build command]({buildCommandDocsUrl}).
"""
));
}
}
/// <summary> /// <summary>
/// Gets the build strategy that the autobuilder should apply, based on the /// Gets the build strategy that the autobuilder should apply, based on the
/// options in the `lgtm.yml` file. /// options in the `lgtm.yml` file.

View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Semmle.Autobuild.Shared;
using Semmle.Util;
namespace Semmle.Autobuild.CSharp
{
/// <summary>
/// A diagnostic rule which tries to identify missing Xamarin SDKs.
/// </summary>
public class MissingXamarinSdkRule : DiagnosticRule
{
private const string docsUrl = "https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-xamarin-applications";
public class Result : IDiagnosticsResult
{
/// <summary>
/// The name of the SDK that is missing.
/// </summary>
public string SDKName { get; }
public Result(string sdkName)
{
this.SDKName = sdkName;
}
public DiagnosticMessage ToDiagnosticMessage<T>(Autobuilder<T> builder, DiagnosticMessage.TspSeverity? severity = null) where T : AutobuildOptionsShared => new(
builder.Options.Language,
$"missing-xamarin-{this.SDKName.ToLower()}-sdk",
$"Missing Xamarin SDK for {this.SDKName}",
severity: severity ?? DiagnosticMessage.TspSeverity.Error,
markdownMessage: $"[Configure your workflow]({docsUrl}) for this SDK before running CodeQL."
);
}
public MissingXamarinSdkRule() :
base("MSB4019:[^\"]*\"[^\"]*Xamarin\\.(?<sdkName>[^\\.]*)\\.CSharp\\.targets\"")
{
}
public override void Fire(DiagnosticClassifier classifier, Match match)
{
if (!match.Groups.TryGetValue("sdkName", out var sdkName))
throw new ArgumentException("Expected regular expression match to contain sdkName");
var xamarinResults = classifier.Results.OfType<Result>().Where(result =>
result.SDKName.Equals(sdkName.Value)
);
if (!xamarinResults.Any())
classifier.Results.Add(new Result(sdkName.Value));
}
}
public class MissingProjectFileRule : DiagnosticRule
{
private const string runsOnDocsUrl = "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on";
private const string checkoutDocsUrl = "https://github.com/actions/checkout#usage";
public class Result : IDiagnosticsResult
{
/// <summary>
/// A set of missing project files.
/// </summary>
public HashSet<string> MissingProjectFiles { get; }
public Result()
{
this.MissingProjectFiles = new HashSet<string>();
}
public DiagnosticMessage ToDiagnosticMessage<T>(Autobuilder<T> builder, DiagnosticMessage.TspSeverity? severity = null) where T : AutobuildOptionsShared => new(
builder.Options.Language,
"missing-project-files",
"Missing project files",
severity: severity ?? DiagnosticMessage.TspSeverity.Warning,
markdownMessage: $"""
Some project files were not found when CodeQL built your project:
{this.MissingProjectFiles.AsEnumerable().Select(p => builder.MakeRelative(p)).ToMarkdownList(MarkdownUtil.CodeFormatter, 5)}
This may lead to subsequent failures. You can check for common causes for missing project files:
- Ensure that the project is built using the {runsOnDocsUrl.ToMarkdownLink("intended operating system")} and that filenames on case-sensitive platforms are correctly specified.
- If your repository uses Git submodules, ensure that those are {checkoutDocsUrl.ToMarkdownLink("checked out")} before the CodeQL action is run.
- If you auto-generate some project files as part of your build process, ensure that these are generated before the CodeQL action is run.
"""
);
}
public MissingProjectFileRule() :
base("MSB3202: The project file \"(?<projectFile>[^\"]+)\" was not found. \\[(?<location>[^\\]]+)\\]")
{
}
public override void Fire(DiagnosticClassifier classifier, Match match)
{
if (!match.Groups.TryGetValue("projectFile", out var projectFile))
throw new ArgumentException("Expected regular expression match to contain projectFile");
if (!match.Groups.TryGetValue("location", out var location))
throw new ArgumentException("Expected regular expression match to contain location");
var result = classifier.Results.OfType<Result>().FirstOrDefault();
// if we do not yet have a result for this rule, create one and add it to the list
// of results the classifier knows about
if (result is null)
{
result = new Result();
classifier.Results.Add(result);
}
// then add the missing project file
result.MissingProjectFiles.Add(projectFile.Value);
}
}
/// <summary>
/// Implements a <see cref="DiagnosticClassifier" /> which applies C#-specific rules to
/// the build output.
/// </summary>
public class CSharpDiagnosticClassifier : DiagnosticClassifier
{
public CSharpDiagnosticClassifier()
{
// add C#-specific rules to this classifier
this.AddRule(new MissingXamarinSdkRule());
this.AddRule(new MissingProjectFileRule());
}
}
}

View File

@@ -15,6 +15,15 @@ namespace Semmle.Autobuild.CSharp
/// </summary> /// </summary>
internal class DotNetRule : IBuildRule<CSharpAutobuildOptions> internal class DotNetRule : IBuildRule<CSharpAutobuildOptions>
{ {
public readonly List<IProjectOrSolution> FailedProjectsOrSolutions = new();
/// <summary>
/// A list of projects which are incompatible with DotNet.
/// </summary>
public IEnumerable<Project<CSharpAutobuildOptions>> NotDotNetProjects { get; private set; }
public DotNetRule() => NotDotNetProjects = new List<Project<CSharpAutobuildOptions>>();
public BuildScript Analyse(IAutobuilder<CSharpAutobuildOptions> builder, bool auto) public BuildScript Analyse(IAutobuilder<CSharpAutobuildOptions> builder, bool auto)
{ {
if (!builder.ProjectsOrSolutionsToBuild.Any()) if (!builder.ProjectsOrSolutionsToBuild.Any())
@@ -22,10 +31,12 @@ namespace Semmle.Autobuild.CSharp
if (auto) if (auto)
{ {
var notDotNetProject = builder.ProjectsOrSolutionsToBuild NotDotNetProjects = builder.ProjectsOrSolutionsToBuild
.SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects)) .SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects))
.OfType<Project<CSharpAutobuildOptions>>() .OfType<Project<CSharpAutobuildOptions>>()
.FirstOrDefault(p => !p.DotNetProject); .Where(p => !p.DotNetProject);
var notDotNetProject = NotDotNetProjects.FirstOrDefault();
if (notDotNetProject is not null) if (notDotNetProject is not null)
{ {
builder.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);
@@ -50,7 +61,10 @@ namespace Semmle.Autobuild.CSharp
var build = GetBuildScript(builder, dotNetPath, environment, projectOrSolution.FullPath); var build = GetBuildScript(builder, dotNetPath, environment, projectOrSolution.FullPath);
ret &= BuildScript.Try(clean) & BuildScript.Try(restore) & build; ret &= BuildScript.Try(clean) & BuildScript.Try(restore) & BuildScript.OnFailure(build, ret =>
{
FailedProjectsOrSolutions.Add(projectOrSolution);
});
} }
return ret; return ret;
}); });

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Semmle.Util;
namespace Semmle.Autobuild.Shared namespace Semmle.Autobuild.Shared
{ {

View File

@@ -1,3 +1,4 @@
using Semmle.Util;
using Semmle.Util.Logging; using Semmle.Util.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -189,10 +190,11 @@ namespace Semmle.Autobuild.Shared
/// solution file and tools. /// solution file and tools.
/// </summary> /// </summary>
/// <param name="options">The command line options.</param> /// <param name="options">The command line options.</param>
protected Autobuilder(IBuildActions actions, TAutobuildOptions options) protected Autobuilder(IBuildActions actions, TAutobuildOptions options, DiagnosticClassifier diagnosticClassifier)
{ {
Actions = actions; Actions = actions;
Options = options; Options = options;
DiagnosticClassifier = diagnosticClassifier;
pathsLazy = new Lazy<IEnumerable<(string, int)>>(() => pathsLazy = new Lazy<IEnumerable<(string, int)>>(() =>
{ {
@@ -232,24 +234,53 @@ namespace Semmle.Autobuild.Shared
return ret ?? new List<IProjectOrSolution>(); return ret ?? new List<IProjectOrSolution>();
}); });
CodeQLExtractorLangRoot = Actions.GetEnvironmentVariable($"CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_ROOT"); CodeQLExtractorLangRoot = Actions.GetEnvironmentVariable(EnvVars.Root(this.Options.Language));
CodeQlPlatform = Actions.GetEnvironmentVariable("CODEQL_PLATFORM"); CodeQlPlatform = Actions.GetEnvironmentVariable(EnvVars.Platform);
TrapDir = TrapDir = RequireEnvironmentVariable(EnvVars.TrapDir(this.Options.Language));
Actions.GetEnvironmentVariable($"CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_TRAP_DIR") ?? SourceArchiveDir = RequireEnvironmentVariable(EnvVars.SourceArchiveDir(this.Options.Language));
throw new InvalidEnvironmentException($"The environment variable CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_TRAP_DIR has not been set."); DiagnosticsDir = RequireEnvironmentVariable(EnvVars.DiagnosticDir(this.Options.Language));
SourceArchiveDir = this.diagnostics = actions.CreateDiagnosticsWriter(Path.Combine(DiagnosticsDir, $"autobuilder-{DateTime.UtcNow:yyyyMMddHHmm}-{Environment.ProcessId}.jsonc"));
Actions.GetEnvironmentVariable($"CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_SOURCE_ARCHIVE_DIR") ??
throw new InvalidEnvironmentException($"The environment variable CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_SOURCE_ARCHIVE_DIR has not been set.");
} }
protected string TrapDir { get; } /// <summary>
/// Retrieves the value of an environment variable named <paramref name="name"> or throws
/// an exception if no such environment variable has been set.
/// </summary>
/// <param name="name">The name of the environment variable.</param>
/// <returns>The value of the environment variable.</returns>
/// <exception cref="InvalidEnvironmentException">
/// Thrown if the environment variable is not set.
/// </exception>
protected string RequireEnvironmentVariable(string name)
{
return Actions.GetEnvironmentVariable(name) ??
throw new InvalidEnvironmentException($"The environment variable {name} has not been set.");
}
protected string SourceArchiveDir { get; } public string TrapDir { get; }
public string SourceArchiveDir { get; }
public string DiagnosticsDir { get; }
protected DiagnosticClassifier DiagnosticClassifier { get; }
private readonly ILogger logger = new ConsoleLogger(Verbosity.Info); private readonly ILogger logger = new ConsoleLogger(Verbosity.Info);
private readonly IDiagnosticsWriter diagnostics;
/// <summary>
/// Makes <see cref="path" /> relative to the root source directory.
/// </summary>
/// <param name="path">The path which to make relative.</param>
/// <returns>The relative path.</returns>
public string MakeRelative(string path)
{
return Path.GetRelativePath(this.RootDirectory, path);
}
/// <summary> /// <summary>
/// Log a given build event to the console. /// Log a given build event to the console.
/// </summary> /// </summary>
@@ -260,6 +291,15 @@ namespace Semmle.Autobuild.Shared
logger.Log(severity, format, args); logger.Log(severity, format, args);
} }
/// <summary>
/// Write <paramref name="diagnostic"/> to the diagnostics file.
/// </summary>
/// <param name="diagnostic">The diagnostics entry to write.</param>
public void AddDiagnostic(DiagnosticMessage diagnostic)
{
diagnostics.AddEntry(diagnostic);
}
/// <summary> /// <summary>
/// Attempt to build this project. /// Attempt to build this project.
/// </summary> /// </summary>
@@ -283,7 +323,19 @@ namespace Semmle.Autobuild.Shared
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}")}");
} }
return script.Run(Actions, startCallback, exitCallback); var onOutput = BuildOutputHandler(Console.Out);
var onError = BuildOutputHandler(Console.Error);
var buildResult = script.Run(Actions, startCallback, exitCallback, onOutput, onError);
// if the build succeeded, all diagnostics we captured from the build output should be warnings;
// otherwise they should all be errors
var diagSeverity = buildResult == 0 ? DiagnosticMessage.TspSeverity.Warning : DiagnosticMessage.TspSeverity.Error;
this.DiagnosticClassifier.Results
.Select(result => result.ToDiagnosticMessage(this, diagSeverity))
.ForEach(AddDiagnostic);
return buildResult;
} }
/// <summary> /// <summary>
@@ -291,13 +343,58 @@ namespace Semmle.Autobuild.Shared
/// </summary> /// </summary>
public abstract BuildScript GetBuildScript(); public abstract BuildScript GetBuildScript();
/// <summary>
/// Produces a diagnostic for the tool status page that we were unable to automatically
/// build the user's project and that they can manually specify a build command. This
/// can be overriden to implement more specific messages depending on the origin of
/// the failure.
/// </summary>
protected virtual void AutobuildFailureDiagnostic() => AddDiagnostic(new DiagnosticMessage(
this.Options.Language,
"autobuild-failure",
"Unable to build project",
visibility: new DiagnosticMessage.TspVisibility(statusPage: true),
plaintextMessage: """
We were unable to automatically build your project.
Set up a manual build command.
"""
));
/// <summary>
/// Returns a build script that can be run upon autobuild failure.
/// </summary>
/// <returns>
/// A build script that reports that we could not automatically detect a suitable build method.
/// </returns>
protected BuildScript AutobuildFailure() => protected BuildScript AutobuildFailure() =>
BuildScript.Create(actions => BuildScript.Create(actions =>
{ {
Log(Severity.Error, "Could not auto-detect a suitable build method"); Log(Severity.Error, "Could not auto-detect a suitable build method");
AutobuildFailureDiagnostic();
return 1; return 1;
}); });
/// <summary>
/// Constructs a <see cref="BuildOutputHandler" /> which uses the <see cref="DiagnosticClassifier" />
/// to classify build output. All data also gets written to <paramref name="writer" />.
/// </summary>
/// <param name="writer">
/// The <see cref="TextWriter" /> to which the build output would have normally been written to.
/// This is normally <see cref="Console.Out" /> or <see cref="Console.Error" />.
/// </param>
/// <returns>The constructed <see cref="BuildOutputHandler" />.</returns>
protected BuildOutputHandler BuildOutputHandler(TextWriter writer) => new(data =>
{
if (data is not null)
{
writer.WriteLine(data);
DiagnosticClassifier.ClassifyLine(data);
}
});
/// <summary> /// <summary>
/// Value of CODEQL_EXTRACTOR_<LANG>_ROOT environment variable. /// Value of CODEQL_EXTRACTOR_<LANG>_ROOT environment variable.
/// </summary> /// </summary>

View File

@@ -11,11 +11,26 @@ using System.Runtime.InteropServices;
namespace Semmle.Autobuild.Shared namespace Semmle.Autobuild.Shared
{ {
public delegate void BuildOutputHandler(string? data);
/// <summary> /// <summary>
/// Wrapper around system calls so that the build scripts can be unit-tested. /// Wrapper around system calls so that the build scripts can be unit-tested.
/// </summary> /// </summary>
public interface IBuildActions public interface IBuildActions
{ {
/// <summary>
/// Runs a process, captures its output, and provides it asynchronously.
/// </summary>
/// <param name="exe">The exe to run.</param>
/// <param name="args">The other command line arguments.</param>
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
/// <param name="env">Additional environment variables.</param>
/// <param name="onOutput">A handler for stdout output.</param>
/// <param name="onError">A handler for stderr output.</param>
/// <returns>The process exit code.</returns>
int RunProcess(string exe, string args, string? workingDirectory, IDictionary<string, string>? env, BuildOutputHandler onOutput, BuildOutputHandler onError);
/// <summary> /// <summary>
/// Runs a process and captures its output. /// Runs a process and captures its output.
/// </summary> /// </summary>
@@ -152,6 +167,17 @@ namespace Semmle.Autobuild.Shared
/// Downloads the resource with the specified URI to a local file. /// Downloads the resource with the specified URI to a local file.
/// </summary> /// </summary>
void DownloadFile(string address, string fileName); void DownloadFile(string address, string fileName);
/// <summary>
/// Creates an <see cref="IDiagnosticsWriter" /> for the given <paramref name="filename" />.
/// </summary>
/// <param name="filename">
/// The path suggesting where the diagnostics should be written to.
/// </param>
/// <returns>
/// A <see cref="IDiagnosticsWriter" /> to which diagnostic entries can be added.
/// </returns>
IDiagnosticsWriter CreateDiagnosticsWriter(string filename);
} }
/// <summary> /// <summary>
@@ -173,15 +199,31 @@ namespace Semmle.Autobuild.Shared
if (workingDirectory is not null) if (workingDirectory is not null)
pi.WorkingDirectory = workingDirectory; pi.WorkingDirectory = workingDirectory;
// Environment variables can only be used when not redirecting stdout environment?.ForEach(kvp => pi.Environment[kvp.Key] = kvp.Value);
if (!redirectStandardOutput)
{
if (environment is not null)
environment.ForEach(kvp => pi.Environment[kvp.Key] = kvp.Value);
}
return pi; return pi;
} }
int IBuildActions.RunProcess(string exe, string args, string? workingDirectory, System.Collections.Generic.IDictionary<string, string>? env, BuildOutputHandler onOutput, BuildOutputHandler onError)
{
var pi = GetProcessStartInfo(exe, args, workingDirectory, env, true);
using var p = new Process
{
StartInfo = pi
};
p.StartInfo.RedirectStandardError = true;
p.OutputDataReceived += new DataReceivedEventHandler((sender, e) => onOutput(e.Data));
p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => onError(e.Data));
p.Start();
p.BeginErrorReadLine();
p.BeginOutputReadLine();
p.WaitForExit();
return p.ExitCode;
}
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? environment) int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? environment)
{ {
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false); var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false);
@@ -253,6 +295,8 @@ namespace Semmle.Autobuild.Shared
public void DownloadFile(string address, string fileName) => public void DownloadFile(string address, string fileName) =>
DownloadFileAsync(address, fileName).Wait(); DownloadFileAsync(address, fileName).Wait();
public IDiagnosticsWriter CreateDiagnosticsWriter(string filename) => new DiagnosticsStream(filename);
public static IBuildActions Instance { get; } = new SystemBuildActions(); public static IBuildActions Instance { get; } = new SystemBuildActions();
} }
} }

View File

@@ -11,22 +11,42 @@ namespace Semmle.Autobuild.Shared
{ {
private readonly WithDotNet<AutobuildOptionsShared> withDotNet; private readonly WithDotNet<AutobuildOptionsShared> withDotNet;
/// <summary>
/// A list of paths to files in the project directory which we classified as scripts.
/// </summary>
public IEnumerable<string> CandidatePaths { get; private set; }
/// <summary>
/// The path of the script we decided to run, if any.
/// </summary>
public string? ScriptPath { get; private set; }
public BuildCommandAutoRule(WithDotNet<AutobuildOptionsShared> withDotNet) public BuildCommandAutoRule(WithDotNet<AutobuildOptionsShared> withDotNet)
{ {
this.withDotNet = withDotNet; this.withDotNet = withDotNet;
this.CandidatePaths = new List<string>();
} }
/// <summary>
/// A list of extensions that we consider to be for scripts on Windows.
/// </summary>
private readonly IEnumerable<string> winExtensions = new List<string> { private readonly IEnumerable<string> winExtensions = new List<string> {
".bat", ".bat",
".cmd", ".cmd",
".exe" ".exe"
}; };
/// <summary>
/// A list of extensions that we consider to be for scripts on Linux.
/// </summary>
private readonly IEnumerable<string> linuxExtensions = new List<string> { private readonly IEnumerable<string> linuxExtensions = new List<string> {
"", "",
".sh" ".sh"
}; };
/// <summary>
/// A list of filenames without extensions that we think might be build scripts.
/// </summary>
private readonly IEnumerable<string> buildScripts = new List<string> { private readonly IEnumerable<string> buildScripts = new List<string> {
"build" "build"
}; };
@@ -35,18 +55,25 @@ namespace Semmle.Autobuild.Shared
{ {
builder.Log(Severity.Info, "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; var extensions = builder.Actions.IsWindows() ? winExtensions : linuxExtensions;
// a list of combined base script names with the current platform's script extensions
// e.g. for Linux: build, build.sh
var scripts = buildScripts.SelectMany(s => extensions.Select(e => s + e)); var scripts = buildScripts.SelectMany(s => extensions.Select(e => s + e));
var scriptPath = builder.Paths.Where(p => scripts.Any(p.Item1.ToLower().EndsWith)).OrderBy(p => p.Item2).Select(p => p.Item1).FirstOrDefault(); // search through the files in the project directory for paths which end in one of
// the names given by `scripts`, then order them by their distance from the root
this.CandidatePaths = builder.Paths.Where(p => scripts.Any(p.Item1.ToLower().EndsWith)).OrderBy(p => p.Item2).Select(p => p.Item1);
// pick the first matching path, if there is one
this.ScriptPath = this.CandidatePaths.FirstOrDefault();
if (scriptPath is null) if (this.ScriptPath is null)
return BuildScript.Failure; return BuildScript.Failure;
var chmod = new CommandBuilder(builder.Actions); var chmod = new CommandBuilder(builder.Actions);
chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}"); chmod.RunCommand("/bin/chmod", $"u+x {this.ScriptPath}");
var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script); var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script);
var dir = builder.Actions.GetDirectoryName(scriptPath); var dir = builder.Actions.GetDirectoryName(this.ScriptPath);
// A specific .NET Core version may be required // A specific .NET Core version may be required
return chmodScript & withDotNet(builder, environment => return chmodScript & withDotNet(builder, environment =>
@@ -58,7 +85,7 @@ namespace Semmle.Autobuild.Shared
if (vsTools is not null) if (vsTools is not null)
command.CallBatFile(vsTools.Path); command.CallBatFile(vsTools.Path);
command.RunCommand(scriptPath); command.RunCommand(this.ScriptPath);
return command.Script; return command.Script;
}); });
} }

View File

@@ -46,6 +46,33 @@ namespace Semmle.Autobuild.Shared
/// <returns>The exit code from this build script.</returns> /// <returns>The exit code from this build script.</returns>
public abstract int Run(IBuildActions actions, Action<string, bool> startCallback, Action<int, string, bool> exitCallBack, out IList<string> stdout); public abstract int Run(IBuildActions actions, Action<string, bool> startCallback, Action<int, string, bool> exitCallBack, out IList<string> stdout);
/// <summary>
/// Runs this build command.
/// </summary>
/// <param name="actions">
/// The interface used to implement the build actions.
/// </param>
/// <param name="startCallback">
/// A call back that is called every time a new process is started. The
/// argument to the call back is a textual representation of the process.
/// </param>
/// <param name="exitCallBack">
/// A call back that is called every time a new process exits. The first
/// argument to the call back is the exit code, and the second argument is
/// an exit message.
/// </param>
/// <param name="onOutput">
/// A handler for data read from stdout.
/// </param>
/// <param name="onError">
/// A handler for data read from stderr.
/// </param>
/// <returns>The exit code from this build script.</returns>
public abstract int Run(IBuildActions actions, Action<string, bool> startCallback, Action<int, string, bool> exitCallBack, BuildOutputHandler onOutput, BuildOutputHandler onError);
/// <summary>
/// A build script which executes an external program or script.
/// </summary>
private class BuildCommand : BuildScript private class BuildCommand : BuildScript
{ {
private readonly string exe, arguments; private readonly string exe, arguments;
@@ -110,8 +137,29 @@ namespace Semmle.Autobuild.Shared
return ret; return ret;
} }
public override int Run(IBuildActions actions, Action<string, bool> startCallback, Action<int, string, bool> exitCallBack, BuildOutputHandler onOutput, BuildOutputHandler onError)
{
startCallback(this.ToString(), silent);
var ret = 1;
var retMessage = "";
try
{
ret = actions.RunProcess(exe, arguments, workingDirectory, environment, onOutput, onError);
}
catch (Exception ex)
when (ex is System.ComponentModel.Win32Exception || ex is FileNotFoundException)
{
retMessage = ex.Message;
}
exitCallBack(ret, retMessage, silent);
return ret;
}
} }
/// <summary>
/// A build script which runs a C# function.
/// </summary>
private class ReturnBuildCommand : BuildScript private class ReturnBuildCommand : BuildScript
{ {
private readonly Func<IBuildActions, int> func; private readonly Func<IBuildActions, int> func;
@@ -127,8 +175,13 @@ namespace Semmle.Autobuild.Shared
stdout = Array.Empty<string>(); stdout = Array.Empty<string>();
return func(actions); return func(actions);
} }
public override int Run(IBuildActions actions, Action<string, bool> startCallback, Action<int, string, bool> exitCallBack, BuildOutputHandler onOutput, BuildOutputHandler onError) => func(actions);
} }
/// <summary>
/// Allows two build scripts to be composed sequentially.
/// </summary>
private class BindBuildScript : BuildScript private class BindBuildScript : BuildScript
{ {
private readonly BuildScript s1; private readonly BuildScript s1;
@@ -175,6 +228,32 @@ namespace Semmle.Autobuild.Shared
stdout = @out; stdout = @out;
return ret2; return ret2;
} }
public override int Run(IBuildActions actions, Action<string, bool> startCallback, Action<int, string, bool> exitCallBack, BuildOutputHandler onOutput, BuildOutputHandler onError)
{
int ret1;
if (s2a is not null)
{
var stdout1 = new List<string>();
var onOutputWrapper = new BuildOutputHandler(data =>
{
if (data is not null)
stdout1.Add(data);
onOutput(data);
});
ret1 = s1.Run(actions, startCallback, exitCallBack, onOutputWrapper, onError);
return s2a(stdout1, ret1).Run(actions, startCallback, exitCallBack, onOutput, onError);
}
if (s2b is not null)
{
ret1 = s1.Run(actions, startCallback, exitCallBack, onOutput, onError);
return s2b(ret1).Run(actions, startCallback, exitCallBack, onOutput, onError);
}
throw new InvalidOperationException("Unexpected error");
}
} }
/// <summary> /// <summary>
@@ -260,6 +339,23 @@ namespace Semmle.Autobuild.Shared
/// </summary> /// </summary>
public static BuildScript Try(BuildScript s) => s | Success; public static BuildScript Try(BuildScript s) => s | Success;
/// <summary>
/// Creates a build script that runs the build script <paramref name="s" />. If
/// running <paramref name="s" /> fails, <paramref name="k" /> is invoked with
/// the exit code.
/// </summary>
/// <param name="s">The build script to run.</param>
/// <param name="k">
/// The callback that is invoked if <paramref name="s" /> failed.
/// </param>
/// <returns>The build script which implements this.</returns>
public static BuildScript OnFailure(BuildScript s, Action<int> k) =>
new BindBuildScript(s, ret => Create(actions =>
{
if (!Succeeded(ret)) k(ret);
return ret;
}));
/// <summary> /// <summary>
/// Creates a build script that deletes the given directory. /// Creates a build script that deletes the given directory.
/// </summary> /// </summary>

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Semmle.Util;
namespace Semmle.Autobuild.Shared
{
/// <summary>
/// Direct results result from the successful application of a <see cref="DiagnosticRule" />,
/// which can later be converted to a corresponding <see cref="DiagnosticMessage" />.
/// </summary>
public interface IDiagnosticsResult
{
/// <summary>
/// Produces a <see cref="DiagnosticMessage" /> corresponding to this result.
/// </summary>
/// <param name="builder">
/// The autobuilder to use for constructing the base <see cref="DiagnosticMessage" />.
/// </param>
/// <param name="severity">
/// An optional severity value which overrides the default severity of the diagnostic.
/// </param>
/// <returns>The <see cref="DiagnosticMessage" /> corresponding to this result.</returns>
DiagnosticMessage ToDiagnosticMessage<T>(Autobuilder<T> builder, DiagnosticMessage.TspSeverity? severity = null) where T : AutobuildOptionsShared;
}
public class DiagnosticRule
{
/// <summary>
/// The pattern against which this rule matches build output.
/// </summary>
public Regex Pattern { get; }
/// <summary>
/// Constructs a diagnostic rule for the given <paramref name="pattern" />.
/// </summary>
/// <param name="pattern"></param>
public DiagnosticRule(Regex pattern)
{
this.Pattern = pattern;
}
/// <summary>
/// Constructs a diagnostic rule for the given regular expression <paramref name="pattern" />.
/// </summary>
/// <param name="pattern"></param>
public DiagnosticRule(string pattern)
{
this.Pattern = new Regex(pattern, RegexOptions.Compiled);
}
/// <summary>
/// Used by a <see cref="DiagnosticClassifier" /> <paramref name="classifier" /> to
/// signal that the rule has matched some build output with <paramref name="match" />.
/// </summary>
/// <param name="classifier">The classifier which is firing the rule.</param>
/// <param name="match">The <see cref="Match" /> that resulted from applying the rule.</param>
public virtual void Fire(DiagnosticClassifier classifier, Match match) { }
}
public class DiagnosticClassifier
{
private readonly List<DiagnosticRule> rules;
public readonly List<IDiagnosticsResult> Results;
public DiagnosticClassifier()
{
this.rules = new List<DiagnosticRule>();
this.Results = new List<IDiagnosticsResult>();
}
/// <summary>
/// Adds <paramref name="rule" /> to this classifier.
/// </summary>
/// <param name="rule">The rule to add.</param>
protected void AddRule(DiagnosticRule rule)
{
this.rules.Add(rule);
}
/// <summary>
/// Applies all of this classifier's rules to <paramref name="line" /> to see which match.
/// </summary>
/// <param name="line">The line to which the rules should be applied to.</param>
public void ClassifyLine(string line)
{
this.rules.ForEach(rule =>
{
var match = rule.Pattern.Match(line);
if (match.Success)
{
rule.Fire(this, match);
}
});
}
}
}

View File

@@ -0,0 +1,13 @@
using Semmle.Util;
namespace Semmle.Autobuild.Shared
{
public static class EnvVars
{
public const string Platform = "CODEQL_PLATFORM";
public static string Root(Language language) => $"CODEQL_EXTRACTOR_{language.UpperCaseName}_ROOT";
public static string TrapDir(Language language) => $"CODEQL_EXTRACTOR_{language.UpperCaseName}_TRAP_DIR";
public static string SourceArchiveDir(Language language) => $"CODEQL_EXTRACTOR_{language.UpperCaseName}_SOURCE_ARCHIVE_DIR";
public static string DiagnosticDir(Language language) => $"CODEQL_EXTRACTOR_{language.UpperCaseName}_DIAGNOSTIC_DIR";
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Semmle.Autobuild.Shared
{
public static class MarkdownUtil
{
/// <summary>
/// Formats items as markdown inline code.
/// </summary>
/// <returns>A function which formats items as markdown inline code.</returns>
public static readonly Func<string, string> CodeFormatter = item => $"`{item}`";
/// <summary>
/// Formats the string as a markdown link.
/// </summary>
/// <param name="link">The URL for the link.</param>
/// <param name="title">The text that is displayed.</param>
/// <returns>A string containing a markdown-formatted link.</returns>
public static string ToMarkdownLink(this string link, string title) => $"[{title}]({link})";
/// <summary>
/// Renders <see cref="projects" /> as a markdown list of the project paths.
/// </summary>
/// <param name="projects">
/// The list of projects whose paths should be rendered as a markdown list.
/// </param>
/// <param name="limit">The maximum number of items to include in the list.</param>
/// <returns>Returns the markdown list as a string.</returns>
public static string ToMarkdownList(this IEnumerable<IProjectOrSolution> projects, int? limit = null)
{
return projects.ToMarkdownList(p => $"`{p.FullPath}`", limit);
}
/// <summary>
/// Renders <see cref="items" /> as a markdown list.
/// </summary>
/// <typeparam name="T">The item type.</typeparam>
/// <param name="items">The list that should be formatted as a markdown list.</param>
/// <param name="formatter">A function which converts individual items into a string representation.</param>
/// <param name="limit">The maximum number of items to include in the list.</param>
/// <returns>Returns the markdown list as a string.</returns>
public static string ToMarkdownList<T>(this IEnumerable<T> items, Func<T, string> formatter, int? limit = null)
{
var sb = new StringBuilder();
// if there is a limit, take at most that many items from the start of the list
var list = limit is not null ? items.Take(limit.Value) : items;
sb.Append(string.Join('\n', list.Select(item => $"- {formatter(item)}")));
// if there were more items than allowed in the list, add an extra item indicating
// how many more items there were
var length = items.Count();
if (limit is not null && length > limit)
{
sb.Append($"\n- and {length - limit} more. View the CodeQL logs for a full list.");
}
return sb.ToString();
}
}
}

View File

@@ -1,7 +1,6 @@
using Semmle.Util.Logging; using Semmle.Util.Logging;
using System; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
namespace Semmle.Autobuild.Shared namespace Semmle.Autobuild.Shared
{ {
@@ -31,6 +30,11 @@ namespace Semmle.Autobuild.Shared
/// </summary> /// </summary>
public class MsBuildRule : IBuildRule<AutobuildOptionsShared> public class MsBuildRule : IBuildRule<AutobuildOptionsShared>
{ {
/// <summary>
/// A list of solutions or projects which failed to build.
/// </summary>
public readonly List<IProjectOrSolution> FailedProjectsOrSolutions = new();
public BuildScript Analyse(IAutobuilder<AutobuildOptionsShared> builder, bool auto) public BuildScript Analyse(IAutobuilder<AutobuildOptionsShared> builder, bool auto)
{ {
if (!builder.ProjectsOrSolutionsToBuild.Any()) if (!builder.ProjectsOrSolutionsToBuild.Any())
@@ -128,7 +132,13 @@ namespace Semmle.Autobuild.Shared
command.Argument(builder.Options.MsBuildArguments); command.Argument(builder.Options.MsBuildArguments);
ret &= command.Script; // append the build script which invokes msbuild to the overall build script `ret`;
// we insert a check that building the current project or solution was successful:
// if it was not successful, we add it to `FailedProjectsOrSolutions`
ret &= BuildScript.OnFailure(command.Script, ret =>
{
FailedProjectsOrSolutions.Add(projectOrSolution);
});
} }
return ret; return ret;

View File

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

View File

@@ -1,4 +1,4 @@
namespace Semmle.Autobuild.Shared namespace Semmle.Util
{ {
public sealed class Language public sealed class Language
{ {

View File

@@ -15,6 +15,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" /> <PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,242 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
namespace Semmle.Util
{
/// <summary>
/// Represents diagnostic messages for the tool status page.
/// </summary>
public class DiagnosticMessage
{
/// <summary>
/// Represents sources of diagnostic messages.
/// </summary>
public class TspSource
{
/// <summary>
/// An identifier under which it makes sense to group this diagnostic message.
/// This is used to build the SARIF reporting descriptor object.
/// </summary>
public string Id { get; }
/// <summary>
/// Display name for the ID. This is used to build the SARIF reporting descriptor object.
/// </summary>
public string Name { get; }
/// <summary>
/// Name of the CodeQL extractor. This is used to identify which tool component the reporting descriptor object should be nested under in SARIF.
/// </summary>
public string? ExtractorName { get; }
public TspSource(string id, string name, string? extractorName = null)
{
Id = id;
Name = name;
ExtractorName = extractorName;
}
}
/// <summary>
/// Enumerates severity levels for diagnostics.
/// </summary>
[JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy))]
public enum TspSeverity
{
Note,
Warning,
Error
}
/// <summary>
/// Stores flags indicating where the diagnostic should be displayed.
/// </summary>
public class TspVisibility
{
/// <summary>
/// A read-only instance of <see cref="TspVisibility" /> which indicates that the
/// diagnostic should be used in all supported locations.
/// </summary>
public static readonly TspVisibility All = new(true, true, true);
/// <summary>
/// True if the message should be displayed on the status page (defaults to false).
/// </summary>
public bool? StatusPage { get; }
/// <summary>
/// True if the message should be counted in the diagnostics summary table printed by
/// <c>codeql database analyze</c> (defaults to false).
/// </summary>
public bool? CLISummaryTable { get; }
/// <summary>
/// True if the message should be sent to telemetry (defaults to false).
/// </summary>
public bool? Telemetry { get; }
public TspVisibility(bool? statusPage = null, bool? cliSummaryTable = null, bool? telemetry = null)
{
this.StatusPage = statusPage;
this.CLISummaryTable = cliSummaryTable;
this.Telemetry = telemetry;
}
}
/// <summary>
/// Represents source code locations for diagnostic messages.
/// </summary>
public class TspLocation
{
/// <summary>
/// Path to the affected file if appropriate, relative to the source root.
/// </summary>
public string? File { get; }
/// <summary>
/// The line where the range to which the diagnostic relates to starts.
/// </summary>
public int? StartLine { get; }
/// <summary>
/// The column where the range to which the diagnostic relates to starts.
/// </summary>
public int? StartColumn { get; }
/// <summary>
/// The line where the range to which the diagnostic relates to ends.
/// </summary>
public int? EndLine { get; }
/// <summary>
/// The column where the range to which the diagnostic relates to ends.
/// </summary>
public int? EndColumn { get; }
public TspLocation(string? file = null, int? startLine = null, int? startColumn = null, int? endLine = null, int? endColumn = null)
{
this.File = file;
this.StartLine = startLine;
this.StartColumn = startColumn;
this.EndLine = endLine;
this.EndColumn = endColumn;
}
}
/// <summary>
/// ISO 8601 timestamp.
/// </summary>
public string Timestamp { get; }
/// <summary>
/// The source of the diagnostic message.
/// </summary>
public TspSource Source { get; }
/// <summary>
/// GitHub flavored Markdown formatted message. Should include inline links to any help pages.
/// </summary>
public string? MarkdownMessage { get; }
/// <summary>
/// Plain text message. Used by components where the string processing needed to support
/// Markdown is cumbersome.
/// </summary>
public string? PlaintextMessage { get; }
/// <summary>
/// List of help links intended to supplement <see cref="PlaintextMessage" />.
/// </summary>
public List<string> HelpLinks { get; }
/// <summary>
/// SARIF severity.
/// </summary>
public TspSeverity? Severity { get; }
/// <summary>
/// If true, then this message won't be presented to users.
/// </summary>
public bool Internal { get; }
public TspVisibility Visibility { get; }
public TspLocation Location { get; }
/// <summary>
/// Structured metadata about the diagnostic message.
/// </summary>
public Dictionary<string, object> Attributes { get; }
public DiagnosticMessage(
Language language, string id, string name, string? markdownMessage = null, string? plaintextMessage = null,
TspVisibility? visibility = null, TspLocation? location = null, TspSeverity? severity = TspSeverity.Error,
DateTime? timestamp = null, bool? intrnl = null
)
{
this.Source = new TspSource(
id: $"{language.UpperCaseName.ToLower()}/autobuilder/{id}",
name: name,
extractorName: language.UpperCaseName.ToLower()
);
this.Timestamp = (timestamp ?? DateTime.UtcNow).ToString("o", CultureInfo.InvariantCulture);
this.HelpLinks = new List<string>();
this.Attributes = new Dictionary<string, object>();
this.Severity = severity;
this.Visibility = visibility ?? TspVisibility.All;
this.Location = location ?? new TspLocation();
this.Internal = intrnl ?? false;
this.MarkdownMessage = markdownMessage;
this.PlaintextMessage = plaintextMessage;
}
}
/// <summary>
/// Provides the ability to write diagnostic messages to some output.
/// </summary>
public interface IDiagnosticsWriter
{
/// <summary>
/// Adds <paramref name="message" /> as a new diagnostics entry.
/// </summary>
/// <param name="message">The diagnostics entry to add.</param>
void AddEntry(DiagnosticMessage message);
}
/// <summary>
/// A wrapper around an underlying <see cref="StreamWriter" /> which allows
/// <see cref="DiagnosticMessage" /> objects to be serialized to it.
/// </summary>
public sealed class DiagnosticsStream : IDiagnosticsWriter, IDisposable
{
private readonly JsonSerializer serializer;
private readonly StreamWriter writer;
/// <summary>
/// Initialises a new <see cref="DiagnosticsStream" /> for a file at <paramref name="path" />.
/// </summary>
/// <param name="path">The path to the file that should be created.</param>
public DiagnosticsStream(string path)
{
this.writer = File.CreateText(path);
var contractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy()
};
serializer = new JsonSerializer
{
ContractResolver = contractResolver,
NullValueHandling = NullValueHandling.Ignore
};
}
/// <summary>
/// Adds <paramref name="message" /> as a new diagnostics entry.
/// </summary>
/// <param name="message">The diagnostics entry to add.</param>
public void AddEntry(DiagnosticMessage message)
{
serializer.Serialize(writer, message);
writer.Flush();
}
/// <summary>
/// Releases all resources used by the <see cref="DiagnosticsStream" /> object.
/// </summary>
public void Dispose()
{
writer.Dispose();
}
}
}

View File

@@ -1,3 +1,7 @@
## 1.4.4
No user-facing changes.
## 1.4.3 ## 1.4.3
No user-facing changes. No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.4.3 lastReleaseVersion: 1.4.4

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all name: codeql/csharp-solorigate-all
version: 1.4.4-dev version: 1.4.5-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -1,3 +1,7 @@
## 1.4.4
No user-facing changes.
## 1.4.3 ## 1.4.3
No user-facing changes. No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.4.3 lastReleaseVersion: 1.4.4

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries name: codeql/csharp-solorigate-queries
version: 1.4.4-dev version: 1.4.5-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -0,0 +1,36 @@
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL found some projects which cannot be built with .NET Core:\n\n- `test.csproj`",
"severity": "warning",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/dotnet-incompatible-projects",
"name": "Some projects are incompatible with .NET Core"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL was unable to build the following projects using MSBuild:\n\n- `test.csproj`\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/msbuild-build-failure",
"name": "Some projects or solutions failed to build using MSBuild"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Example</RootNamespace>
<AssemblyName>Example</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,5 @@
from create_database_utils import *
from diagnostics_test_utils import *
run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully)
check_diagnostics()

View File

@@ -0,0 +1,36 @@
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL was unable to build the following projects using MSBuild:\n\n- `test.sln`\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/msbuild-build-failure",
"name": "Some projects or solutions failed to build using MSBuild"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "Some project files were not found when CodeQL built your project:\n\n- `Example.csproj`\n- `Example.Test.csproj`\n\nThis may lead to subsequent failures. You can check for common causes for missing project files:\n\n- Ensure that the project is built using the [intended operating system](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on) and that filenames on case-sensitive platforms are correctly specified.\n- If your repository uses Git submodules, ensure that those are [checked out](https://github.com/actions/checkout#usage) before the CodeQL action is run.\n- If you auto-generate some project files as part of your build process, ensure that these are generated before the CodeQL action is run.",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/missing-project-files",
"name": "Missing project files"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}

View File

@@ -0,0 +1,5 @@
from create_database_utils import *
from diagnostics_test_utils import *
run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully)
check_diagnostics()

View File

@@ -0,0 +1,26 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example.csproj", "{F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Test", "Example.Test.csproj", "{F4587B5F-9918-4079-9291-5A08CD9761FB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}.Debug|x86.ActiveCfg = Debug|x86
{F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}.Debug|x86.Build.0 = Debug|x86
{F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}.Release|x86.ActiveCfg = Release|x86
{F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}.Release|x86.Build.0 = Release|x86
{F4587B5F-9918-4079-9291-5A08CD9761FB}.Debug|x86.ActiveCfg = Debug|x86
{F4587B5F-9918-4079-9291-5A08CD9761FB}.Debug|x86.Build.0 = Debug|x86
{F4587B5F-9918-4079-9291-5A08CD9761FB}.Release|x86.ActiveCfg = Release|x86
{F4587B5F-9918-4079-9291-5A08CD9761FB}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,54 @@
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL was unable to build the following projects using .NET Core:\n\n- `test.csproj`\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/dotnet-build-failure",
"name": "Some projects or solutions failed to build using .NET Core"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL was unable to build the following projects using MSBuild:\n\n- `test.csproj`\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/msbuild-build-failure",
"name": "Some projects or solutions failed to build using MSBuild"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "[Configure your workflow](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-xamarin-applications) for this SDK before running CodeQL.",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/missing-xamarin-ios-sdk",
"name": "Missing Xamarin SDK for iOS"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}

View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LanguageTargets>$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets</LanguageTargets>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,5 @@
from create_database_utils import *
from diagnostics_test_utils import *
run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully)
check_diagnostics()

View File

@@ -1,3 +1,5 @@
from create_database_utils import * from create_database_utils import *
from diagnostics_test_utils import *
run_codeql_database_create(['dotnet build'], test_db="default-db", db=None, lang="csharp") run_codeql_database_create(['dotnet build'], db=None, lang="csharp")
check_diagnostics()

View File

@@ -1,8 +1,11 @@
import os import os
from create_database_utils import * from create_database_utils import *
from diagnostics_test_utils import *
run_codeql_database_create(['dotnet pack'], test_db="default-db", db=None, lang="csharp") run_codeql_database_create(['dotnet pack'], db=None, lang="csharp")
## Check that the NuGet package is created. ## Check that the NuGet package is created.
if not os.path.isfile("bin/Debug/dotnet_pack.1.0.0.nupkg"): if not os.path.isfile("bin/Debug/dotnet_pack.1.0.0.nupkg"):
raise Exception("The NuGet package was not created.") raise Exception("The NuGet package was not created.")
check_diagnostics()

View File

@@ -1,9 +1,12 @@
import os import os
from create_database_utils import * from create_database_utils import *
from diagnostics_test_utils import *
artifacts = 'bin/Temp' artifacts = 'bin/Temp'
run_codeql_database_create([f"dotnet publish -o {artifacts}"], test_db="default-db", db=None, lang="csharp") run_codeql_database_create([f"dotnet publish -o {artifacts}"], db=None, lang="csharp")
## Check that the publish folder is created. ## Check that the publish folder is created.
if not os.path.isdir(artifacts): if not os.path.isdir(artifacts):
raise Exception("The publish artifact folder was not created.") raise Exception("The publish artifact folder was not created.")
check_diagnostics()

View File

@@ -1,5 +1,6 @@
import os import os
from create_database_utils import * from create_database_utils import *
from diagnostics_test_utils import *
def run_codeql_database_create_stdout(args, dbname): def run_codeql_database_create_stdout(args, dbname):
stdout = open(dbname + "file.txt", 'w+') stdout = open(dbname + "file.txt", 'w+')
@@ -16,32 +17,40 @@ def check_build_out(msg, s):
# no arguments # no arguments
s = run_codeql_database_create_stdout(['dotnet run'], "test-db") s = run_codeql_database_create_stdout(['dotnet run'], "test-db")
check_build_out("Default reply", s) check_build_out("Default reply", s)
check_diagnostics()
# no arguments, but `--` # no arguments, but `--`
s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test-db', 'dotnet run --'], "test2-db") s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test-db', 'dotnet run --'], "test2-db")
check_build_out("Default reply", s) check_build_out("Default reply", s)
check_diagnostics(diagnostics_dir="test2-db/diagnostic")
# one argument, no `--` # one argument, no `--`
s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test2-db', 'dotnet run hello'], "test3-db") s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test2-db', 'dotnet run hello'], "test3-db")
check_build_out("Default reply", s) check_build_out("Default reply", s)
check_diagnostics(diagnostics_dir="test3-db/diagnostic")
# one argument, but `--` # one argument, but `--`
s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test3-db', 'dotnet run -- hello'], "test4-db") s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test3-db', 'dotnet run -- hello'], "test4-db")
check_build_out("Default reply", s) check_build_out("Default reply", s)
check_diagnostics(diagnostics_dir="test4-db/diagnostic")
# two arguments, no `--` # two arguments, no `--`
s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test4-db', 'dotnet run hello world'], "test5-db") s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test4-db', 'dotnet run hello world'], "test5-db")
check_build_out("hello, world", s) check_build_out("hello, world", s)
check_diagnostics(diagnostics_dir="test5-db/diagnostic")
# two arguments, and `--` # two arguments, and `--`
s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test5-db', 'dotnet run -- hello world'], "test6-db") s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test5-db', 'dotnet run -- hello world'], "test6-db")
check_build_out("hello, world", s) check_build_out("hello, world", s)
check_diagnostics(diagnostics_dir="test6-db/diagnostic")
# shared compilation enabled; tracer should override by changing the command # shared compilation enabled; tracer should override by changing the command
# to `dotnet run -p:UseSharedCompilation=true -p:UseSharedCompilation=false -- hello world` # to `dotnet run -p:UseSharedCompilation=true -p:UseSharedCompilation=false -- hello world`
s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test6-db', 'dotnet run -p:UseSharedCompilation=true -- hello world'], "test7-db") s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test6-db', 'dotnet run -p:UseSharedCompilation=true -- hello world'], "test7-db")
check_build_out("hello, world", s) check_build_out("hello, world", s)
check_diagnostics(diagnostics_dir="test7-db/diagnostic")
# option passed into `dotnet run` # option passed into `dotnet run`
s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test7-db', 'dotnet build', 'dotnet run --no-build hello world'], "test8-db") s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test7-db', 'dotnet build', 'dotnet run --no-build hello world'], "test8-db")
check_build_out("hello, world", s) check_build_out("hello, world", s)
check_diagnostics(diagnostics_dir="test8-db/diagnostic")

View File

@@ -1,4 +1,6 @@
from create_database_utils import * from create_database_utils import *
from diagnostics_test_utils import *
# force CodeQL to use MSBuild by setting `LGTM_INDEX_MSBUILD_TARGET` # force CodeQL to use MSBuild by setting `LGTM_INDEX_MSBUILD_TARGET`
run_codeql_database_create([], test_db="default-db", db=None, lang="csharp", extra_env={ 'LGTM_INDEX_MSBUILD_TARGET': 'Build' }) run_codeql_database_create([], db=None, lang="csharp", extra_env={ 'LGTM_INDEX_MSBUILD_TARGET': 'Build' })
check_diagnostics()

View File

@@ -0,0 +1,3 @@
#!/bin/sh
exit 1

View File

@@ -0,0 +1,36 @@
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL attempted to build your project using a script located at `build.sh`, which failed. Set up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/script-failure",
"name": "Unable to build project using build script"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL could not find any project or solution files in your repository. Set up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/no-projects-or-solutions",
"name": "No project or solutions files found"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}

View File

@@ -0,0 +1,5 @@
from create_database_utils import *
from diagnostics_test_utils import *
run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully)
check_diagnostics()

View File

@@ -0,0 +1,3 @@
#!/bin/sh
exit 1

View File

@@ -0,0 +1,36 @@
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL could not find any project or solution files in your repository. Set up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/no-projects-or-solutions",
"name": "No project or solutions files found"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"attributes": {},
"helpLinks": [],
"internal": false,
"location": {},
"markdownMessage": "CodeQL found multiple potential build scripts for your project and attempted to run `build.sh`, which failed. This may not be the right build script for your project. Set up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).",
"severity": "error",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/multiple-build-scripts",
"name": "There are multiple potential build scripts"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}

Some files were not shown because too many files have changed in this diff Show More