Merge branch 'github:main' into main

This commit is contained in:
Grzegorz Niedziela
2023-02-23 10:50:15 +00:00
committed by GitHub
395 changed files with 31400 additions and 2624 deletions

View File

@@ -9,7 +9,7 @@ inputs:
outputs:
cache-dir:
description: "The directory where the cache was stored"
value: ${{ steps.fill-compilation-dir.outputs.compdir }}
value: ${{ steps.output-compilation-dir.outputs.compdir }}
runs:
using: composite
@@ -27,7 +27,9 @@ runs:
if: ${{ github.event_name == 'pull_request' }}
uses: actions/cache/restore@v3
with:
path: '**/.cache'
path: |
**/.cache
~/.codeql/compile-cache
key: codeql-compile-${{ inputs.key }}-pr-${{ github.sha }}
restore-keys: |
codeql-compile-${{ inputs.key }}-${{ github.base_ref }}-${{ env.merge_base }}
@@ -37,18 +39,111 @@ runs:
if: ${{ github.event_name != 'pull_request' }}
uses: actions/cache@v3
with:
path: '**/.cache'
path: |
**/.cache
~/.codeql/compile-cache
key: codeql-compile-${{ inputs.key }}-${{ github.ref_name }}-${{ github.sha }} # just fill on main
restore-keys: | # restore the latest cache if the exact cache is unavailable, to speed up compilation.
codeql-compile-${{ inputs.key }}-${{ github.ref_name }}-
codeql-compile-${{ inputs.key }}-main-
- name: Fill compilation cache directory
id: fill-compilation-dir
- name: Output-compilationdir
id: output-compilation-dir
shell: bash
run: |
# Move all the existing cache into another folder, so we only preserve the cache for the current queries.
node $GITHUB_WORKSPACE/.github/actions/cache-query-compilation/move-caches.js ${COMBINED_CACHE_DIR}
echo "compdir=${COMBINED_CACHE_DIR}" >> $GITHUB_OUTPUT
env:
COMBINED_CACHE_DIR: ${{ runner.temp }}/compilation-dir
- name: Fill compilation cache directory
id: fill-compilation-dir
uses: actions/github-script@v6
env:
COMBINED_CACHE_DIR: ${{ runner.temp }}/compilation-dir
with:
script: |
// # Move all the existing cache into another folder, so we only preserve the cache for the current queries.
// mkdir -p ${COMBINED_CACHE_DIR}
// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty.
// # copy the contents of the .cache folders into the combined cache folder.
// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files
// # clean up the .cache folders
// rm -rf **/.cache/*
const fs = require("fs");
const path = require("path");
const os = require("os");
// the first argv is the cache folder to create.
const COMBINED_CACHE_DIR = process.env.COMBINED_CACHE_DIR;
function* walkCaches(dir) {
const files = fs.readdirSync(dir, { withFileTypes: true });
for (const file of files) {
if (file.isDirectory()) {
const filePath = path.join(dir, file.name);
yield* walkCaches(filePath);
if (file.name === ".cache") {
yield filePath;
}
}
}
}
async function copyDir(src, dest) {
for await (const file of await fs.promises.readdir(src, { withFileTypes: true })) {
const srcPath = path.join(src, file.name);
const destPath = path.join(dest, file.name);
if (file.isDirectory()) {
if (!fs.existsSync(destPath)) {
fs.mkdirSync(destPath);
}
await copyDir(srcPath, destPath);
} else {
await fs.promises.copyFile(srcPath, destPath);
}
}
}
async function main() {
const cacheDirs = [...walkCaches(".")];
for (const dir of cacheDirs) {
console.log(`Found .cache dir at ${dir}`);
}
const globalCacheDir = path.join(os.homedir(), ".codeql", "compile-cache");
if (fs.existsSync(globalCacheDir)) {
console.log("Found global home dir: " + globalCacheDir);
cacheDirs.push(globalCacheDir);
}
if (cacheDirs.length === 0) {
console.log("No cache dirs found");
return;
}
// mkdir -p ${COMBINED_CACHE_DIR}
fs.mkdirSync(COMBINED_CACHE_DIR, { recursive: true });
// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty.
await Promise.all(
cacheDirs.map((cacheDir) =>
(async function () {
await fs.promises.rm(path.join(cacheDir, "lock"), { force: true });
await fs.promises.rm(path.join(cacheDir, "size"), { force: true });
})()
)
);
// # copy the contents of the .cache folders into the combined cache folder.
// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files
await Promise.all(
cacheDirs.map((cacheDir) => copyDir(cacheDir, COMBINED_CACHE_DIR))
);
// # clean up the .cache folders
// rm -rf **/.cache/*
await Promise.all(
cacheDirs.map((cacheDir) => fs.promises.rm(cacheDir, { recursive: true }))
);
}
main();

View File

@@ -1,75 +0,0 @@
// # Move all the existing cache into another folder, so we only preserve the cache for the current queries.
// mkdir -p ${COMBINED_CACHE_DIR}
// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty.
// # copy the contents of the .cache folders into the combined cache folder.
// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files
// # clean up the .cache folders
// rm -rf **/.cache/*
const fs = require("fs");
const path = require("path");
// the first argv is the cache folder to create.
const COMBINED_CACHE_DIR = process.argv[2];
function* walkCaches(dir) {
const files = fs.readdirSync(dir, { withFileTypes: true });
for (const file of files) {
if (file.isDirectory()) {
const filePath = path.join(dir, file.name);
yield* walkCaches(filePath);
if (file.name === ".cache") {
yield filePath;
}
}
}
}
async function copyDir(src, dest) {
for await (const file of await fs.promises.readdir(src, { withFileTypes: true })) {
const srcPath = path.join(src, file.name);
const destPath = path.join(dest, file.name);
if (file.isDirectory()) {
if (!fs.existsSync(destPath)) {
fs.mkdirSync(destPath);
}
await copyDir(srcPath, destPath);
} else {
await fs.promises.copyFile(srcPath, destPath);
}
}
}
async function main() {
const cacheDirs = [...walkCaches(".")];
for (const dir of cacheDirs) {
console.log(`Found .cache dir at ${dir}`);
}
// mkdir -p ${COMBINED_CACHE_DIR}
fs.mkdirSync(COMBINED_CACHE_DIR, { recursive: true });
// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty.
await Promise.all(
cacheDirs.map((cacheDir) =>
(async function () {
await fs.promises.rm(path.join(cacheDir, "lock"), { force: true });
await fs.promises.rm(path.join(cacheDir, "size"), { force: true });
})()
)
);
// # copy the contents of the .cache folders into the combined cache folder.
// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files
await Promise.all(
cacheDirs.map((cacheDir) => copyDir(cacheDir, COMBINED_CACHE_DIR))
);
// # clean up the .cache folders
// rm -rf **/.cache/*
await Promise.all(
cacheDirs.map((cacheDir) => fs.promises.rm(cacheDir, { recursive: true }))
);
}
main();

View File

@@ -24,14 +24,14 @@ jobs:
with:
key: all-queries
- name: check formatting
run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 codeql query format --check-only
run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
- name: compile queries - check-only
# run with --check-only if running in a PR (github.sha != main)
if : ${{ github.event_name == 'pull_request' }}
shell: bash
run: codeql query compile -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
- name: compile queries - full
# do full compile if running on main - this populates the cache
if : ${{ github.event_name != 'pull_request' }}
shell: bash
run: codeql query compile -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"

View File

@@ -5,13 +5,6 @@ on:
branches: [main]
pull_request:
branches: [main]
paths:
- "ql/**"
- "**.qll"
- "**.ql"
- "**.dbscheme"
- "**/qlpack.yml"
- ".github/workflows/ql-for-ql-build.yml"
env:
CARGO_TERM_COLOR: always
@@ -22,6 +15,8 @@ jobs:
steps:
### Build the queries ###
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@v2
@@ -34,7 +29,9 @@ jobs:
id: cache-extractor
uses: actions/cache@v3
with:
path: ql/extractor-pack/
path: |
ql/extractor-pack/
ql/target/release/buramu
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
- name: Cache cargo
if: steps.cache-extractor.outputs.cache-hit != 'true'
@@ -57,6 +54,7 @@ jobs:
key: run-ql-for-ql
- name: Make database and analyze
run: |
./ql/target/release/buramu | tee deprecated.blame # Add a blame file for the extractor to parse.
${CODEQL} database create -l=ql --search-path ql/extractor-pack ${DB}
${CODEQL} database analyze -j0 --format=sarif-latest --output=ql-for-ql.sarif ${DB} ql/ql/src/codeql-suites/ql-code-scanning.qls --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
env:
@@ -65,6 +63,7 @@ jobs:
LGTM_INDEX_FILTERS: |
exclude:ql/ql/test
exclude:*/ql/lib/upgrades/
exclude:java/ql/integration-tests
- name: Upload sarif to code-scanning
uses: github/codeql-action/upload-sarif@v2
with:

View File

@@ -2,9 +2,9 @@
/csharp/ @github/codeql-csharp
/go/ @github/codeql-go
/java/ @github/codeql-java
/javascript/ @github/codeql-javascript
/python/ @github/codeql-python
/ruby/ @github/codeql-ruby
/javascript/ @github/codeql-dynamic
/python/ @github/codeql-dynamic
/ruby/ @github/codeql-dynamic
/swift/ @github/codeql-swift
/java/kotlin-extractor/ @github/codeql-kotlin
/java/kotlin-explorer/ @github/codeql-kotlin

View File

@@ -131,6 +131,14 @@ namespace Semmle.Autobuild.Cpp.Tests
bool IBuildActions.IsWindows() => IsWindows;
public bool IsMacOs { get; set; }
bool IBuildActions.IsMacOs() => IsMacOs;
public bool IsArm { get; set; }
bool IBuildActions.IsArm() => IsArm;
string IBuildActions.PathCombine(params string[] parts)
{
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -145,6 +145,14 @@ namespace Semmle.Autobuild.CSharp.Tests
bool IBuildActions.IsWindows() => IsWindows;
public bool IsMacOs { get; set; }
bool IBuildActions.IsMacOs() => IsMacOs;
public bool IsArm { get; set; }
bool IBuildActions.IsArm() => IsArm;
public string PathCombine(params string[] parts)
{
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));

View File

@@ -7,6 +7,7 @@ using System.Xml;
using System.Net.Http;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace Semmle.Autobuild.Shared
{
@@ -98,6 +99,18 @@ namespace Semmle.Autobuild.Shared
/// </summary>
bool IsWindows();
/// <summary>
/// Gets a value indicating whether we are running on macOS.
/// </summary>
/// <returns>True if we are running on macOS.</returns>
bool IsMacOs();
/// <summary>
/// Gets a value indicating whether we are running on arm.
/// </summary>
/// <returns>True if we are running on arm.</returns>
bool IsArm();
/// <summary>
/// Combine path segments, Path.Combine().
/// </summary>
@@ -203,6 +216,12 @@ namespace Semmle.Autobuild.Shared
bool IBuildActions.IsWindows() => Win32.IsWindows();
bool IBuildActions.IsMacOs() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
bool IBuildActions.IsArm() =>
RuntimeInformation.ProcessArchitecture == Architecture.Arm64 ||
RuntimeInformation.ProcessArchitecture == Architecture.Arm;
string IBuildActions.PathCombine(params string[] parts) => Path.Combine(parts);
void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents);

View File

@@ -1,18 +1,36 @@
using Semmle.Util.Logging;
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace Semmle.Autobuild.Shared
{
internal static class MsBuildCommandExtensions
{
/// <summary>
/// Appends a call to msbuild.
/// </summary>
/// <param name="cmdBuilder"></param>
/// <param name="builder"></param>
/// <returns></returns>
public static CommandBuilder MsBuildCommand(this CommandBuilder cmdBuilder, IAutobuilder<AutobuildOptionsShared> builder)
{
var isArmMac = builder.Actions.IsMacOs() && builder.Actions.IsArm();
// mono doesn't ship with `msbuild` on Arm-based Macs, but we can fall back to
// msbuild that ships with `dotnet` which can be invoked with `dotnet msbuild`
// perhaps we should do this on all platforms?
return isArmMac ?
cmdBuilder.RunCommand("dotnet").Argument("msbuild") :
cmdBuilder.RunCommand("msbuild");
}
}
/// <summary>
/// A build rule using msbuild.
/// </summary>
public class MsBuildRule : IBuildRule<AutobuildOptionsShared>
{
/// <summary>
/// The name of the msbuild command.
/// </summary>
private const string msBuild = "msbuild";
public BuildScript Analyse(IAutobuilder<AutobuildOptionsShared> builder, bool auto)
{
if (!builder.ProjectsOrSolutionsToBuild.Any())
@@ -57,7 +75,7 @@ namespace Semmle.Autobuild.Shared
Script;
var nugetRestore = GetNugetRestoreScript();
var msbuildRestoreCommand = new CommandBuilder(builder.Actions).
RunCommand(msBuild).
MsBuildCommand(builder).
Argument("/t:restore").
QuoteArgument(projectOrSolution.FullPath);
@@ -95,7 +113,7 @@ namespace Semmle.Autobuild.Shared
command.RunCommand("set Platform=&& type NUL", quoteExe: false);
}
command.RunCommand(msBuild);
command.MsBuildCommand(builder);
command.QuoteArgument(projectOrSolution.FullPath);
var target = builder.Options.MsBuildTarget ?? "rebuild";

View File

@@ -65,6 +65,15 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.has_modifiers(target, Modifier.Create(cx, modifier));
}
private static void ExtractFieldModifiers(Context cx, TextWriter trapFile, IEntity key, IFieldSymbol symbol)
{
if (symbol.IsReadOnly)
HasModifier(cx, trapFile, key, Modifiers.Readonly);
if (symbol.IsRequired)
HasModifier(cx, trapFile, key, Modifiers.Required);
}
private static void ExtractNamedTypeModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
{
if (symbol.Kind != SymbolKind.NamedType)
@@ -106,8 +115,11 @@ namespace Semmle.Extraction.CSharp.Entities
if (symbol.IsVirtual)
HasModifier(cx, trapFile, key, Modifiers.Virtual);
if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly)
HasModifier(cx, trapFile, key, Modifiers.Readonly);
if (symbol is IFieldSymbol field)
ExtractFieldModifiers(cx, trapFile, key, field);
if (symbol.Kind == SymbolKind.Property && ((IPropertySymbol)symbol).IsRequired)
HasModifier(cx, trapFile, key, Modifiers.Required);
if (symbol.IsOverride)
HasModifier(cx, trapFile, key, Modifiers.Override);

View File

@@ -13,6 +13,7 @@ internal static class Modifiers
public const string Public = "public";
public const string Readonly = "readonly";
public const string Record = "record";
public const string Required = "required";
public const string Ref = "ref";
public const string Sealed = "sealed";
public const string Static = "static";

View File

@@ -77,12 +77,8 @@ namespace Semmle.Extraction.CSharp
/// <summary>
/// Gets the source-level modifiers belonging to this symbol, if any.
/// </summary>
public static IEnumerable<string> GetSourceLevelModifiers(this ISymbol symbol)
{
var methodModifiers = symbol.GetModifiers<Microsoft.CodeAnalysis.CSharp.Syntax.BaseMethodDeclarationSyntax>(md => md.Modifiers);
var typeModifiers = symbol.GetModifiers<Microsoft.CodeAnalysis.CSharp.Syntax.TypeDeclarationSyntax>(cd => cd.Modifiers);
return methodModifiers.Concat(typeModifiers).Select(m => m.Text);
}
public static IEnumerable<string> GetSourceLevelModifiers(this ISymbol symbol) =>
symbol.GetModifiers<Microsoft.CodeAnalysis.CSharp.Syntax.MemberDeclarationSyntax>(md => md.Modifiers).Select(m => m.Text);
/// <summary>
/// Holds if the ID generated for `dependant` will contain a reference to

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,3 +1,9 @@
## 0.5.3
### Minor Analysis Improvements
* C# 11: Added extractor support for the `scoped` modifier annotation on parameters and local variables.
## 0.5.2
### Major Analysis Improvements

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* C# 11: Added extractor support for the `scoped` modifier annotation on parameters and local variables.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* C# 11: Added library support for `checked` operators.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* C# 11: Added extractor support for `required` fields and properties.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The extraction of member modifiers has been generalised, which could lead to the extraction of more modifiers.

View File

@@ -0,0 +1,5 @@
## 0.5.3
### Minor Analysis Improvements
* C# 11: Added extractor support for the `scoped` modifier annotation on parameters and local variables.

View File

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

View File

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

View File

@@ -435,8 +435,12 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de
* (`BinaryOperator`), or a conversion operator (`ConversionOperator`).
*/
class Operator extends Callable, Member, Attributable, @operator {
/** Gets the assembly name of this operator. */
string getAssemblyName() { operators(this, result, _, _, _, _) }
/**
* DEPRECATED: use `getFunctionName()` instead.
*
* Gets the assembly name of this operator.
*/
deprecated string getAssemblyName() { result = this.getFunctionName() }
override string getName() { operators(this, _, result, _, _, _) }
@@ -445,7 +449,7 @@ class Operator extends Callable, Member, Attributable, @operator {
/**
* Gets the metadata name of the operator, such as `op_implicit` or `op_RightShift`.
*/
string getFunctionName() { none() }
string getFunctionName() { operators(this, result, _, _, _, _) }
override ValueOrRefType getDeclaringType() { operators(this, _, _, result, _, _) }
@@ -481,10 +485,11 @@ class RecordCloneMethod extends Method, DotNet::RecordCloneCallable {
* A user-defined unary operator - an operator taking one operand.
*
* Either a plus operator (`PlusOperator`), minus operator (`MinusOperator`),
* not operator (`NotOperator`), complement operator (`ComplementOperator`),
* true operator (`TrueOperator`), false operator (`FalseOperator`),
* increment operator (`IncrementOperator`), or decrement operator
* (`DecrementOperator`).
* checked minus operator (`CheckedMinusOperator`), not operator (`NotOperator`),
* complement operator (`ComplementOperator`), true operator (`TrueOperator`),
* false operator (`FalseOperator`), increment operator (`IncrementOperator`),
* checked increment operator (`CheckedIncrementOperator`), decrement operator
* (`DecrementOperator`) or checked decrement operator (`CheckedDecrementOperator`).
*/
class UnaryOperator extends Operator {
UnaryOperator() {
@@ -505,8 +510,6 @@ class UnaryOperator extends Operator {
class PlusOperator extends UnaryOperator {
PlusOperator() { this.getName() = "+" }
override string getFunctionName() { result = "op_UnaryPlus" }
override string getAPrimaryQlClass() { result = "PlusOperator" }
}
@@ -522,11 +525,24 @@ class PlusOperator extends UnaryOperator {
class MinusOperator extends UnaryOperator {
MinusOperator() { this.getName() = "-" }
override string getFunctionName() { result = "op_UnaryNegation" }
override string getAPrimaryQlClass() { result = "MinusOperator" }
}
/**
* A user-defined checked minus operator (`-`), for example
*
* ```csharp
* public static Widget operator checked -(Widget w) {
* ...
* }
* ```
*/
class CheckedMinusOperator extends UnaryOperator {
CheckedMinusOperator() { this.getName() = "checked -" }
override string getAPrimaryQlClass() { result = "CheckedMinusOperator" }
}
/**
* A user-defined not operator (`!`), for example
*
@@ -539,8 +555,6 @@ class MinusOperator extends UnaryOperator {
class NotOperator extends UnaryOperator {
NotOperator() { this.getName() = "!" }
override string getFunctionName() { result = "op_LogicalNot" }
override string getAPrimaryQlClass() { result = "NotOperator" }
}
@@ -556,8 +570,6 @@ class NotOperator extends UnaryOperator {
class ComplementOperator extends UnaryOperator {
ComplementOperator() { this.getName() = "~" }
override string getFunctionName() { result = "op_OnesComplement" }
override string getAPrimaryQlClass() { result = "ComplementOperator" }
}
@@ -573,11 +585,24 @@ class ComplementOperator extends UnaryOperator {
class IncrementOperator extends UnaryOperator {
IncrementOperator() { this.getName() = "++" }
override string getFunctionName() { result = "op_Increment" }
override string getAPrimaryQlClass() { result = "IncrementOperator" }
}
/**
* A user-defined checked increment operator (`++`), for example
*
* ```csharp
* public static Widget operator checked ++(Widget w) {
* ...
* }
* ```
*/
class CheckedIncrementOperator extends UnaryOperator {
CheckedIncrementOperator() { this.getName() = "checked ++" }
override string getAPrimaryQlClass() { result = "CheckedIncrementOperator" }
}
/**
* A user-defined decrement operator (`--`), for example
*
@@ -590,11 +615,24 @@ class IncrementOperator extends UnaryOperator {
class DecrementOperator extends UnaryOperator {
DecrementOperator() { this.getName() = "--" }
override string getFunctionName() { result = "op_Decrement" }
override string getAPrimaryQlClass() { result = "DecrementOperator" }
}
/**
* A user-defined checked decrement operator (`--`), for example
*
* ```csharp
* public static Widget operator checked --(Widget w) {
* ...
* }
* ```
*/
class CheckedDecrementOperator extends UnaryOperator {
CheckedDecrementOperator() { this.getName() = "checked --" }
override string getAPrimaryQlClass() { result = "CheckedDecrementOperator" }
}
/**
* A user-defined false operator (`false`), for example
*
@@ -607,8 +645,6 @@ class DecrementOperator extends UnaryOperator {
class FalseOperator extends UnaryOperator {
FalseOperator() { this.getName() = "false" }
override string getFunctionName() { result = "op_False" }
override string getAPrimaryQlClass() { result = "FalseOperator" }
}
@@ -624,17 +660,18 @@ class FalseOperator extends UnaryOperator {
class TrueOperator extends UnaryOperator {
TrueOperator() { this.getName() = "true" }
override string getFunctionName() { result = "op_True" }
override string getAPrimaryQlClass() { result = "TrueOperator" }
}
/**
* A user-defined binary operator.
*
* Either an addition operator (`AddOperator`), a subtraction operator
* (`SubOperator`), a multiplication operator (`MulOperator`), a division
* operator (`DivOperator`), a remainder operator (`RemOperator`), an and
* Either an addition operator (`AddOperator`), a checked addition operator
* (`CheckedAddOperator`) a subtraction operator (`SubOperator`), a checked
* substraction operator (`CheckedSubOperator`), a multiplication operator
* (`MulOperator`), a checked multiplication operator (`CheckedMulOperator`),
* a division operator (`DivOperator`), a checked division operator
* (`CheckedDivOperator`), a remainder operator (`RemOperator`), an and
* operator (`AndOperator`), an or operator (`OrOperator`), an xor
* operator (`XorOperator`), a left shift operator (`LeftShiftOperator`),
* a right shift operator (`RightShiftOperator`), an unsigned right shift
@@ -659,11 +696,24 @@ class BinaryOperator extends Operator {
class AddOperator extends BinaryOperator {
AddOperator() { this.getName() = "+" }
override string getFunctionName() { result = "op_Addition" }
override string getAPrimaryQlClass() { result = "AddOperator" }
}
/**
* A user-defined checked addition operator (`+`), for example
*
* ```csharp
* public static Widget operator checked +(Widget lhs, Widget rhs) {
* ...
* }
* ```
*/
class CheckedAddOperator extends BinaryOperator {
CheckedAddOperator() { this.getName() = "checked +" }
override string getAPrimaryQlClass() { result = "CheckedAddOperator" }
}
/**
* A user-defined subtraction operator (`-`), for example
*
@@ -676,11 +726,24 @@ class AddOperator extends BinaryOperator {
class SubOperator extends BinaryOperator {
SubOperator() { this.getName() = "-" }
override string getFunctionName() { result = "op_Subtraction" }
override string getAPrimaryQlClass() { result = "SubOperator" }
}
/**
* A user-defined checked subtraction operator (`-`), for example
*
* ```csharp
* public static Widget operator checked -(Widget lhs, Widget rhs) {
* ...
* }
* ```
*/
class CheckedSubOperator extends BinaryOperator {
CheckedSubOperator() { this.getName() = "checked -" }
override string getAPrimaryQlClass() { result = "CheckedSubOperator" }
}
/**
* A user-defined multiplication operator (`*`), for example
*
@@ -693,11 +756,24 @@ class SubOperator extends BinaryOperator {
class MulOperator extends BinaryOperator {
MulOperator() { this.getName() = "*" }
override string getFunctionName() { result = "op_Multiply" }
override string getAPrimaryQlClass() { result = "MulOperator" }
}
/**
* A user-defined checked multiplication operator (`*`), for example
*
* ```csharp
* public static Widget operator checked *(Widget lhs, Widget rhs) {
* ...
* }
* ```
*/
class CheckedMulOperator extends BinaryOperator {
CheckedMulOperator() { this.getName() = "checked *" }
override string getAPrimaryQlClass() { result = "CheckedMulOperator" }
}
/**
* A user-defined division operator (`/`), for example
*
@@ -710,11 +786,24 @@ class MulOperator extends BinaryOperator {
class DivOperator extends BinaryOperator {
DivOperator() { this.getName() = "/" }
override string getFunctionName() { result = "op_Division" }
override string getAPrimaryQlClass() { result = "DivOperator" }
}
/**
* A user-defined checked division operator (`/`), for example
*
* ```csharp
* public static Widget operator checked /(Widget lhs, Widget rhs) {
* ...
* }
* ```
*/
class CheckedDivOperator extends BinaryOperator {
CheckedDivOperator() { this.getName() = "checked /" }
override string getAPrimaryQlClass() { result = "CheckedDivOperator" }
}
/**
* A user-defined remainder operator (`%`), for example
*
@@ -727,8 +816,6 @@ class DivOperator extends BinaryOperator {
class RemOperator extends BinaryOperator {
RemOperator() { this.getName() = "%" }
override string getFunctionName() { result = "op_Modulus" }
override string getAPrimaryQlClass() { result = "RemOperator" }
}
@@ -744,8 +831,6 @@ class RemOperator extends BinaryOperator {
class AndOperator extends BinaryOperator {
AndOperator() { this.getName() = "&" }
override string getFunctionName() { result = "op_BitwiseAnd" }
override string getAPrimaryQlClass() { result = "AndOperator" }
}
@@ -761,8 +846,6 @@ class AndOperator extends BinaryOperator {
class OrOperator extends BinaryOperator {
OrOperator() { this.getName() = "|" }
override string getFunctionName() { result = "op_BitwiseOr" }
override string getAPrimaryQlClass() { result = "OrOperator" }
}
@@ -778,8 +861,6 @@ class OrOperator extends BinaryOperator {
class XorOperator extends BinaryOperator {
XorOperator() { this.getName() = "^" }
override string getFunctionName() { result = "op_ExclusiveOr" }
override string getAPrimaryQlClass() { result = "XorOperator" }
}
@@ -795,8 +876,6 @@ class XorOperator extends BinaryOperator {
class LeftShiftOperator extends BinaryOperator {
LeftShiftOperator() { this.getName() = "<<" }
override string getFunctionName() { result = "op_LeftShift" }
override string getAPrimaryQlClass() { result = "LeftShiftOperator" }
}
@@ -815,8 +894,6 @@ deprecated class LShiftOperator = LeftShiftOperator;
class RightShiftOperator extends BinaryOperator {
RightShiftOperator() { this.getName() = ">>" }
override string getFunctionName() { result = "op_RightShift" }
override string getAPrimaryQlClass() { result = "RightShiftOperator" }
}
@@ -835,8 +912,6 @@ deprecated class RShiftOperator = RightShiftOperator;
class UnsignedRightShiftOperator extends BinaryOperator {
UnsignedRightShiftOperator() { this.getName() = ">>>" }
override string getFunctionName() { result = "op_UnsignedRightShift" }
override string getAPrimaryQlClass() { result = "UnsignedRightShiftOperator" }
}
@@ -852,8 +927,6 @@ class UnsignedRightShiftOperator extends BinaryOperator {
class EQOperator extends BinaryOperator {
EQOperator() { this.getName() = "==" }
override string getFunctionName() { result = "op_Equality" }
override string getAPrimaryQlClass() { result = "EQOperator" }
}
@@ -869,8 +942,6 @@ class EQOperator extends BinaryOperator {
class NEOperator extends BinaryOperator {
NEOperator() { this.getName() = "!=" }
override string getFunctionName() { result = "op_Inequality" }
override string getAPrimaryQlClass() { result = "NEOperator" }
}
@@ -886,8 +957,6 @@ class NEOperator extends BinaryOperator {
class LTOperator extends BinaryOperator {
LTOperator() { this.getName() = "<" }
override string getFunctionName() { result = "op_LessThan" }
override string getAPrimaryQlClass() { result = "LTOperator" }
}
@@ -903,8 +972,6 @@ class LTOperator extends BinaryOperator {
class GTOperator extends BinaryOperator {
GTOperator() { this.getName() = ">" }
override string getFunctionName() { result = "op_GreaterThan" }
override string getAPrimaryQlClass() { result = "GTOperator" }
}
@@ -920,8 +987,6 @@ class GTOperator extends BinaryOperator {
class LEOperator extends BinaryOperator {
LEOperator() { this.getName() = "<=" }
override string getFunctionName() { result = "op_LessThanOrEqual" }
override string getAPrimaryQlClass() { result = "LEOperator" }
}
@@ -937,8 +1002,6 @@ class LEOperator extends BinaryOperator {
class GEOperator extends BinaryOperator {
GEOperator() { this.getName() = ">=" }
override string getFunctionName() { result = "op_GreaterThanOrEqual" }
override string getAPrimaryQlClass() { result = "GEOperator" }
}
@@ -954,7 +1017,8 @@ class GEOperator extends BinaryOperator {
class ConversionOperator extends Operator {
ConversionOperator() {
this.getName() = "implicit conversion" or
this.getName() = "explicit conversion"
this.getName() = "explicit conversion" or
this.getName() = "checked explicit conversion"
}
/** Gets the source type of the conversion. */
@@ -976,8 +1040,6 @@ class ConversionOperator extends Operator {
class ImplicitConversionOperator extends ConversionOperator {
ImplicitConversionOperator() { this.getName() = "implicit conversion" }
override string getFunctionName() { result = "op_Implicit" }
override string getAPrimaryQlClass() { result = "ImplicitConversionOperator" }
}
@@ -993,11 +1055,24 @@ class ImplicitConversionOperator extends ConversionOperator {
class ExplicitConversionOperator extends ConversionOperator {
ExplicitConversionOperator() { this.getName() = "explicit conversion" }
override string getFunctionName() { result = "op_Explicit" }
override string getAPrimaryQlClass() { result = "ExplicitConversionOperator" }
}
/**
* A user-defined checked explicit conversion operator, for example
*
* ```csharp
* public static explicit operator checked int(BigInteger i) {
* ...
* }
* ```
*/
class CheckedExplicitConversionOperator extends ConversionOperator {
CheckedExplicitConversionOperator() { this.getName() = "checked explicit conversion" }
override string getAPrimaryQlClass() { result = "CheckedExplicitConversionOperator" }
}
/**
* A local function, defined within the scope of another callable.
* For example, `Fac` on lines 2--4 in

View File

@@ -90,6 +90,9 @@ class Modifiable extends Declaration, @modifiable {
/** Holds if this declaration is `const`. */
predicate isConst() { this.hasModifier("const") }
/** Holds if this declaration has the modifier `required`. */
predicate isRequired() { this.hasModifier("required") }
/** Holds if this declaration is `unsafe`. */
predicate isUnsafe() {
this.hasModifier("unsafe") or
@@ -178,6 +181,8 @@ class Member extends DotNet::Member, Modifiable, @member {
override predicate isAbstract() { Modifiable.super.isAbstract() }
override predicate isStatic() { Modifiable.super.isStatic() }
override predicate isRequired() { Modifiable.super.isRequired() }
}
private class TOverridable = @virtualizable or @callable_accessor;

View File

@@ -80,6 +80,9 @@ class Member extends Declaration, @dotnet_member {
/** Holds if this member is `static`. */
predicate isStatic() { none() }
/** Holds if this member is declared `required`. */
predicate isRequired() { none() }
/**
* Holds if this member has name `name` and is defined in type `type`
* with namespace `namespace`.

View File

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

View File

@@ -8,6 +8,7 @@ private import semmle.code.csharp.dataflow.FlowSummary
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate
private import semmle.code.csharp.security.dataflow.flowsources.Remote
@@ -104,8 +105,17 @@ class ExternalApi extends DotNet::Callable {
pragma[nomagic]
predicate isSink() { sinkNode(this.getAnInput(), _) }
/** Holds if this API is supported by existing CodeQL libraries, that is, it is either a recognized source or sink or has a flow summary. */
predicate isSupported() { this.hasSummary() or this.isSource() or this.isSink() }
/** Holds if this API is a known neutral. */
pragma[nomagic]
predicate isNeutral() { this instanceof FlowSummaryImpl::Public::NeutralCallable }
/**
* Holds if this API is supported by existing CodeQL libraries, that is, it is either a
* recognized source, sink or neutral or it has a flow summary.
*/
predicate isSupported() {
this.hasSummary() or this.isSource() or this.isSink() or this.isNeutral()
}
}
/**

View File

@@ -8,13 +8,9 @@
private import csharp
private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import ExternalApi
private predicate relevant(ExternalApi api) {
api.isSupported() or
api instanceof FlowSummaryImpl::Public::NeutralCallable
}
private predicate relevant(ExternalApi api) { api.isSupported() }
from string info, int usages
where Results<relevant/1>::restrict(info, usages)

View File

@@ -7,14 +7,9 @@
*/
private import csharp
private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import ExternalApi
private predicate relevant(ExternalApi api) {
not api.isSupported() and
not api instanceof FlowSummaryImpl::Public::NeutralCallable
}
private predicate relevant(ExternalApi api) { not api.isSupported() }
from string info, int usages
where Results<relevant/1>::restrict(info, usages)

View File

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

View File

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

View File

@@ -9,13 +9,10 @@
*/
private import csharp
private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import Telemetry.ExternalApi
from Call c, ExternalApi api
where
c.getTarget().getUnboundDeclaration() = api and
not api.isSupported() and
not api instanceof FlowSummaryImpl::Public::NeutralCallable
not api.isSupported()
select c, "Call to unsupported external API $@.", api, api.toString()

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 0.5.3-dev
version: 0.5.4-dev
groups:
- csharp
- queries

View File

@@ -0,0 +1,56 @@
namespace CheckedOperators;
public class Number
{
public int Value { get; }
public Number(int n) => this.Value = n;
public static Number operator checked +(Number n1, Number n2) =>
new Number(checked(n1.Value + n2.Value));
public static Number operator +(Number n1, Number n2) =>
new Number(n1.Value + n2.Value);
public static Number operator checked -(Number n1, Number n2) =>
new Number(checked(n1.Value - n2.Value));
public static Number operator -(Number n1, Number n2) =>
new Number(n1.Value - n2.Value);
public static Number operator checked *(Number n1, Number n2) =>
new Number(checked(n1.Value * n2.Value));
public static Number operator *(Number n1, Number n2) =>
new Number(n1.Value * n2.Value);
public static Number operator checked /(Number n1, Number n2) =>
new Number(checked(n1.Value / n2.Value));
public static Number operator /(Number n1, Number n2) =>
new Number(n1.Value / n2.Value);
public static Number operator checked -(Number n) =>
new Number(checked(-n.Value));
public static Number operator -(Number n) =>
new Number(-n.Value);
public static Number operator checked ++(Number n) =>
new Number(checked(n.Value + 1));
public static Number operator ++(Number n) =>
new Number(n.Value + 1);
public static Number operator checked --(Number n) =>
new Number(checked(n.Value - 1));
public static Number operator --(Number n) =>
new Number(n.Value - 1);
public static explicit operator short(Number n) =>
(short)n.Value;
public static explicit operator checked short(Number n) =>
checked((short)n.Value);
}

View File

@@ -1,3 +1,221 @@
CheckedOperators.cs:
# 1| [NamespaceDeclaration] namespace ... { ... }
# 3| 1: [Class] Number
# 5| 4: [Property] Value
# 5| -1: [TypeMention] int
# 5| 3: [Getter] get_Value
# 7| 5: [InstanceConstructor] Number
#-----| 2: (Parameters)
# 7| 0: [Parameter] n
# 7| -1: [TypeMention] int
# 7| 4: [AssignExpr] ... = ...
# 7| 0: [PropertyCall] access to property Value
# 7| -1: [ThisAccess] this access
# 7| 1: [ParameterAccess] access to parameter n
# 9| 6: [CheckedAddOperator] checked +
# 9| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 9| 0: [Parameter] n1
# 9| -1: [TypeMention] Number
# 9| 1: [Parameter] n2
# 9| -1: [TypeMention] Number
# 10| 4: [ObjectCreation] object creation of type Number
# 10| -1: [TypeMention] Number
# 10| 0: [CheckedExpr] checked (...)
# 10| 0: [AddExpr] ... + ...
# 10| 0: [PropertyCall] access to property Value
# 10| -1: [ParameterAccess] access to parameter n1
# 10| 1: [PropertyCall] access to property Value
# 10| -1: [ParameterAccess] access to parameter n2
# 12| 7: [AddOperator] +
# 12| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 12| 0: [Parameter] n1
# 12| -1: [TypeMention] Number
# 12| 1: [Parameter] n2
# 12| -1: [TypeMention] Number
# 13| 4: [ObjectCreation] object creation of type Number
# 13| -1: [TypeMention] Number
# 13| 0: [AddExpr] ... + ...
# 13| 0: [PropertyCall] access to property Value
# 13| -1: [ParameterAccess] access to parameter n1
# 13| 1: [PropertyCall] access to property Value
# 13| -1: [ParameterAccess] access to parameter n2
# 15| 8: [CheckedSubOperator] checked -
# 15| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 15| 0: [Parameter] n1
# 15| -1: [TypeMention] Number
# 15| 1: [Parameter] n2
# 15| -1: [TypeMention] Number
# 16| 4: [ObjectCreation] object creation of type Number
# 16| -1: [TypeMention] Number
# 16| 0: [CheckedExpr] checked (...)
# 16| 0: [SubExpr] ... - ...
# 16| 0: [PropertyCall] access to property Value
# 16| -1: [ParameterAccess] access to parameter n1
# 16| 1: [PropertyCall] access to property Value
# 16| -1: [ParameterAccess] access to parameter n2
# 18| 9: [SubOperator] -
# 18| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 18| 0: [Parameter] n1
# 18| -1: [TypeMention] Number
# 18| 1: [Parameter] n2
# 18| -1: [TypeMention] Number
# 19| 4: [ObjectCreation] object creation of type Number
# 19| -1: [TypeMention] Number
# 19| 0: [SubExpr] ... - ...
# 19| 0: [PropertyCall] access to property Value
# 19| -1: [ParameterAccess] access to parameter n1
# 19| 1: [PropertyCall] access to property Value
# 19| -1: [ParameterAccess] access to parameter n2
# 21| 10: [CheckedMulOperator] checked *
# 21| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 21| 0: [Parameter] n1
# 21| -1: [TypeMention] Number
# 21| 1: [Parameter] n2
# 21| -1: [TypeMention] Number
# 22| 4: [ObjectCreation] object creation of type Number
# 22| -1: [TypeMention] Number
# 22| 0: [CheckedExpr] checked (...)
# 22| 0: [MulExpr] ... * ...
# 22| 0: [PropertyCall] access to property Value
# 22| -1: [ParameterAccess] access to parameter n1
# 22| 1: [PropertyCall] access to property Value
# 22| -1: [ParameterAccess] access to parameter n2
# 24| 11: [MulOperator] *
# 24| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 24| 0: [Parameter] n1
# 24| -1: [TypeMention] Number
# 24| 1: [Parameter] n2
# 24| -1: [TypeMention] Number
# 25| 4: [ObjectCreation] object creation of type Number
# 25| -1: [TypeMention] Number
# 25| 0: [MulExpr] ... * ...
# 25| 0: [PropertyCall] access to property Value
# 25| -1: [ParameterAccess] access to parameter n1
# 25| 1: [PropertyCall] access to property Value
# 25| -1: [ParameterAccess] access to parameter n2
# 27| 12: [CheckedDivOperator] checked /
# 27| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 27| 0: [Parameter] n1
# 27| -1: [TypeMention] Number
# 27| 1: [Parameter] n2
# 27| -1: [TypeMention] Number
# 28| 4: [ObjectCreation] object creation of type Number
# 28| -1: [TypeMention] Number
# 28| 0: [CheckedExpr] checked (...)
# 28| 0: [DivExpr] ... / ...
# 28| 0: [PropertyCall] access to property Value
# 28| -1: [ParameterAccess] access to parameter n1
# 28| 1: [PropertyCall] access to property Value
# 28| -1: [ParameterAccess] access to parameter n2
# 30| 13: [DivOperator] /
# 30| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 30| 0: [Parameter] n1
# 30| -1: [TypeMention] Number
# 30| 1: [Parameter] n2
# 30| -1: [TypeMention] Number
# 31| 4: [ObjectCreation] object creation of type Number
# 31| -1: [TypeMention] Number
# 31| 0: [DivExpr] ... / ...
# 31| 0: [PropertyCall] access to property Value
# 31| -1: [ParameterAccess] access to parameter n1
# 31| 1: [PropertyCall] access to property Value
# 31| -1: [ParameterAccess] access to parameter n2
# 33| 14: [CheckedMinusOperator] checked -
# 33| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 33| 0: [Parameter] n
# 33| -1: [TypeMention] Number
# 34| 4: [ObjectCreation] object creation of type Number
# 34| -1: [TypeMention] Number
# 34| 0: [CheckedExpr] checked (...)
# 34| 0: [UnaryMinusExpr] -...
# 34| 0: [PropertyCall] access to property Value
# 34| -1: [ParameterAccess] access to parameter n
# 36| 15: [MinusOperator] -
# 36| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 36| 0: [Parameter] n
# 36| -1: [TypeMention] Number
# 37| 4: [ObjectCreation] object creation of type Number
# 37| -1: [TypeMention] Number
# 37| 0: [UnaryMinusExpr] -...
# 37| 0: [PropertyCall] access to property Value
# 37| -1: [ParameterAccess] access to parameter n
# 39| 16: [CheckedIncrementOperator] checked ++
# 39| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 39| 0: [Parameter] n
# 39| -1: [TypeMention] Number
# 40| 4: [ObjectCreation] object creation of type Number
# 40| -1: [TypeMention] Number
# 40| 0: [CheckedExpr] checked (...)
# 40| 0: [AddExpr] ... + ...
# 40| 0: [PropertyCall] access to property Value
# 40| -1: [ParameterAccess] access to parameter n
# 40| 1: [IntLiteral] 1
# 42| 17: [IncrementOperator] ++
# 42| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 42| 0: [Parameter] n
# 42| -1: [TypeMention] Number
# 43| 4: [ObjectCreation] object creation of type Number
# 43| -1: [TypeMention] Number
# 43| 0: [AddExpr] ... + ...
# 43| 0: [PropertyCall] access to property Value
# 43| -1: [ParameterAccess] access to parameter n
# 43| 1: [IntLiteral] 1
# 45| 18: [CheckedDecrementOperator] checked --
# 45| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 45| 0: [Parameter] n
# 45| -1: [TypeMention] Number
# 46| 4: [ObjectCreation] object creation of type Number
# 46| -1: [TypeMention] Number
# 46| 0: [CheckedExpr] checked (...)
# 46| 0: [SubExpr] ... - ...
# 46| 0: [PropertyCall] access to property Value
# 46| -1: [ParameterAccess] access to parameter n
# 46| 1: [IntLiteral] 1
# 48| 19: [DecrementOperator] --
# 48| -1: [TypeMention] Number
#-----| 2: (Parameters)
# 48| 0: [Parameter] n
# 48| -1: [TypeMention] Number
# 49| 4: [ObjectCreation] object creation of type Number
# 49| -1: [TypeMention] Number
# 49| 0: [SubExpr] ... - ...
# 49| 0: [PropertyCall] access to property Value
# 49| -1: [ParameterAccess] access to parameter n
# 49| 1: [IntLiteral] 1
# 51| 20: [ExplicitConversionOperator] explicit conversion
# 51| -1: [TypeMention] short
#-----| 2: (Parameters)
# 51| 0: [Parameter] n
# 51| -1: [TypeMention] Number
# 52| 4: [CastExpr] (...) ...
# 52| 0: [TypeAccess] access to type Int16
# 52| 0: [TypeMention] short
# 52| 1: [PropertyCall] access to property Value
# 52| -1: [ParameterAccess] access to parameter n
# 54| 21: [CheckedExplicitConversionOperator] checked explicit conversion
# 54| -1: [TypeMention] short
#-----| 2: (Parameters)
# 54| 0: [Parameter] n
# 54| -1: [TypeMention] Number
# 55| 4: [CheckedExpr] checked (...)
# 55| 0: [CastExpr] (...) ...
# 55| 0: [TypeAccess] access to type Int16
# 55| 0: [TypeMention] short
# 55| 1: [PropertyCall] access to property Value
# 55| -1: [ParameterAccess] access to parameter n
GenericAttribute.cs:
# 3| [GenericAssemblyAttribute] [assembly: MyGeneric<Int32>(...)]
# 3| 0: [TypeMention] MyGenericAttribute<int>
@@ -439,6 +657,97 @@ RelaxedShift.cs:
# 30| 1: [OperatorCall] call to operator >>>
# 30| 0: [LocalVariableAccess] access to local variable n31
# 30| 1: [StringLiteralUtf16] "3"
RequiredMembers.cs:
# 4| [Class] ClassRequiredMembers
# 6| 4: [Field] RequiredField
# 6| -1: [TypeMention] object
# 7| 5: [Property] RequiredProperty
# 7| -1: [TypeMention] string
# 7| 3: [Getter] get_RequiredProperty
# 7| 4: [Setter] set_RequiredProperty
#-----| 2: (Parameters)
# 7| 0: [Parameter] value
# 8| 6: [Property] VirtualProperty
# 8| -1: [TypeMention] object
# 8| 3: [Getter] get_VirtualProperty
# 8| 4: [Setter] set_VirtualProperty
#-----| 2: (Parameters)
# 8| 0: [Parameter] value
# 10| 7: [InstanceConstructor] ClassRequiredMembers
# 10| 4: [BlockStmt] {...}
# 13| 8: [InstanceConstructor] ClassRequiredMembers
#-----| 0: (Attributes)
# 12| 1: [DefaultAttribute] [SetsRequiredMembers(...)]
# 12| 0: [TypeMention] SetsRequiredMembersAttribute
#-----| 2: (Parameters)
# 13| 0: [Parameter] requiredField
# 13| -1: [TypeMention] object
# 13| 1: [Parameter] requiredProperty
# 13| -1: [TypeMention] string
# 14| 4: [BlockStmt] {...}
# 15| 0: [ExprStmt] ...;
# 15| 0: [AssignExpr] ... = ...
# 15| 0: [FieldAccess] access to field RequiredField
# 15| 1: [ParameterAccess] access to parameter requiredField
# 16| 1: [ExprStmt] ...;
# 16| 0: [AssignExpr] ... = ...
# 16| 0: [PropertyCall] access to property RequiredProperty
# 16| 1: [ParameterAccess] access to parameter requiredProperty
# 20| [Class] ClassRequiredMembersSub
#-----| 3: (Base types)
# 20| 0: [TypeMention] ClassRequiredMembers
# 22| 4: [Property] VirtualProperty
# 22| -1: [TypeMention] object
# 22| 3: [Getter] get_VirtualProperty
# 22| 4: [Setter] set_VirtualProperty
#-----| 2: (Parameters)
# 22| 0: [Parameter] value
# 24| 5: [InstanceConstructor] ClassRequiredMembersSub
# 24| 3: [ConstructorInitializer] call to constructor ClassRequiredMembers
# 24| 4: [BlockStmt] {...}
# 27| 6: [InstanceConstructor] ClassRequiredMembersSub
#-----| 0: (Attributes)
# 26| 1: [DefaultAttribute] [SetsRequiredMembers(...)]
# 26| 0: [TypeMention] SetsRequiredMembersAttribute
#-----| 2: (Parameters)
# 27| 0: [Parameter] requiredField
# 27| -1: [TypeMention] object
# 27| 1: [Parameter] requiredProperty
# 27| -1: [TypeMention] string
# 27| 2: [Parameter] virtualProperty
# 27| -1: [TypeMention] object
# 27| 3: [ConstructorInitializer] call to constructor ClassRequiredMembers
# 27| 0: [ParameterAccess] access to parameter requiredField
# 27| 1: [ParameterAccess] access to parameter requiredProperty
# 28| 4: [BlockStmt] {...}
# 29| 0: [ExprStmt] ...;
# 29| 0: [AssignExpr] ... = ...
# 29| 0: [PropertyCall] access to property VirtualProperty
# 29| 1: [ParameterAccess] access to parameter virtualProperty
# 33| [RecordClass] RecordRequiredMembers
# 33| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 33| 0: [Parameter] left
# 33| 1: [Parameter] right
# 33| 13: [EQOperator] ==
#-----| 2: (Parameters)
# 33| 0: [Parameter] left
# 33| 1: [Parameter] right
# 33| 14: [Property] EqualityContract
# 33| 3: [Getter] get_EqualityContract
# 35| 15: [Property] X
# 35| -1: [TypeMention] object
# 35| 3: [Getter] get_X
# 35| 4: [Setter] set_X
#-----| 2: (Parameters)
# 35| 0: [Parameter] value
# 38| [Struct] StructRequiredMembers
# 40| 5: [Property] Y
# 40| -1: [TypeMention] string
# 40| 3: [Getter] get_Y
# 40| 4: [Setter] set_Y
#-----| 2: (Parameters)
# 40| 0: [Parameter] value
Scoped.cs:
# 1| [Struct] S1
# 2| [Struct] S2

View File

@@ -0,0 +1,42 @@
using System;
using System.Diagnostics.CodeAnalysis;
public class ClassRequiredMembers
{
public required object? RequiredField;
public required string? RequiredProperty { get; init; }
public virtual object? VirtualProperty { get; init; }
public ClassRequiredMembers() { }
[SetsRequiredMembers]
public ClassRequiredMembers(object requiredField, string requiredProperty)
{
RequiredField = requiredField;
RequiredProperty = requiredProperty;
}
}
public class ClassRequiredMembersSub : ClassRequiredMembers
{
public override required object? VirtualProperty { get; init; }
public ClassRequiredMembersSub() : base() { }
[SetsRequiredMembers]
public ClassRequiredMembersSub(object requiredField, string requiredProperty, object virtualProperty) : base(requiredField, requiredProperty)
{
VirtualProperty = virtualProperty;
}
}
public record RecordRequiredMembers
{
public required object? X { get; init; }
}
public struct StructRequiredMembers
{
public required string? Y { get; init; }
}

View File

@@ -0,0 +1,16 @@
| CheckedOperators.cs:9:43:9:43 | checked + | op_CheckedAddition | CheckedAddOperator |
| CheckedOperators.cs:12:35:12:35 | + | op_Addition | AddOperator |
| CheckedOperators.cs:15:43:15:43 | checked - | op_CheckedSubtraction | CheckedSubOperator |
| CheckedOperators.cs:18:35:18:35 | - | op_Subtraction | SubOperator |
| CheckedOperators.cs:21:43:21:43 | checked * | op_CheckedMultiply | CheckedMulOperator |
| CheckedOperators.cs:24:35:24:35 | * | op_Multiply | MulOperator |
| CheckedOperators.cs:27:43:27:43 | checked / | op_CheckedDivision | CheckedDivOperator |
| CheckedOperators.cs:30:35:30:35 | / | op_Division | DivOperator |
| CheckedOperators.cs:33:43:33:43 | checked - | op_CheckedUnaryNegation | CheckedMinusOperator |
| CheckedOperators.cs:36:35:36:35 | - | op_UnaryNegation | MinusOperator |
| CheckedOperators.cs:39:43:39:44 | checked ++ | op_CheckedIncrement | CheckedIncrementOperator |
| CheckedOperators.cs:42:35:42:36 | ++ | op_Increment | IncrementOperator |
| CheckedOperators.cs:45:43:45:44 | checked -- | op_CheckedDecrement | CheckedDecrementOperator |
| CheckedOperators.cs:48:35:48:36 | -- | op_Decrement | DecrementOperator |
| CheckedOperators.cs:51:28:51:35 | explicit conversion | op_Explicit | ExplicitConversionOperator |
| CheckedOperators.cs:54:28:54:35 | checked explicit conversion | op_CheckedExplicit | CheckedExplicitConversionOperator |

View File

@@ -0,0 +1,5 @@
import csharp
from Operator o
where o.getFile().getStem() = "CheckedOperators"
select o, o.getFunctionName(), o.getAPrimaryQlClass()

View File

@@ -0,0 +1,5 @@
| RequiredMembers.cs:6:29:6:41 | RequiredField | ClassRequiredMembers | Field |
| RequiredMembers.cs:7:29:7:44 | RequiredProperty | ClassRequiredMembers | Property |
| RequiredMembers.cs:22:38:22:52 | VirtualProperty | ClassRequiredMembersSub | Property |
| RequiredMembers.cs:35:29:35:29 | X | RecordRequiredMembers | Property |
| RequiredMembers.cs:40:29:40:29 | Y | StructRequiredMembers | Property |

View File

@@ -0,0 +1,8 @@
import csharp
query predicate requiredmembers(Member m, string type, string qlclass) {
m.getFile().getStem() = "RequiredMembers" and
m.isRequired() and
type = m.getDeclaringType().getName() and
qlclass = m.getAPrimaryQlClass()
}

View File

@@ -238,3 +238,7 @@
| ViableCallable.cs:458:10:458:14 | M5<> | ViableCallable.cs:444:23:444:27 | M2<> |
| ViableCallable.cs:475:10:475:12 | Run | ViableCallable.cs:468:10:468:11 | M2 |
| ViableCallable.cs:475:10:475:12 | Run | ViableCallable.cs:473:17:473:18 | M1 |
| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:487:32:487:32 | + |
| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:488:40:488:40 | checked + |
| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:489:28:489:35 | explicit conversion |
| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:490:28:490:35 | checked explicit conversion |

View File

@@ -471,3 +471,7 @@
| ViableCallable.cs:461:9:461:30 | call to method M2<T> | C17.M2<T>(Func<T>) |
| ViableCallable.cs:478:9:478:14 | call to method M1 | C18.M1() |
| ViableCallable.cs:481:9:481:14 | call to method M2 | I2.M2() |
| ViableCallable.cs:495:18:495:22 | call to operator + | C19.+(C19, C19) |
| ViableCallable.cs:498:26:498:30 | call to operator checked + | C19.checked +(C19, C19) |
| ViableCallable.cs:501:18:501:23 | call to operator explicit conversion | C19.explicit conversion(C19) |
| ViableCallable.cs:504:26:504:31 | call to operator checked explicit conversion | C19.checked explicit conversion(C19) |

View File

@@ -480,4 +480,27 @@ class C18 : I2
// Viable callables: I2.M2()
i.M2();
}
}
class C19
{
public static C19 operator +(C19 x, C19 y) => throw null;
public static C19 operator checked +(C19 x, C19 y) => throw null;
public static explicit operator int(C19 x) => throw null;
public static explicit operator checked int(C19 x) => throw null;
void Run(C19 c)
{
// Viable callables: C19.op_Addition()
var c1 = c + c;
// Viable callables: C19.op_CheckedAddition()
var c2 = checked(c + c);
// Viable callables: C19.op_Explicit()
var n1 = (int)c;
// Viable callables: C19.op_CheckedExplicit()
var n2 = checked((int)c);
}
}

View File

@@ -268,3 +268,7 @@
| ViableCallable.cs:423:9:423:21 | call to method M<String> | M<> | A5 |
| ViableCallable.cs:478:9:478:14 | call to method M1 | M1 | C18 |
| ViableCallable.cs:481:9:481:14 | call to method M2 | M2 | I2 |
| ViableCallable.cs:495:18:495:22 | call to operator + | + | C19 |
| ViableCallable.cs:498:26:498:30 | call to operator checked + | checked + | C19 |
| ViableCallable.cs:501:18:501:23 | call to operator explicit conversion | explicit conversion | C19 |
| ViableCallable.cs:504:26:504:31 | call to operator checked explicit conversion | checked explicit conversion | C19 |

View File

@@ -6,7 +6,11 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
dotnet_platform="linux-x64"
elif [[ "$OSTYPE" == "darwin"* ]]; then
platform="osx64"
dotnet_platform="osx-x64"
if [[ $(uname -m) == 'arm64' ]]; then
dotnet_platform="osx-arm64"
else
dotnet_platform="osx-x64"
fi
else
echo "Unknown OS"
exit 1

View File

@@ -17,7 +17,7 @@
.NET 5, .NET 6","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
Go (aka Golang), "Go up to 1.20", "Go 1.11 or more recent", ``.go``
Java,"Java 7 to 19 [4]_","javac (OpenJDK and Oracle JDK),
Java,"Java 7 to 20 [4]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [5]_",``.java``
Kotlin [6]_,"Kotlin 1.5.0 to 1.8.20","kotlinc",``.kt``
@@ -31,7 +31,7 @@
.. [1] C++20 support is currently in beta. Supported for GCC on Linux only. Modules are *not* supported.
.. [2] Support for the clang-cl compiler is preliminary.
.. [3] Support for the Arm Compiler (armcc) is preliminary.
.. [4] Builds that execute on Java 7 to 19 can be analyzed. The analysis understands Java 19 standard language features.
.. [4] Builds that execute on Java 7 to 20 can be analyzed. The analysis understands Java 20 standard language features.
.. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin.
.. [6] Kotlin support is currently in beta.
.. [7] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files.

View File

@@ -1,3 +1,13 @@
## 0.4.3
### New Features
* Go 1.20 is now supported. The extractor now functions as expected when Go 1.20 is installed; the definition of `implementsComparable` has been updated according to Go 1.20's new, more-liberal rules; and taint flow models have been added for relevant, new standard-library functions.
### Minor Analysis Improvements
* Support for the Twirp framework has been added.
## 0.4.2
No user-facing changes.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Support for the Twirp framework has been added.

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Go 1.20 is now supported. The extractor now functions as expected when Go 1.20 is installed, the definitions of `implementsComparable` has been updated according to Go 1.20's new, more-liberal rules, and taint flow models have been added for relevant new standard library functions.

View File

@@ -0,0 +1,9 @@
## 0.4.3
### New Features
* Go 1.20 is now supported. The extractor now functions as expected when Go 1.20 is installed; the definition of `implementsComparable` has been updated according to Go 1.20's new, more-liberal rules; and taint flow models have been added for relevant, new standard-library functions.
### Minor Analysis Improvements
* Support for the Twirp framework has been added.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.2
lastReleaseVersion: 0.4.3

View File

@@ -1,5 +1,5 @@
name: codeql/go-all
version: 0.4.3-dev
version: 0.4.4-dev
groups: go
dbscheme: go.dbscheme
extractor: go

View File

@@ -56,14 +56,14 @@ private predicate isIncorrectIntegerConversion(int sourceBitSize, int sinkBitSiz
* integer types, which could cause unexpected values.
*/
class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
boolean sourceIsSigned;
boolean sinkIsSigned;
int sourceBitSize;
int sinkBitSize;
ConversionWithoutBoundsCheckConfig() {
sourceIsSigned in [true, false] and
sinkIsSigned in [true, false] and
isIncorrectIntegerConversion(sourceBitSize, sinkBitSize) and
this = "ConversionWithoutBoundsCheckConfig" + sourceBitSize + sourceIsSigned + sinkBitSize
this = "ConversionWithoutBoundsCheckConfig" + sourceBitSize + sinkIsSigned + sinkBitSize
}
/** Gets the bit size of the source. */
@@ -75,11 +75,6 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
|
c.getTarget() = ip and source = c.getResult(0)
|
(
if ip.getResultType(0) instanceof SignedIntegerType
then sourceIsSigned = true
else sourceIsSigned = false
) and
(
apparentBitSize = ip.getTargetBitSize()
or
@@ -112,10 +107,13 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
predicate isSinkWithBitSize(DataFlow::TypeCastNode sink, int bitSize) {
sink.asExpr() instanceof ConversionExpr and
exists(IntegerType integerType | sink.getResultType().getUnderlyingType() = integerType |
bitSize = integerType.getSize()
or
not exists(integerType.getSize()) and
bitSize = getIntTypeBitSize(sink.getFile())
(
bitSize = integerType.getSize()
or
not exists(integerType.getSize()) and
bitSize = getIntTypeBitSize(sink.getFile())
) and
if integerType instanceof SignedIntegerType then sinkIsSigned = true else sinkIsSigned = false
) and
not exists(ShrExpr shrExpr |
shrExpr.getLeftOperand().getGlobalValueNumber() =
@@ -134,7 +132,7 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
if sinkBitSize != 0 then bitSize = sinkBitSize else bitSize = 32
|
node = DataFlow::BarrierGuard<upperBoundCheckGuard/3>::getABarrierNodeForGuard(g) and
g.isBoundFor(bitSize, sourceIsSigned)
g.isBoundFor(bitSize, sinkIsSigned)
)
}

View File

@@ -1,3 +1,13 @@
## 0.4.3
### New Queries
* Added a new query, `go/unhandled-writable-file-close`, to detect instances where writable file handles are closed without appropriate checks for errors.
### Query Metadata Changes
* The precision of the `go/log-injection` query was decreased from `high` to `medium`, since it may not be able to identify every way in which log data may be sanitized. This also aligns it with the precision of comparable queries for other languages.
## 0.4.2
No user-facing changes.

View File

@@ -1,4 +0,0 @@
---
category: newQuery
---
* Added a new query, `go/unhandled-writable-file-close`, to detect instances where writable file handles are closed without appropriate checks for errors.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `go/incorrect-integer-conversion` now correctly recognises guards of the form `if val <= x` to protect a conversion `uintX(val)` when `x` is in the range `(math.MaxIntX, math.MaxUintX]`.

View File

@@ -1,4 +1,9 @@
---
category: queryMetadata
---
## 0.4.3
### New Queries
* Added a new query, `go/unhandled-writable-file-close`, to detect instances where writable file handles are closed without appropriate checks for errors.
### Query Metadata Changes
* The precision of the `go/log-injection` query was decreased from `high` to `medium`, since it may not be able to identify every way in which log data may be sanitized. This also aligns it with the precision of comparable queries for other languages.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.2
lastReleaseVersion: 0.4.3

View File

@@ -1,5 +1,5 @@
name: codeql/go-queries
version: 0.4.3-dev
version: 0.4.4-dev
groups:
- go
- queries

View File

@@ -7,7 +7,7 @@ func testing() {
nonvariadicDeclaredFunction([]int{})
}
func variadicDeclaredFunction(x ...int) int { // $ isVariadic
func variadicDeclaredFunction(x ...int) int {
a := make([]int, 0, 10)
y := append(x, a...)
print(x[0], x[1])
@@ -15,7 +15,7 @@ func variadicDeclaredFunction(x ...int) int { // $ isVariadic
fmt.Fprint(nil, nil, nil)
variadicFunctionLiteral := func(z ...int) int { return z[1] } // $ isVariadic
return variadicFunctionLiteral(y...)
}
} // $ isVariadic
func nonvariadicDeclaredFunction(x []int) int {
return 0

View File

@@ -59,7 +59,7 @@ func main() {
http.HandleFunc("/foo", handler) // $ handler="/foo"
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { // $ handler="/bar"
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
}) // $ handler="/bar"
}

View File

@@ -264,6 +264,9 @@ func testBoundsChecking(input string) {
_ = int16(parsed)
}
}
if parsed <= math.MaxUint16 {
_ = uint16(parsed)
}
}
{
parsed, err := strconv.ParseUint(input, 10, 32)

View File

@@ -0,0 +1,6 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

View File

@@ -0,0 +1,13 @@
plugins {
/**
* Use `apply false` in the top-level build.gradle file to add a Gradle
* plugin as a build dependency but not apply it to the current (root)
* project. Don't use `apply false` in sub-projects. For more information,
* see Applying external plugins with same version to subprojects.
*/
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
}

View File

@@ -0,0 +1,28 @@
{
"markdownMessage": "An Android build may have failed. Ensure the Code Scanning workflow installs required dependencies, and that the [Gradle and Android SDK versions are compatible](https://developer.android.com/studio/releases/gradle-plugin#updating-gradle). Suspicious output line: ` > Minimum supported Gradle version is 7.4. Current version is 7.3. If using the gradle wrapper, try editing the distributionUrl in <test-root-directory>/gradle/wrapper/gradle-wrapper.properties to gradle-7.4-all.zip`",
"severity": "error",
"source": {
"extractorName": "java",
"id": "java/autobuilder/android-build-failure",
"name": "Android build failure"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"markdownMessage": "An Android build may have failed. Ensure the Code Scanning workflow installs required dependencies, and that the [Gradle and Android SDK versions are compatible](https://developer.android.com/studio/releases/gradle-plugin#updating-gradle). Suspicious output line: `Caused by: java.lang.RuntimeException: Minimum supported Gradle version is 7.4. Current version is 7.3. If using the gradle wrapper, try editing the distributionUrl in <test-root-directory>/gradle/wrapper/gradle-wrapper.properties to gradle-7.4-all.zip`",
"severity": "error",
"source": {
"extractorName": "java",
"id": "java/autobuilder/android-build-failure",
"name": "Android build failure"
},
"visibility": {
"cliSummaryTable": false,
"statusPage": false,
"telemetry": true
}
}

View File

@@ -0,0 +1,4 @@
# We currently have a bug where gradle tests become flaky when executed in parallel
# - sometimes, gradle fails to connect to the gradle daemon.
# Therefore, force this test to run sequentially.
# Additionally, Android SDK on-demand downloading can fail when multiple tests try to download the same SDK in parallel.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -0,0 +1,240 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

View File

@@ -0,0 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,58 @@
/**
* The first line in the build configuration applies the Android Gradle plugin
* to this build and makes the android block available to specify
* Android-specific build options.
*/
plugins {
id 'com.android.application'
}
/**
* The android block is where you configure all your Android-specific
* build options.
*/
android {
/**
* The app's namespace. Used primarily to access app resources.
*/
namespace 'com.github.androidsample'
/**
* compileSdk specifies the Android API level Gradle should use to
* compile your app. This means your app can use the API features included in
* this API level and lower.
*/
compileSdk 33
/**
* The defaultConfig block encapsulates default settings and entries for all
* build variants and can override some attributes in main/AndroidManifest.xml
* dynamically from the build system. You can configure product flavors to override
* these values for different versions of your app.
*/
defaultConfig {
// Uniquely identifies the package for publishing.
applicationId 'com.github.androidsample'
// Defines the minimum API level required to run the app.
minSdk 21
// Specifies the API level used to test the app.
targetSdk 33
// Defines the version number of your app.
versionCode 1
// Defines a user-friendly version name for your app.
versionName "1.0"
}
variantFilter { variant -> if (variant.buildType.name == "debug") { setIgnore(true) } }
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.androidsample">
<application android:label="AndroidSample">
<activity android:name="Main" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,11 @@
package com.github.androidsample;
import android.app.Activity;
import android.os.Bundle;
public class Main extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState) {
}
}

View File

@@ -0,0 +1,40 @@
pluginManagement {
/**
* The pluginManagement {repositories {...}} block configures the
* repositories Gradle uses to search or download the Gradle plugins and
* their transitive dependencies. Gradle pre-configures support for remote
* repositories such as JCenter, Maven Central, and Ivy. You can also use
* local repositories or define your own remote repositories. The code below
* defines the Gradle Plugin Portal, Google's Maven repository,
* and the Maven Central Repository as the repositories Gradle should use to look for its
* dependencies.
*/
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
/**
* The dependencyResolutionManagement {repositories {...}}
* block is where you configure the repositories and dependencies used by
* all modules in your project, such as libraries that you are using to
* create your application. However, you should configure module-specific
* dependencies in each module-level build.gradle file. For new projects,
* Android Studio includes Google's Maven repository and the Maven Central
* Repository by default, but it does not configure any dependencies (unless
* you select a template that requires some).
*/
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "Android Sample"
include ':project'

View File

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

View File

@@ -0,0 +1,42 @@
{
"markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies. Suspicious output line: `[ERROR] COMPILATION ERROR : `",
"severity": "error",
"source": {
"extractorName": "java",
"id": "java/autobuilder/compilation-error",
"name": "Some of your code may have failed to compile"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies. Suspicious output line: `[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project maven-sample: Compilation failure`",
"severity": "error",
"source": {
"extractorName": "java",
"id": "java/autobuilder/compilation-error",
"name": "Some of your code may have failed to compile"
},
"visibility": {
"cliSummaryTable": false,
"statusPage": false,
"telemetry": true
}
}
{
"markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies. Suspicious output line: `org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project maven-sample: Compilation failure`",
"severity": "error",
"source": {
"extractorName": "java",
"id": "java/autobuilder/compilation-error",
"name": "Some of your code may have failed to compile"
},
"visibility": {
"cliSummaryTable": false,
"statusPage": false,
"telemetry": true
}
}

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>maven-sample</artifactId>
<version>1.0-SNAPSHOT</version>
<name>maven-sample</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<version>1.1.1</version>
<executions>
<execution>
<id>check-maven-version</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.App</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<java>
<licenseHeader>
<content>/* FAIL ME */</content>
</licenseHeader>
</java>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,30 @@
paaaaaaaaaaaaaaaackage com.example;
import java.util.regex.Pattern;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
String expectedVersion = System.getenv("EXPECT_MAVEN");
Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize();
String observedVersion = mavenHome.getFileName().toString();
if (expectedVersion != null && !expectedVersion.equals(observedVersion)) {
System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome);
System.exit(1);
}
String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX");
String command = System.getProperty("sun.java.command");
if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) {
System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'");
System.exit(1);
}
}
}

View File

@@ -0,0 +1,8 @@
<html>
<head>
<title>A sample</title>
</head>
<body>
<p>Hello world!</p>
</body>
</html>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<struts>
This is a sample file
</struts>

View File

@@ -0,0 +1,20 @@
package com.example;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
}

View File

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

View File

@@ -0,0 +1,14 @@
{
"markdownMessage": "A dependency failed to download. Check that all dependencies are available, and [supply credentials for any private dependencies](https://github.com/Azure/actions-workflow-samples/blob/master/assets/create-secrets-for-GitHub-workflows.md#set-up-secrets-in-github-action-workflows). Suspicious output line: `Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact junit:junit-nonesuch:jar:4.11 in central (https://repo.maven.apache.org/maven2)`",
"severity": "error",
"source": {
"extractorName": "java",
"id": "java/autobuilder/dependency-download-failure",
"name": "Failed to download a dependency"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>maven-sample</artifactId>
<version>1.0-SNAPSHOT</version>
<name>maven-sample</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-nonesuch</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<version>1.1.1</version>
<executions>
<execution>
<id>check-maven-version</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.App</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<java>
<licenseHeader>
<content>/* FAIL ME */</content>
</licenseHeader>
</java>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,30 @@
package com.example;
import java.util.regex.Pattern;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
String expectedVersion = System.getenv("EXPECT_MAVEN");
Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize();
String observedVersion = mavenHome.getFileName().toString();
if (expectedVersion != null && !expectedVersion.equals(observedVersion)) {
System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome);
System.exit(1);
}
String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX");
String command = System.getProperty("sun.java.command");
if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) {
System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'");
System.exit(1);
}
}
}

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