mirror of
https://github.com/github/codeql.git
synced 2026-06-12 16:31:10 +02:00
Compare commits
104 Commits
copilot/vs
...
copilot/ql
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ec64167ac | ||
|
|
de281fc00c | ||
|
|
ad18659373 | ||
|
|
923fe2dcb9 | ||
|
|
642259cd51 | ||
|
|
0d984588f9 | ||
|
|
b4a9689341 | ||
|
|
6a8e20a0c8 | ||
|
|
4c411bbcb5 | ||
|
|
b60bf8c79f | ||
|
|
ef00aa2567 | ||
|
|
6d0968744b | ||
|
|
98f147556a | ||
|
|
4c1a0058bf | ||
|
|
f5919875b7 | ||
|
|
8d456df26f | ||
|
|
72fcf27d1a | ||
|
|
0cea01c22f | ||
|
|
a473565256 | ||
|
|
c47135a40b | ||
|
|
3cbc8f0262 | ||
|
|
cc1ea25856 | ||
|
|
5a38cbd5d5 | ||
|
|
e93bc11f6f | ||
|
|
cf6d94cf8a | ||
|
|
292fc8b777 | ||
|
|
a1759d9834 | ||
|
|
6b74874372 | ||
|
|
ef29d22c75 | ||
|
|
1f91f915c7 | ||
|
|
ba8eebe2b5 | ||
|
|
dc1409e5f4 | ||
|
|
284f42bb9e | ||
|
|
2f3524de74 | ||
|
|
b32573b060 | ||
|
|
cd2398aeea | ||
|
|
d6892eaf0d | ||
|
|
d2972cb53f | ||
|
|
5576d30780 | ||
|
|
da999ee440 | ||
|
|
3da195f50f | ||
|
|
93a4b427e3 | ||
|
|
0430c71318 | ||
|
|
f34275636c | ||
|
|
0a801440b9 | ||
|
|
6f2cc43f32 | ||
|
|
5042fdee84 | ||
|
|
04341c47bd | ||
|
|
af45e53e77 | ||
|
|
b27d08ee32 | ||
|
|
20ce679d61 | ||
|
|
f62ebef9e0 | ||
|
|
c3ef1ddd64 | ||
|
|
dede5bc49b | ||
|
|
ad97b6dd64 | ||
|
|
dc0c7d7ec2 | ||
|
|
61a5cece56 | ||
|
|
566a92e555 | ||
|
|
1fd31d0ddd | ||
|
|
c4e3720d8a | ||
|
|
0547e9c98d | ||
|
|
2a3cff382c | ||
|
|
c610af88d3 | ||
|
|
fa63dad1d1 | ||
|
|
019a5c01ad | ||
|
|
5fb75ac987 | ||
|
|
c1c9287535 | ||
|
|
d1226b71de | ||
|
|
71a363545a | ||
|
|
62207f152c | ||
|
|
d5f94475b5 | ||
|
|
00e95a0757 | ||
|
|
c695c151ea | ||
|
|
b38440490a | ||
|
|
aee33a0cc9 | ||
|
|
df15a719cb | ||
|
|
812e8e6b34 | ||
|
|
80c6f082d1 | ||
|
|
cc12740c0e | ||
|
|
acb5c0e70f | ||
|
|
6042adebae | ||
|
|
ec13e1bcd3 | ||
|
|
2884428b62 | ||
|
|
e8779295ee | ||
|
|
fa758d6bf5 | ||
|
|
fa9426c749 | ||
|
|
0ecca91dea | ||
|
|
f669a4f3bf | ||
|
|
3275c814bd | ||
|
|
9a180036a5 | ||
|
|
93e7ab52b7 | ||
|
|
facb3b681d | ||
|
|
b67694b2ab | ||
|
|
e10750b35e | ||
|
|
18550039f2 | ||
|
|
0caa483925 | ||
|
|
640b17ec78 | ||
|
|
a367294c23 | ||
|
|
b6004045bd | ||
|
|
cc7e03b0f5 | ||
|
|
1cbd423251 | ||
|
|
437244fe90 | ||
|
|
f7cf24d1f9 | ||
|
|
c3bafacf81 |
208
.github/workflows/go-version-update.yml
vendored
Normal file
208
.github/workflows/go-version-update.yml
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
name: Update Go version
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 3 * * 1" # Run weekly on Mondays at 3 AM UTC (1 = Monday)
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-go-version:
|
||||
name: Check and update Go version
|
||||
if: github.repository == 'github/codeql'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Fetch latest Go version
|
||||
id: fetch-version
|
||||
run: |
|
||||
LATEST_GO_VERSION=$(curl -s https://go.dev/dl/?mode=json | jq -r '.[0].version')
|
||||
|
||||
if [ -z "$LATEST_GO_VERSION" ] || [ "$LATEST_GO_VERSION" = "null" ]; then
|
||||
echo "Error: Failed to fetch latest Go version from go.dev"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Latest Go version from go.dev: $LATEST_GO_VERSION"
|
||||
echo "version=$LATEST_GO_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract version numbers (e.g., go1.26.0 -> 1.26.0)
|
||||
LATEST_VERSION_NUM=$(echo $LATEST_GO_VERSION | sed 's/^go//')
|
||||
echo "version_num=$LATEST_VERSION_NUM" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract major.minor version (e.g., 1.26.0 -> 1.26)
|
||||
LATEST_MAJOR_MINOR=$(echo $LATEST_VERSION_NUM | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
echo "major_minor=$LATEST_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check current Go version
|
||||
id: current-version
|
||||
run: |
|
||||
CURRENT_VERSION=$(sed -n 's/.*go_sdk\.download(version = \"\([^\"]*\)\".*/\1/p' MODULE.bazel)
|
||||
|
||||
if [ -z "$CURRENT_VERSION" ]; then
|
||||
echo "Error: Could not extract Go version from MODULE.bazel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Current Go version in MODULE.bazel: $CURRENT_VERSION"
|
||||
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract major.minor version
|
||||
CURRENT_MAJOR_MINOR=$(echo $CURRENT_VERSION | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
echo "major_minor=$CURRENT_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Compare versions
|
||||
id: compare
|
||||
run: |
|
||||
LATEST="${{ steps.fetch-version.outputs.version_num }}"
|
||||
CURRENT="${{ steps.current-version.outputs.version }}"
|
||||
|
||||
echo "Latest: $LATEST"
|
||||
echo "Current: $CURRENT"
|
||||
|
||||
if [ "$LATEST" = "$CURRENT" ]; then
|
||||
echo "Go version is up to date"
|
||||
echo "needs_update=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Go version needs update from $CURRENT to $LATEST"
|
||||
echo "needs_update=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Update Go version in files
|
||||
if: steps.compare.outputs.needs_update == 'true'
|
||||
run: |
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
LATEST_MAJOR_MINOR="${{ steps.fetch-version.outputs.major_minor }}"
|
||||
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
|
||||
CURRENT_MAJOR_MINOR="${{ steps.current-version.outputs.major_minor }}"
|
||||
|
||||
echo "Updating from $CURRENT_VERSION to $LATEST_VERSION_NUM"
|
||||
|
||||
# Escape dots in current version strings for use in sed patterns
|
||||
CURRENT_VERSION_ESCAPED=$(echo "$CURRENT_VERSION" | sed 's/\./\\./g')
|
||||
CURRENT_MAJOR_MINOR_ESCAPED=$(echo "$CURRENT_MAJOR_MINOR" | sed 's/\./\\./g')
|
||||
|
||||
# Update MODULE.bazel
|
||||
sed -i "s/go_sdk\.download(version = \"$CURRENT_VERSION_ESCAPED\")/go_sdk.download(version = \"$LATEST_VERSION_NUM\")/" MODULE.bazel
|
||||
if ! grep -q "go_sdk.download(version = \"$LATEST_VERSION_NUM\")" MODULE.bazel; then
|
||||
echo "Error: Failed to update MODULE.bazel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update go/extractor/go.mod
|
||||
if ! sed -i "s/^go $CURRENT_MAJOR_MINOR_ESCAPED\$/go $LATEST_MAJOR_MINOR/" go/extractor/go.mod; then
|
||||
echo "Warning: Failed to update go directive in go.mod"
|
||||
fi
|
||||
if ! sed -i "s/^toolchain go$CURRENT_VERSION_ESCAPED\$/toolchain go$LATEST_VERSION_NUM/" go/extractor/go.mod; then
|
||||
echo "Warning: Failed to update toolchain in go.mod"
|
||||
fi
|
||||
|
||||
# Update go/extractor/autobuilder/build-environment.go
|
||||
if ! sed -i "s/var maxGoVersion = util\.NewSemVer(\"$CURRENT_MAJOR_MINOR_ESCAPED\")/var maxGoVersion = util.NewSemVer(\"$LATEST_MAJOR_MINOR\")/" go/extractor/autobuilder/build-environment.go; then
|
||||
echo "Warning: Failed to update build-environment.go"
|
||||
fi
|
||||
|
||||
# Update go/actions/test/action.yml
|
||||
if ! sed -i "s/default: \"~$CURRENT_VERSION_ESCAPED\"/default: \"~$LATEST_VERSION_NUM\"/" go/actions/test/action.yml; then
|
||||
echo "Warning: Failed to update action.yml"
|
||||
fi
|
||||
|
||||
# Show what changed
|
||||
git diff
|
||||
|
||||
- name: Check for changes
|
||||
id: check-changes
|
||||
if: steps.compare.outputs.needs_update == 'true'
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
echo "No changes detected"
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Changes detected"
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check for existing PR
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
id: check-pr
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
PR_NUMBER=$(gh pr list --head "$BRANCH_NAME" --state open --json number --jq '.[0].number')
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
echo "Existing PR found: #$PR_NUMBER"
|
||||
echo "pr_exists=true" >> $GITHUB_OUTPUT
|
||||
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "No existing PR found"
|
||||
echo "pr_exists=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Commit and push changes
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
LATEST_MAJOR_MINOR="${{ steps.fetch-version.outputs.major_minor }}"
|
||||
|
||||
# Create or switch to branch
|
||||
git checkout -B "$BRANCH_NAME"
|
||||
|
||||
# Stage and commit changes
|
||||
git add MODULE.bazel go/extractor/go.mod go/extractor/autobuilder/build-environment.go go/actions/test/action.yml
|
||||
git commit -m "Go: Update to $LATEST_VERSION_NUM"
|
||||
|
||||
# Push changes
|
||||
git push --force-with-lease origin "$BRANCH_NAME"
|
||||
|
||||
- name: Create or update PR
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
|
||||
|
||||
PR_TITLE="Go: Update to $LATEST_VERSION_NUM"
|
||||
|
||||
PR_BODY=$(cat <<EOF
|
||||
This PR updates Go from $CURRENT_VERSION to $LATEST_VERSION_NUM.
|
||||
|
||||
Updated files:
|
||||
- \`MODULE.bazel\` - go_sdk.download version
|
||||
- \`go/extractor/go.mod\` - go directive and toolchain
|
||||
- \`go/extractor/autobuilder/build-environment.go\` - maxGoVersion (only if MAJOR.MINOR changes)
|
||||
- \`go/actions/test/action.yml\` - default go-test-version
|
||||
|
||||
This PR was automatically created by the [Go version update workflow](https://github.com/${{ github.repository }}/blob/main/.github/workflows/go-version-update.yml).
|
||||
EOF
|
||||
)
|
||||
|
||||
if [ "${{ steps.check-pr.outputs.pr_exists }}" = "true" ]; then
|
||||
echo "Updating existing PR #${{ steps.check-pr.outputs.pr_number }}"
|
||||
gh pr edit "${{ steps.check-pr.outputs.pr_number }}" --title "$PR_TITLE" --body "$PR_BODY"
|
||||
else
|
||||
echo "Creating new PR"
|
||||
gh pr create \
|
||||
--title "$PR_TITLE" \
|
||||
--body "$PR_BODY" \
|
||||
--base main \
|
||||
--head "$BRANCH_NAME" \
|
||||
--label "Go"
|
||||
fi
|
||||
@@ -273,7 +273,7 @@ use_repo(
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
go_sdk.download(version = "1.26.0")
|
||||
go_sdk.download(version = "1.26.4")
|
||||
|
||||
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
|
||||
go_deps.from_file(go_mod = "//go/extractor:go.mod")
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll"
|
||||
],
|
||||
"Bound Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/Bound.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll"
|
||||
],
|
||||
"ModulusAnalysis Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/ModulusAnalysis.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/ModulusAnalysis.qll"
|
||||
|
||||
2578
cpp/downgrades/0853f43dc8c08deecb473c54a2b70da8597f1ab5/old.dbscheme
Normal file
2578
cpp/downgrades/0853f43dc8c08deecb473c54a2b70da8597f1ab5/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Fix NameQualifier inconsistency
|
||||
compatibility: full
|
||||
@@ -1071,7 +1071,7 @@ class NullPointerType extends BuiltInType {
|
||||
* const float fa[40];
|
||||
* ```
|
||||
*/
|
||||
class DerivedType extends Type, @derivedtype {
|
||||
class DerivedType extends Type, NameQualifyingElement, @derivedtype {
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string getName() { derivedtypes(underlyingElement(this), result, _, _) }
|
||||
|
||||
@@ -1430,7 +1430,8 @@ specialnamequalifyingelements(
|
||||
@namequalifyingelement = @namespace
|
||||
| @specialnamequalifyingelement
|
||||
| @usertype
|
||||
| @decltype;
|
||||
| @decltype
|
||||
| @derivedtype;
|
||||
|
||||
namequalifiers(
|
||||
unique int id: @namequalifier,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Fix NameQualifier inconsistency
|
||||
compatibility: full
|
||||
@@ -1,3 +1,7 @@
|
||||
| inconsistency2.cpp:3:3:3:5 | T:: | inconsistency2.cpp:3:3:3:6 | x | inconsistency2.cpp:2:20:2:20 | T |
|
||||
| inconsistency2.cpp:3:3:3:11 | const s:: | inconsistency2.cpp:3:3:3:6 | x | file://:0:0:0:0 | const s |
|
||||
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | (int)... | inconsistency.cpp:4:8:4:8 | S |
|
||||
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | A | inconsistency.cpp:4:8:4:8 | S |
|
||||
| name_qualifiers.cpp:29:7:29:8 | :: | name_qualifiers.cpp:29:7:29:9 | x | file://:0:0:0:0 | (global namespace) |
|
||||
| name_qualifiers.cpp:31:7:31:10 | N1:: | name_qualifiers.cpp:31:7:31:12 | nx | name_qualifiers.cpp:4:11:4:12 | N1 |
|
||||
| name_qualifiers.cpp:34:7:34:8 | :: | name_qualifiers.cpp:34:9:34:12 | N1:: | file://:0:0:0:0 | (global namespace) |
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from NameQualifier nq, Location l
|
||||
where
|
||||
l = nq.getQualifiedElement().getLocation() and
|
||||
l.getFile().getShortName() = "name_qualifiers"
|
||||
where l = nq.getQualifiedElement().getLocation()
|
||||
select nq, nq.getQualifiedElement(), nq.getQualifyingElement()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// This file is present to test whether name-qualifying an enum constant leads to a database inconsistency.
|
||||
// As such, there is no QL part of the test.
|
||||
|
||||
|
||||
struct S { enum E { A }; };
|
||||
|
||||
static int f() {
|
||||
static void f() {
|
||||
switch(0) { case S::A: break; }
|
||||
}
|
||||
|
||||
12
cpp/ql/test/library-tests/name_qualifiers/inconsistency2.cpp
Normal file
12
cpp/ql/test/library-tests/name_qualifiers/inconsistency2.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace {
|
||||
template <typename T> T f() {
|
||||
T::x;
|
||||
return {};
|
||||
}
|
||||
struct s {
|
||||
static int x;
|
||||
};
|
||||
struct t {
|
||||
s x = f<const s>();
|
||||
};
|
||||
}
|
||||
@@ -9,6 +9,7 @@ dependencies:
|
||||
codeql/controlflow: ${workspace}
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/mad: ${workspace}
|
||||
codeql/rangeanalysis: ${workspace}
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/threat-models: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
|
||||
@@ -4,67 +4,31 @@
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
private import internal.rangeanalysis.BoundSpecific
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.dataflow.SSA::Ssa
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.SsaUtils as SU
|
||||
private import codeql.rangeanalysis.Bound as SharedBound
|
||||
|
||||
private newtype TBound =
|
||||
TBoundZero() or
|
||||
TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or
|
||||
TBoundExpr(Expr e) {
|
||||
interestingExprBound(e) and
|
||||
not exists(SsaVariable v | e = v.getAUse())
|
||||
}
|
||||
/** Provides C#-specific definitions for bounds. */
|
||||
private module BoundDefs implements SharedBound::BoundDefinitions<CS::Location> {
|
||||
class Type = CS::Type;
|
||||
|
||||
/**
|
||||
* A bound that may be inferred for an expression plus/minus an integer delta.
|
||||
*/
|
||||
abstract class Bound extends TBound {
|
||||
/** Gets a textual representation of this bound. */
|
||||
abstract string toString();
|
||||
class SsaVariable = SU::SsaVariable;
|
||||
|
||||
/** Gets an expression that equals this bound plus `delta`. */
|
||||
abstract Expr getExpr(int delta);
|
||||
class SsaSourceVariable = SourceVariable;
|
||||
|
||||
/** Gets an expression that equals this bound. */
|
||||
Expr getExpr() { result = this.getExpr(0) }
|
||||
class Expr = CS::ControlFlowNodes::ExprNode;
|
||||
|
||||
/** Gets the location of this bound. */
|
||||
abstract Location getLocation();
|
||||
class IntegralType = CS::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = CU::ConstantIntegerExpr;
|
||||
|
||||
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
|
||||
predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.getExpr()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The bound that corresponds to the integer 0. This is used to represent all
|
||||
* integer bounds as bounds are always accompanied by an added integer delta.
|
||||
*/
|
||||
class ZeroBound extends Bound, TBoundZero {
|
||||
override string toString() { result = "0" }
|
||||
module BoundImpl = SharedBound::Bound<CS::Location, BoundDefs>;
|
||||
|
||||
override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta }
|
||||
|
||||
override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound corresponding to the value of an SSA variable.
|
||||
*/
|
||||
class SsaBound extends Bound, TBoundSsa {
|
||||
/** Gets the SSA variable that equals this bound. */
|
||||
SsaVariable getSsa() { this = TBoundSsa(result) }
|
||||
|
||||
override string toString() { result = this.getSsa().toString() }
|
||||
|
||||
override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 }
|
||||
|
||||
override Location getLocation() { result = this.getSsa().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound that corresponds to the value of a specific expression that might be
|
||||
* interesting, but isn't otherwise represented by the value of an SSA variable.
|
||||
*/
|
||||
class ExprBound extends Bound, TBoundExpr {
|
||||
override string toString() { result = this.getExpr().toString() }
|
||||
|
||||
override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 }
|
||||
|
||||
override Location getLocation() { result = this.getExpr().getLocation() }
|
||||
}
|
||||
import BoundImpl
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Provides C#-specific definitions for bounds.
|
||||
*/
|
||||
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.dataflow.SSA::Ssa as Ssa
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.SsaUtils as SU
|
||||
|
||||
class SsaVariable = SU::SsaVariable;
|
||||
|
||||
class Expr = CS::ControlFlowNodes::ExprNode;
|
||||
|
||||
class Location = CS::Location;
|
||||
|
||||
class IntegralType = CS::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = CU::ConstantIntegerExpr;
|
||||
|
||||
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
|
||||
predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.getExpr()) }
|
||||
@@ -0,0 +1,139 @@
|
||||
.. _codeql-cli-2.25.6:
|
||||
|
||||
==========================
|
||||
CodeQL 2.25.6 (2026-06-04)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/application-security/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.25.6 runs a total of 496 security queries when configured with the Default suite (covering 169 CWE). The Extended suite enables an additional 131 queries (covering 32 more CWE).
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* When the :code:`git` executable is available, CodeQL can now obtain configuration and queries from SHA-256 Git repositories, and infer Git metadata about them.
|
||||
|
||||
Miscellaneous
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* The build of Eclipse Temurin OpenJDK that is used to run the CodeQL CLI has been updated to version 21.0.11.
|
||||
|
||||
Query Packs
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: :code:`actions/untrusted-checkout/critical`, :code:`actions/untrusted-checkout/high`, :code:`actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Adjusted :code:`actions/untrusted-checkout/critical` to align more with other untrusted resource queries, where the alert location is the location where the artifact is obtained from (the checkout point). This aligns with the other 2 related queries. This will cause the same alerts to re-open for closed alerts of this query.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Altered the alert message for clarity for queries: :code:`actions/untrusted-checkout/critical`, :code:`actions/untrusted-checkout/high`.
|
||||
* The :code:`actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
|
||||
|
||||
Query Metadata Changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Reversed adjustment of the name of :code:`actions/untrusted-checkout/high`, but kept the portion of the previous change for the word "trusted" to "privileged". Added a missing "a" to phrasing in :code:`actions/untrusted-checkout/high` and :code:`actions/untrusted-checkout/medium`.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* Upgraded to allow analysis of Swift 6.3.2.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added flow source models for :code:`scanf_s` and related functions.
|
||||
* Added a :code:`Call` column to :code:`LocalFlowSourceFunction::hasLocalFlowSource` and :code:`RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a :code:`Call` column continue to be supported.
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
* Full support for C# 14 / .NET 10. All new language features are now supported by the extractor. The QL library and data flow analysis now support the new C# 14 language constructs and include generated Models as Data (MaD) models for the .NET 10 runtime.
|
||||
* C# 14: Added support for user-defined instance increment/decrement operators.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* Added LLM-generated source and sink models for :code:`org.apache.avro`.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`js/clear-text-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`py/clear-text-logging-sensitive-data`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`swift/cleartext-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like :code:`^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`rust/cleartext-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Deprecated APIs
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`UsingAliasTypedefType` class has been deprecated. Use :code:`TypeAliasType` instead.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added a :code:`getOriginalTemplate` predicate to :code:`TemplateClass`, :code:`TemplateFunction`, :code:`TemplateVariable`, and :code:`AliasTemplateType`, which yields the class member template the template was generated from. The predicates only have results for templates that are members of class template instantiations.
|
||||
* Added :code:`AliasTemplateType` and :code:`AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
|
||||
@@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here <https://docs.g
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
codeql-cli-2.25.6
|
||||
codeql-cli-2.25.5
|
||||
codeql-cli-2.25.4
|
||||
codeql-cli-2.25.3
|
||||
|
||||
@@ -4,7 +4,7 @@ inputs:
|
||||
go-test-version:
|
||||
description: Which Go version to use for running the tests
|
||||
required: false
|
||||
default: "~1.26.0"
|
||||
default: "~1.26.4"
|
||||
run-code-checks:
|
||||
description: Whether to run formatting, code and qhelp generation checks
|
||||
required: false
|
||||
|
||||
@@ -2,14 +2,14 @@ module github.com/github/codeql-go/extractor
|
||||
|
||||
go 1.26
|
||||
|
||||
toolchain go1.26.0
|
||||
toolchain go1.26.4
|
||||
|
||||
// when updating this, run
|
||||
// bazel run @rules_go//go -- mod tidy
|
||||
// when adding or removing dependencies, run
|
||||
// bazel mod tidy
|
||||
require (
|
||||
golang.org/x/mod v0.36.0
|
||||
golang.org/x/mod v0.37.0
|
||||
golang.org/x/tools v0.45.0
|
||||
)
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
|
||||
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
|
||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import go
|
||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
||||
import GoCfg::ControlFlow::Consistency
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The Go control flow graph implementation has been migrated to use the shared CFG library. This is an internal change with no user-visible API changes.
|
||||
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* @name Print CFG
|
||||
* @description Produces a representation of a file's Control Flow Graph.
|
||||
* This query is used by the VS Code extension.
|
||||
* @id go/print-cfg
|
||||
* @kind graph
|
||||
* @tags ide-contextual-queries/print-cfg
|
||||
*/
|
||||
|
||||
import go
|
||||
import semmle.go.controlflow.ControlFlowGraph
|
||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
||||
|
||||
external string selectedSourceFile();
|
||||
|
||||
private predicate selectedSourceFileAlias = selectedSourceFile/0;
|
||||
|
||||
external int selectedSourceLine();
|
||||
|
||||
private predicate selectedSourceLineAlias = selectedSourceLine/0;
|
||||
|
||||
external int selectedSourceColumn();
|
||||
|
||||
private predicate selectedSourceColumnAlias = selectedSourceColumn/0;
|
||||
|
||||
module ViewCfgQueryInput implements GoCfg::ControlFlow::ViewCfgQueryInputSig<File> {
|
||||
predicate selectedSourceFile = selectedSourceFileAlias/0;
|
||||
|
||||
predicate selectedSourceLine = selectedSourceLineAlias/0;
|
||||
|
||||
predicate selectedSourceColumn = selectedSourceColumnAlias/0;
|
||||
|
||||
predicate cfgScopeSpan(
|
||||
CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn
|
||||
) {
|
||||
file = scope.getFile() and
|
||||
scope.getLocation().getStartLine() = startLine and
|
||||
scope.getLocation().getStartColumn() = startColumn and
|
||||
exists(Location loc |
|
||||
loc.getEndLine() = endLine and
|
||||
loc.getEndColumn() = endColumn and
|
||||
loc = scope.(FuncDef).getBody().getLocation()
|
||||
)
|
||||
or
|
||||
file = scope.(File) and
|
||||
startLine = 1 and
|
||||
startColumn = 1 and
|
||||
endLine = file.getNumberOfLines() and
|
||||
endColumn = 999999
|
||||
}
|
||||
}
|
||||
|
||||
import GoCfg::ControlFlow::ViewCfgQuery<File, ViewCfgQueryInput>
|
||||
@@ -431,7 +431,7 @@ private class HeuristicLoggerFunction extends Method {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mustNotReturnNormally() { logFunctionPrefix = "Fatal" }
|
||||
override predicate mayReturnNormally() { logFunctionPrefix != "Fatal" }
|
||||
|
||||
override predicate mustPanic() { logFunctionPrefix = "Panic" }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Provides queries to pretty-print a Go AST as a graph.
|
||||
*/
|
||||
overlay[local?]
|
||||
overlay[local]
|
||||
module;
|
||||
|
||||
import go
|
||||
|
||||
@@ -437,12 +437,11 @@ class Function extends ValueEntity, @functionobject {
|
||||
* This predicate is an over-approximation: it may hold for functions that can never
|
||||
* return normally, but it never fails to hold for functions that can.
|
||||
*
|
||||
* Library models should not override this predicate; override `mustNotReturnNormally`
|
||||
* instead, so that the control-flow graph construction can take the model into account.
|
||||
* Note this is declared here and not in `DeclaredFunction` so that library models can override this
|
||||
* by extending `Function` rather than having to remember to extend `DeclaredFunction`.
|
||||
*/
|
||||
predicate mayReturnNormally() {
|
||||
not this.mustPanic() and
|
||||
not this.mustNotReturnNormally() and
|
||||
(ControlFlow::mayReturnNormally(this.getFuncDecl()) or not exists(this.getBody()))
|
||||
}
|
||||
|
||||
@@ -462,16 +461,6 @@ class Function extends ValueEntity, @functionobject {
|
||||
*/
|
||||
predicate mustPanic() { none() }
|
||||
|
||||
/**
|
||||
* Holds if calling this function never returns normally (for example because it
|
||||
* always panics, exits the process, or loops forever).
|
||||
*
|
||||
* Unlike `mayReturnNormally`, this predicate must be defined without reference to
|
||||
* the control-flow graph, so that it can be used during CFG construction to
|
||||
* suppress normal-flow successors of calls to this function.
|
||||
*/
|
||||
predicate mustNotReturnNormally() { none() }
|
||||
|
||||
/** Gets the number of parameters of this function. */
|
||||
int getNumParameter() { result = this.getType().(SignatureType).getNumParameter() }
|
||||
|
||||
|
||||
@@ -5,27 +5,66 @@ overlay[local]
|
||||
module;
|
||||
|
||||
import go
|
||||
private import ControlFlowGraphShared
|
||||
private import ControlFlowGraphImpl
|
||||
private import codeql.controlflow.BasicBlock as BB
|
||||
private import codeql.controlflow.SuccessorType
|
||||
|
||||
/** A basic block in the control-flow graph. */
|
||||
class BasicBlock = GoCfg::Cfg::BasicBlock;
|
||||
private module Input implements BB::InputSig<Location> {
|
||||
/** A delineated part of the AST with its own CFG. */
|
||||
class CfgScope = ControlFlow::Root;
|
||||
|
||||
/** An entry basic block. */
|
||||
class EntryBasicBlock = GoCfg::Cfg::EntryBasicBlock;
|
||||
/** The class of control flow nodes. */
|
||||
class Node = ControlFlowNode;
|
||||
|
||||
/** Gets the CFG scope in which this node occurs. */
|
||||
CfgScope nodeGetCfgScope(Node node) { node.getRoot() = result }
|
||||
|
||||
/** Gets an immediate successor of this node. */
|
||||
Node nodeGetASuccessor(Node node, SuccessorType t) {
|
||||
result = node.getASuccessor() and
|
||||
(
|
||||
not result instanceof ControlFlow::ConditionGuardNode and t instanceof DirectSuccessor
|
||||
or
|
||||
t.(BooleanSuccessor).getValue() = result.(ControlFlow::ConditionGuardNode).getOutcome()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` represents an entry node to be used when calculating
|
||||
* dominance.
|
||||
*/
|
||||
predicate nodeIsDominanceEntry(Node node) { node instanceof EntryNode }
|
||||
|
||||
/**
|
||||
* Holds if `node` represents an exit node to be used when calculating
|
||||
* post dominance.
|
||||
*/
|
||||
predicate nodeIsPostDominanceExit(Node node) { node instanceof ExitNode }
|
||||
}
|
||||
|
||||
private module BbImpl = BB::Make<Location, Input>;
|
||||
|
||||
class BasicBlock = BbImpl::BasicBlock;
|
||||
|
||||
class EntryBasicBlock = BbImpl::EntryBasicBlock;
|
||||
|
||||
cached
|
||||
private predicate reachableBB(BasicBlock bb) {
|
||||
bb instanceof EntryBasicBlock
|
||||
or
|
||||
exists(BasicBlock predBB | predBB.getASuccessor(_) = bb | reachableBB(predBB))
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic block that is reachable from an entry basic block.
|
||||
*
|
||||
* Since the shared CFG library only creates nodes for reachable code,
|
||||
* all basic blocks are reachable by construction.
|
||||
*/
|
||||
class ReachableBasicBlock extends BasicBlock {
|
||||
ReachableBasicBlock() { any() }
|
||||
ReachableBasicBlock() { reachableBB(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A reachable basic block with more than one predecessor.
|
||||
*/
|
||||
class ReachableJoinBlock extends ReachableBasicBlock {
|
||||
ReachableJoinBlock() { this.getFirstNode().(ControlFlow::Node).isJoin() }
|
||||
ReachableJoinBlock() { this.getFirstNode().isJoin() }
|
||||
}
|
||||
|
||||
@@ -5,17 +5,13 @@ overlay[local]
|
||||
module;
|
||||
|
||||
import go
|
||||
private import ControlFlowGraphShared
|
||||
private import ControlFlowGraphImpl
|
||||
|
||||
/** Provides helper predicates for mapping between CFG nodes and the AST. */
|
||||
/** Provides helper predicates for mapping btween CFG nodes and the AST. */
|
||||
module ControlFlow {
|
||||
/** A file or function with which a CFG is associated. */
|
||||
class Root extends AstNode {
|
||||
Root() {
|
||||
exists(this.(FuncDef).getBody())
|
||||
or
|
||||
exists(this.(File).getADecl())
|
||||
}
|
||||
Root() { exists(this.(File).getADecl()) or exists(this.(FuncDef).getBody()) }
|
||||
|
||||
/** Holds if `nd` belongs to this file or function. */
|
||||
predicate isRootOf(AstNode nd) {
|
||||
@@ -33,16 +29,22 @@ module ControlFlow {
|
||||
}
|
||||
|
||||
/**
|
||||
* A node in the intra-procedural control-flow graph of a Go function.
|
||||
* A node in the intra-procedural control-flow graph of a Go function or file.
|
||||
*
|
||||
* Nodes correspond to expressions and statements that compute a value or perform
|
||||
* an operation (as opposed to providing syntactic structure or type information).
|
||||
*
|
||||
* There are also synthetic entry and exit nodes for each Go function
|
||||
* There are also synthetic entry and exit nodes for each Go function and file
|
||||
* that mark the beginning and the end, respectively, of the execution of the
|
||||
* function.
|
||||
* function and the loading of the file.
|
||||
*/
|
||||
class Node extends GoCfg::ControlFlowNode {
|
||||
class Node extends TControlFlowNode {
|
||||
/** Gets a node that directly follows this one in the control-flow graph. */
|
||||
Node getASuccessor() { result = CFG::succ(this) }
|
||||
|
||||
/** Gets a node that directly precedes this one in the control-flow graph. */
|
||||
Node getAPredecessor() { this = result.getASuccessor() }
|
||||
|
||||
/** Holds if this is a node with more than one successor. */
|
||||
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
||||
|
||||
@@ -50,23 +52,22 @@ module ControlFlow {
|
||||
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
|
||||
|
||||
/** Holds if this is the first control-flow node in `subtree`. */
|
||||
predicate isFirstNodeOf(AstNode subtree) {
|
||||
this.isBefore(subtree)
|
||||
or
|
||||
this.injects(subtree)
|
||||
}
|
||||
predicate isFirstNodeOf(AstNode subtree) { CFG::firstNode(subtree, this) }
|
||||
|
||||
/** Holds if this node is the (unique) entry node of a function. */
|
||||
predicate isEntryNode() { this instanceof GoCfg::ControlFlow::EntryNode }
|
||||
/** Holds if this node is the (unique) entry node of a function or file. */
|
||||
predicate isEntryNode() { this instanceof MkEntryNode }
|
||||
|
||||
/** Holds if this node is the (unique) exit node of a function. */
|
||||
predicate isExitNode() { this instanceof GoCfg::ControlFlow::ExitNode }
|
||||
/** Holds if this node is the (unique) exit node of a function or file. */
|
||||
predicate isExitNode() { this instanceof MkExitNode }
|
||||
|
||||
/** Gets the basic block to which this node belongs. */
|
||||
BasicBlock getBasicBlock() { result.getANode() = this }
|
||||
|
||||
/** Holds if this node dominates `dominee` in the control-flow graph. */
|
||||
overlay[caller?]
|
||||
pragma[inline]
|
||||
predicate dominatesNode(ControlFlow::Node dominee) {
|
||||
exists(GoCfg::Cfg::BasicBlock thisbb, GoCfg::Cfg::BasicBlock dbb, int i, int j |
|
||||
exists(ReachableBasicBlock thisbb, ReachableBasicBlock dbb, int i, int j |
|
||||
this = thisbb.getNode(i) and dominee = dbb.getNode(j)
|
||||
|
|
||||
thisbb.strictlyDominates(dbb)
|
||||
@@ -75,12 +76,20 @@ module ControlFlow {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the innermost function to which this node belongs. */
|
||||
Root getRoot() { result = this.getEnclosingCallable() }
|
||||
/** Gets the innermost function or file to which this node belongs. */
|
||||
Root getRoot() { none() }
|
||||
|
||||
/** Gets the file to which this node belongs. */
|
||||
File getFile() { result = this.getLocation().getFile() }
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this control flow node.
|
||||
*/
|
||||
string toString() { result = "control-flow node" }
|
||||
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getLocation()` instead.
|
||||
*
|
||||
@@ -104,22 +113,6 @@ module ControlFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/** A synthetic entry node for a function. */
|
||||
class EntryNode extends Node instanceof GoCfg::ControlFlow::EntryNode { }
|
||||
|
||||
/** A synthetic exit node for a function. */
|
||||
class ExitNode extends Node instanceof GoCfg::ControlFlow::ExitNode { }
|
||||
|
||||
private predicate isBranchConditionRoot(Expr expr) {
|
||||
expr = any(LogicalBinaryExpr lbe).getLeftOperand()
|
||||
or
|
||||
expr = any(ForStmt fs).getCond()
|
||||
or
|
||||
expr = any(IfStmt is).getCond()
|
||||
or
|
||||
expr = any(ExpressionSwitchStmt ess | not exists(ess.getExpr())).getACase().getAnExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
* A control-flow node that initializes or updates the value of a constant, a variable,
|
||||
* a field, or an (array, slice, or map) element.
|
||||
@@ -179,7 +172,7 @@ module ControlFlow {
|
||||
exists(IR::FieldTarget trg | trg = super.getLhs() |
|
||||
(
|
||||
trg.getBase() = base or
|
||||
trg.getBase() = IR::implicitDerefInstruction(base.(IR::EvalInstruction).getExpr())
|
||||
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
|
||||
) and
|
||||
trg.getField() = f and
|
||||
super.getRhs() = rhs
|
||||
@@ -227,7 +220,7 @@ module ControlFlow {
|
||||
exists(IR::ElementTarget trg | trg = super.getLhs() |
|
||||
(
|
||||
trg.getBase() = base or
|
||||
trg.getBase() = IR::implicitDerefInstruction(base.(IR::EvalInstruction).getExpr())
|
||||
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
|
||||
) and
|
||||
trg.getIndex() = index and
|
||||
super.getRhs() = rhs
|
||||
@@ -257,19 +250,11 @@ module ControlFlow {
|
||||
* A control-flow node recording the fact that a certain expression has a known
|
||||
* Boolean value at this point in the program.
|
||||
*/
|
||||
class ConditionGuardNode extends IR::Instruction {
|
||||
class ConditionGuardNode extends IR::Instruction, MkConditionGuardNode {
|
||||
Expr cond;
|
||||
boolean outcome;
|
||||
|
||||
ConditionGuardNode() {
|
||||
isBranchConditionRoot(cond) and
|
||||
this.isAfterTrue(cond) and
|
||||
outcome = true
|
||||
or
|
||||
isBranchConditionRoot(cond) and
|
||||
this.isAfterFalse(cond) and
|
||||
outcome = false
|
||||
}
|
||||
ConditionGuardNode() { this = MkConditionGuardNode(cond, outcome) }
|
||||
|
||||
private predicate ensuresAux(Expr expr, boolean b) {
|
||||
expr = cond and b = outcome
|
||||
@@ -335,17 +320,21 @@ module ControlFlow {
|
||||
boolean getOutcome() { result = outcome }
|
||||
|
||||
override Root getRoot() { result.isRootOf(cond) }
|
||||
|
||||
override string toString() { result = cond + " is " + outcome }
|
||||
|
||||
override Location getLocation() { result = cond.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entry node of function `root`.
|
||||
* Gets the entry node of function or file `root`.
|
||||
*/
|
||||
EntryNode entryNode(Root root) { result.getEnclosingCallable() = root }
|
||||
Node entryNode(Root root) { result = MkEntryNode(root) }
|
||||
|
||||
/**
|
||||
* Gets the exit node of function `root`.
|
||||
* Gets the exit node of function or file `root`.
|
||||
*/
|
||||
ExitNode exitNode(Root root) { result.getEnclosingCallable() = root }
|
||||
Node exitNode(Root root) { result = MkExitNode(root) }
|
||||
|
||||
/**
|
||||
* Holds if the function `f` may return without panicking, exiting the process, or looping forever.
|
||||
@@ -353,12 +342,7 @@ module ControlFlow {
|
||||
* This is defined conservatively, and so may also hold of a function that in fact
|
||||
* cannot return normally, but never fails to hold of a function that can return normally.
|
||||
*/
|
||||
predicate mayReturnNormally(FuncDecl f) {
|
||||
exists(GoCfg::ControlFlow::NormalExitNode exit |
|
||||
exit.getEnclosingCallable() = f and
|
||||
exists(exit.getAPredecessor())
|
||||
)
|
||||
}
|
||||
predicate mayReturnNormally(FuncDecl f) { CFG::mayReturnNormally(f.getBody()) }
|
||||
|
||||
/**
|
||||
* Holds if `pred` is the node for the case `testExpr` in an expression
|
||||
@@ -368,18 +352,10 @@ module ControlFlow {
|
||||
predicate isSwitchCaseTestPassingEdge(
|
||||
ControlFlow::Node pred, ControlFlow::Node succ, Expr switchExpr, Expr testExpr
|
||||
) {
|
||||
exists(ExpressionSwitchStmt ess, CaseClause cc, int i |
|
||||
ess.getExpr() = switchExpr and
|
||||
cc = ess.getACase() and
|
||||
testExpr = cc.getExpr(i) and
|
||||
pred.isAfter(testExpr) and
|
||||
succ.isFirstNodeOf(cc.getStmt(0))
|
||||
)
|
||||
CFG::isSwitchCaseTestPassingEdge(pred, succ, switchExpr, testExpr)
|
||||
}
|
||||
}
|
||||
|
||||
class ControlFlowNode = ControlFlow::Node;
|
||||
|
||||
class CfgScope = GoCfg::CfgScope;
|
||||
|
||||
class Write = ControlFlow::WriteNode;
|
||||
|
||||
2133
go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll
Normal file
2133
go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -200,7 +200,7 @@ private ControlFlow::Node mostRecentSideEffect(ControlFlow::Node entry, ControlF
|
||||
|
||||
cached
|
||||
private ControlFlow::Node mostRecentSideEffectUnique(ControlFlow::Node node) {
|
||||
result = unique( | | mostRecentSideEffect(getControlFlowEntry(node), node))
|
||||
result = unique( | | mostRecentSideEffect(_, node))
|
||||
}
|
||||
|
||||
/** Used to represent the "global value number" of an expression. */
|
||||
|
||||
@@ -89,7 +89,7 @@ private module Internal {
|
||||
/** Holds if the `i`th node of `bb` in function `f` is an entry node. */
|
||||
private predicate entryNode(FuncDef f, ReachableBasicBlock bb, int i) {
|
||||
f = bb.getScope() and
|
||||
bb.getNode(i).(ControlFlow::Node).isEntryNode()
|
||||
bb.getNode(i).isEntryNode()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,7 +59,7 @@ module Glog {
|
||||
/** Holds if this function takes a format string. */
|
||||
predicate formatter() { format = "f" }
|
||||
|
||||
override predicate mustNotReturnNormally() { level = "Fatal" or level = "Exit" }
|
||||
override predicate mayReturnNormally() { level != "Fatal" and level != "Exit" }
|
||||
}
|
||||
|
||||
private class StringFormatter extends StringOps::Formatting::Range instanceof GlogFunction {
|
||||
|
||||
@@ -29,8 +29,8 @@ module Logrus {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mustNotReturnNormally() {
|
||||
exists(string level, string suffix | level = ["Fatal", "Panic"] |
|
||||
override predicate mayReturnNormally() {
|
||||
not exists(string level, string suffix | level = ["Fatal", "Panic"] |
|
||||
this.getName() = level + suffix
|
||||
)
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ module Revel {
|
||||
|
||||
private IR::EvalInstruction skipImplicitFieldReads(IR::Instruction insn) {
|
||||
result = insn or
|
||||
result = skipImplicitFieldReads(insn.(IR::ImplicitFieldReadInstruction).getBaseInstruction())
|
||||
result = skipImplicitFieldReads(insn.(IR::ImplicitFieldReadInstruction).getBase())
|
||||
}
|
||||
|
||||
/** A call to `Controller.Render`. */
|
||||
|
||||
@@ -54,7 +54,7 @@ module Zap {
|
||||
this.hasQualifiedName(packagePath(), "SugaredLogger", "Fatal" + getSuffix())
|
||||
}
|
||||
|
||||
override predicate mustNotReturnNormally() { any() }
|
||||
override predicate mayReturnNormally() { none() }
|
||||
}
|
||||
|
||||
/** A Zap logging function which always panics. */
|
||||
|
||||
@@ -44,7 +44,7 @@ module Log {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mustNotReturnNormally() { any() }
|
||||
override predicate mayReturnNormally() { none() }
|
||||
}
|
||||
|
||||
/** A log function which must panic. */
|
||||
|
||||
@@ -12,7 +12,7 @@ module Os {
|
||||
private class Exit extends Function {
|
||||
Exit() { this.hasQualifiedName("os", "Exit") }
|
||||
|
||||
override predicate mustNotReturnNormally() { any() }
|
||||
override predicate mayReturnNormally() { none() }
|
||||
}
|
||||
|
||||
// These models are not implemented using Models-as-Data because they represent reverse flow.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* @name Web Cache Deception
|
||||
* @description A caching system has been detected on the application and is vulnerable to web cache deception. By manipulating the URL it is possible to force the application to cache pages that are only accessible by an authenticated user. Once cached, these pages can be accessed by an unauthenticated user.
|
||||
* @kind problem
|
||||
|
||||
@@ -54,31 +54,31 @@ func main() {}
|
||||
// bad is an example of a bad implementation
|
||||
func (ld *Ldap) bad(req *http.Request) {
|
||||
// ...
|
||||
untrusted := req.UserAgent()
|
||||
untrusted := req.UserAgent() // $ Source
|
||||
goldap.NewSearchRequest(
|
||||
untrusted, // BAD: untrusted dn
|
||||
untrusted, // $ Alert // BAD: untrusted dn
|
||||
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
|
||||
nil,
|
||||
)
|
||||
goldapv3.NewSearchRequest(
|
||||
untrusted, // BAD: untrusted dn
|
||||
untrusted, // $ Alert // BAD: untrusted dn
|
||||
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
|
||||
nil,
|
||||
)
|
||||
gopkgldapv2.NewSearchRequest(
|
||||
untrusted, // BAD: untrusted dn
|
||||
untrusted, // $ Alert // BAD: untrusted dn
|
||||
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
|
||||
nil,
|
||||
)
|
||||
client := &ldapclient.LDAPClient{}
|
||||
client.Authenticate(untrusted, "123456") // BAD: untrusted filter
|
||||
client.GetGroupsOfUser(untrusted) // BAD: untrusted filter
|
||||
client.Authenticate(untrusted, "123456") // $ Alert // BAD: untrusted filter
|
||||
client.GetGroupsOfUser(untrusted) // $ Alert // BAD: untrusted filter
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
query: experimental/CWE-090/LDAPInjection.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
query: experimental/CWE-203/Timing.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -12,9 +12,9 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
secret := "MySuperSecretPasscode"
|
||||
secretHeader := "X-Secret"
|
||||
|
||||
headerSecret := req.Header.Get(secretHeader)
|
||||
headerSecret := req.Header.Get(secretHeader) // $ Source
|
||||
secretStr := string(secret)
|
||||
if len(headerSecret) != 0 && headerSecret != secretStr {
|
||||
if len(headerSecret) != 0 && headerSecret != secretStr { // $ Alert
|
||||
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
|
||||
}
|
||||
return nil, nil
|
||||
@@ -25,9 +25,9 @@ func bad2(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
secret := "MySuperSecretPasscode"
|
||||
secretHeader := "X-Secret"
|
||||
|
||||
headerSecret := req.Header.Get(secretHeader)
|
||||
headerSecret := req.Header.Get(secretHeader) // $ Source
|
||||
secretStr := string(secret)
|
||||
if len(headerSecret) != 0 && strings.Compare(headerSecret, secretStr) != 0 {
|
||||
if len(headerSecret) != 0 && strings.Compare(headerSecret, secretStr) != 0 { // $ Alert
|
||||
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
|
||||
}
|
||||
return nil, nil
|
||||
@@ -38,8 +38,8 @@ func bad4(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
secret := "MySuperSecretPasscode"
|
||||
secretHeader := "X-Secret"
|
||||
|
||||
headerSecret := req.Header.Get(secretHeader)
|
||||
if len(secret) != 0 && headerSecret != "SecretStringLiteral" {
|
||||
headerSecret := req.Header.Get(secretHeader) // $ Source
|
||||
if len(secret) != 0 && headerSecret != "SecretStringLiteral" { // $ Alert
|
||||
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/CWE-285/PamAuthBypass.ql
|
||||
query: experimental/CWE-285/PamAuthBypass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
func bad() error {
|
||||
t, _ := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) {
|
||||
return "", nil
|
||||
})
|
||||
}) // $ Alert
|
||||
return t.Authenticate(0)
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
ldapServer := "ldap.example.com"
|
||||
ldapPort := 389
|
||||
bindDN := "cn=admin,dc=example,dc=com"
|
||||
bindPassword := req.URL.Query()["password"][0]
|
||||
bindPassword := req.URL.Query()["password"][0] // $ Source
|
||||
|
||||
// Connect to the LDAP server
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
@@ -25,7 +25,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
defer l.Close()
|
||||
|
||||
// BAD: user input is not sanetized
|
||||
err = l.Bind(bindDN, bindPassword)
|
||||
err = l.Bind(bindDN, bindPassword) // $ Alert
|
||||
if err != nil {
|
||||
return fmt.Errorf("LDAP bind failed: %v", err), err
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func bad2(req *http.Request) {
|
||||
ldapPort := 389
|
||||
bindDN := "cn=admin,dc=example,dc=com"
|
||||
// BAD : empty password
|
||||
bindPassword := ""
|
||||
bindPassword := "" // $ Source
|
||||
|
||||
// Connect to the LDAP server
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
@@ -94,7 +94,7 @@ func bad2(req *http.Request) {
|
||||
defer l.Close()
|
||||
|
||||
// BAD : bindPassword is empty
|
||||
err = l.Bind(bindDN, bindPassword)
|
||||
err = l.Bind(bindDN, bindPassword) // $ Alert
|
||||
if err != nil {
|
||||
log.Fatalf("LDAP bind failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
query: experimental/CWE-287/ImproperLdapAuth.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#select
|
||||
| go-jose.v3.go:24:32:24:37 | JwtKey | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:24:32:24:37 | JwtKey | This $@. | go-jose.v3.go:13:21:13:33 | "AllYourBase" | Constant Key is used as JWT Secret key |
|
||||
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | This $@. | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | Constant Key is used as JWT Secret key |
|
||||
edges
|
||||
| go-jose.v3.go:13:14:13:34 | type conversion | go-jose.v3.go:24:32:24:37 | JwtKey | provenance | |
|
||||
| go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:13:14:13:34 | type conversion | provenance | |
|
||||
@@ -11,6 +14,3 @@ nodes
|
||||
| golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | semmle.label | "AllYourBase" |
|
||||
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | semmle.label | JwtKey1 |
|
||||
subpaths
|
||||
#select
|
||||
| go-jose.v3.go:24:32:24:37 | JwtKey | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:24:32:24:37 | JwtKey | This $@. | go-jose.v3.go:13:21:13:33 | "AllYourBase" | Constant Key is used as JWT Secret key |
|
||||
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | This $@. | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | Constant Key is used as JWT Secret key |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/CWE-321-V2/HardCodedKeys.ql
|
||||
query: experimental/CWE-321-V2/HardCodedKeys.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// NOT OK
|
||||
var JwtKey = []byte("AllYourBase")
|
||||
var JwtKey = []byte("AllYourBase") // $ Source
|
||||
|
||||
func main2(r *http.Request) {
|
||||
signedToken := r.URL.Query().Get("signedToken")
|
||||
@@ -21,7 +21,7 @@ func verifyJWT(signedToken string) {
|
||||
fmt.Println("verifying JWT")
|
||||
DecodedToken, _ := jwt.ParseSigned(signedToken)
|
||||
out := CustomerInfo{}
|
||||
if err := DecodedToken.Claims(JwtKey, &out); err != nil {
|
||||
if err := DecodedToken.Claims(JwtKey, &out); err != nil { // $ Alert
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%v\n", out)
|
||||
|
||||
@@ -16,7 +16,7 @@ type CustomerInfo struct {
|
||||
}
|
||||
|
||||
// BAD constant key
|
||||
var JwtKey1 = []byte("AllYourBase")
|
||||
var JwtKey1 = []byte("AllYourBase") // $ Source
|
||||
|
||||
func main1(r *http.Request) {
|
||||
signedToken := r.URL.Query().Get("signedToken")
|
||||
@@ -24,7 +24,7 @@ func main1(r *http.Request) {
|
||||
}
|
||||
|
||||
func LoadJwtKey(token *jwt.Token) (interface{}, error) {
|
||||
return JwtKey1, nil
|
||||
return JwtKey1, nil // $ Alert
|
||||
}
|
||||
|
||||
func verifyJWT_golangjwt(signedToken string) {
|
||||
|
||||
@@ -8,23 +8,23 @@
|
||||
edges
|
||||
| DivideByZero.go:10:12:10:16 | selection of URL | DivideByZero.go:10:12:10:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:10:12:10:24 | call to Query | DivideByZero.go:11:27:11:32 | param1 | provenance | |
|
||||
| DivideByZero.go:11:2:11:33 | extract:0 ... := ... | DivideByZero.go:12:16:12:20 | value | provenance | |
|
||||
| DivideByZero.go:11:27:11:32 | param1 | DivideByZero.go:11:2:11:33 | extract:0 ... := ... | provenance | Config |
|
||||
| DivideByZero.go:11:2:11:33 | ... := ...[0] | DivideByZero.go:12:16:12:20 | value | provenance | |
|
||||
| DivideByZero.go:11:27:11:32 | param1 | DivideByZero.go:11:2:11:33 | ... := ...[0] | provenance | Config |
|
||||
| DivideByZero.go:17:12:17:16 | selection of URL | DivideByZero.go:17:12:17:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:17:12:17:24 | call to Query | DivideByZero.go:18:11:18:24 | type conversion | provenance | |
|
||||
| DivideByZero.go:18:11:18:24 | type conversion | DivideByZero.go:19:16:19:20 | value | provenance | |
|
||||
| DivideByZero.go:24:12:24:16 | selection of URL | DivideByZero.go:24:12:24:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:24:12:24:24 | call to Query | DivideByZero.go:25:31:25:36 | param1 | provenance | |
|
||||
| DivideByZero.go:25:2:25:45 | extract:0 ... := ... | DivideByZero.go:26:16:26:20 | value | provenance | |
|
||||
| DivideByZero.go:25:31:25:36 | param1 | DivideByZero.go:25:2:25:45 | extract:0 ... := ... | provenance | Config |
|
||||
| DivideByZero.go:25:2:25:45 | ... := ...[0] | DivideByZero.go:26:16:26:20 | value | provenance | |
|
||||
| DivideByZero.go:25:31:25:36 | param1 | DivideByZero.go:25:2:25:45 | ... := ...[0] | provenance | Config |
|
||||
| DivideByZero.go:31:12:31:16 | selection of URL | DivideByZero.go:31:12:31:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:31:12:31:24 | call to Query | DivideByZero.go:32:33:32:38 | param1 | provenance | |
|
||||
| DivideByZero.go:32:2:32:43 | extract:0 ... := ... | DivideByZero.go:33:16:33:20 | value | provenance | |
|
||||
| DivideByZero.go:32:33:32:38 | param1 | DivideByZero.go:32:2:32:43 | extract:0 ... := ... | provenance | Config |
|
||||
| DivideByZero.go:32:2:32:43 | ... := ...[0] | DivideByZero.go:33:16:33:20 | value | provenance | |
|
||||
| DivideByZero.go:32:33:32:38 | param1 | DivideByZero.go:32:2:32:43 | ... := ...[0] | provenance | Config |
|
||||
| DivideByZero.go:38:12:38:16 | selection of URL | DivideByZero.go:38:12:38:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:38:12:38:24 | call to Query | DivideByZero.go:39:32:39:37 | param1 | provenance | |
|
||||
| DivideByZero.go:39:2:39:46 | extract:0 ... := ... | DivideByZero.go:40:16:40:20 | value | provenance | |
|
||||
| DivideByZero.go:39:32:39:37 | param1 | DivideByZero.go:39:2:39:46 | extract:0 ... := ... | provenance | Config |
|
||||
| DivideByZero.go:39:2:39:46 | ... := ...[0] | DivideByZero.go:40:16:40:20 | value | provenance | |
|
||||
| DivideByZero.go:39:32:39:37 | param1 | DivideByZero.go:39:2:39:46 | ... := ...[0] | provenance | Config |
|
||||
| DivideByZero.go:54:12:54:16 | selection of URL | DivideByZero.go:54:12:54:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||
| DivideByZero.go:54:12:54:24 | call to Query | DivideByZero.go:55:11:55:24 | type conversion | provenance | |
|
||||
| DivideByZero.go:55:11:55:24 | type conversion | DivideByZero.go:57:17:57:21 | value | provenance | |
|
||||
@@ -34,7 +34,7 @@ models
|
||||
nodes
|
||||
| DivideByZero.go:10:12:10:16 | selection of URL | semmle.label | selection of URL |
|
||||
| DivideByZero.go:10:12:10:24 | call to Query | semmle.label | call to Query |
|
||||
| DivideByZero.go:11:2:11:33 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
||||
| DivideByZero.go:11:2:11:33 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| DivideByZero.go:11:27:11:32 | param1 | semmle.label | param1 |
|
||||
| DivideByZero.go:12:16:12:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:17:12:17:16 | selection of URL | semmle.label | selection of URL |
|
||||
@@ -43,17 +43,17 @@ nodes
|
||||
| DivideByZero.go:19:16:19:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:24:12:24:16 | selection of URL | semmle.label | selection of URL |
|
||||
| DivideByZero.go:24:12:24:24 | call to Query | semmle.label | call to Query |
|
||||
| DivideByZero.go:25:2:25:45 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
||||
| DivideByZero.go:25:2:25:45 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| DivideByZero.go:25:31:25:36 | param1 | semmle.label | param1 |
|
||||
| DivideByZero.go:26:16:26:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:31:12:31:16 | selection of URL | semmle.label | selection of URL |
|
||||
| DivideByZero.go:31:12:31:24 | call to Query | semmle.label | call to Query |
|
||||
| DivideByZero.go:32:2:32:43 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
||||
| DivideByZero.go:32:2:32:43 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| DivideByZero.go:32:33:32:38 | param1 | semmle.label | param1 |
|
||||
| DivideByZero.go:33:16:33:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:38:12:38:16 | selection of URL | semmle.label | selection of URL |
|
||||
| DivideByZero.go:38:12:38:24 | call to Query | semmle.label | call to Query |
|
||||
| DivideByZero.go:39:2:39:46 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
||||
| DivideByZero.go:39:2:39:46 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| DivideByZero.go:39:32:39:37 | param1 | semmle.label | param1 |
|
||||
| DivideByZero.go:40:16:40:20 | value | semmle.label | value |
|
||||
| DivideByZero.go:54:12:54:16 | selection of URL | semmle.label | selection of URL |
|
||||
|
||||
@@ -7,37 +7,37 @@ import (
|
||||
)
|
||||
|
||||
func myHandler1(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
value, _ := strconv.Atoi(param1)
|
||||
out := 1337 / value
|
||||
out := 1337 / value // $ Alert
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
func myHandler2(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
value := int(param1[0])
|
||||
out := 1337 / value
|
||||
out := 1337 / value // $ Alert
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
func myHandler3(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
value, _ := strconv.ParseInt(param1, 10, 64)
|
||||
out := 1337 / value
|
||||
out := 1337 / value // $ Alert
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
func myHandler4(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
value, _ := strconv.ParseFloat(param1, 32)
|
||||
out := 1337 / value
|
||||
out := 1337 / value // $ Alert
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
func myHandler5(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
value, _ := strconv.ParseUint(param1, 10, 64)
|
||||
out := 1337 / value
|
||||
out := 1337 / value // $ Alert
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
@@ -51,10 +51,10 @@ func myHandler6(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func myHandler7(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
value := int(param1[0])
|
||||
if value >= 0 {
|
||||
out := 1337 / value
|
||||
out := 1337 / value // $ Alert
|
||||
fmt.Println(out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
query: experimental/CWE-369/DivideByZero.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#select
|
||||
| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop |
|
||||
| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop |
|
||||
| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop |
|
||||
edges
|
||||
| DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First |
|
||||
| test.go:10:1:12:1 | function declaration | test.go:11:2:11:13 | call to Take |
|
||||
@@ -7,7 +11,3 @@ edges
|
||||
| test.go:21:3:21:14 | call to runQuery | test.go:10:1:12:1 | function declaration |
|
||||
| test.go:24:2:26:2 | for statement | test.go:25:3:25:17 | call to runRunQuery |
|
||||
| test.go:25:3:25:17 | call to runRunQuery | test.go:14:1:16:1 | function declaration |
|
||||
#select
|
||||
| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop |
|
||||
| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop |
|
||||
| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop |
|
||||
|
||||
@@ -6,8 +6,8 @@ func getUsers(db *gorm.DB, names []string) []User {
|
||||
res := make([]User, 0, len(names))
|
||||
for _, name := range names {
|
||||
var user User
|
||||
db.Where("name = ?", name).First(&user)
|
||||
db.Where("name = ?", name).First(&user) // $ Alert
|
||||
res = append(res, user)
|
||||
}
|
||||
} // $ Source
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/CWE-400/DatabaseCallInLoop.ql
|
||||
query: experimental/CWE-400/DatabaseCallInLoop.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -8,7 +8,7 @@ type User struct {
|
||||
}
|
||||
|
||||
func runQuery(db *gorm.DB) {
|
||||
db.Take(nil)
|
||||
db.Take(nil) // $ Alert
|
||||
}
|
||||
|
||||
func runRunQuery(db *gorm.DB) {
|
||||
@@ -19,9 +19,9 @@ func main() {
|
||||
var db *gorm.DB
|
||||
for i := 0; i < 10; i++ {
|
||||
runQuery(db)
|
||||
}
|
||||
} // $ Source
|
||||
|
||||
for i := 10; i > 0; i-- {
|
||||
runRunQuery(db)
|
||||
}
|
||||
} // $ Source
|
||||
}
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
query: experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -56,41 +56,41 @@ func main() {
|
||||
func DecompressHandler(w http.ResponseWriter, request *http.Request) {
|
||||
GZipOpenReaderSafe(request.PostFormValue("test"))
|
||||
ZipOpenReaderSafe(request.PostFormValue("test"))
|
||||
ZipOpenReader(request.FormValue("filepath"))
|
||||
ZipNewReader(request.Body)
|
||||
ZipNewReaderKlauspost(request.Body)
|
||||
Bzip2Dsnet(request.Body)
|
||||
ZipOpenReader(request.FormValue("filepath")) // $ Source
|
||||
ZipNewReader(request.Body) // $ Source
|
||||
ZipNewReaderKlauspost(request.Body) // $ Source
|
||||
Bzip2Dsnet(request.Body) // $ Source
|
||||
Bzip2DsnetSafe(request.Body)
|
||||
Bzip2(request.Body)
|
||||
Bzip2(request.Body) // $ Source
|
||||
Bzip2Safe(request.Body)
|
||||
Flate(request.Body)
|
||||
Flate(request.Body) // $ Source
|
||||
FlateSafe(request.Body)
|
||||
FlateKlauspost(request.Body)
|
||||
FlateKlauspost(request.Body) // $ Source
|
||||
FlateKlauspostSafe(request.Body)
|
||||
FlateDsnet(request.Body)
|
||||
FlateDsnet(request.Body) // $ Source
|
||||
FlateDsnetSafe(request.Body)
|
||||
ZlibKlauspost(request.Body)
|
||||
ZlibKlauspost(request.Body) // $ Source
|
||||
ZlibKlauspostSafe(request.Body)
|
||||
Zlib(request.Body)
|
||||
Zlib(request.Body) // $ Source
|
||||
ZlibSafe(request.Body)
|
||||
Snappy(request.Body)
|
||||
Snappy(request.Body) // $ Source
|
||||
SnappySafe(request.Body)
|
||||
SnappyKlauspost(request.Body)
|
||||
SnappyKlauspost(request.Body) // $ Source
|
||||
SnappyKlauspostSafe(request.Body)
|
||||
S2(request.Body)
|
||||
S2(request.Body) // $ Source
|
||||
S2Safe(request.Body)
|
||||
Gzip(request.Body)
|
||||
Gzip(request.Body) // $ Source
|
||||
GzipSafe(request.Body)
|
||||
GZipIoReader(request.Body, "dest")
|
||||
GzipKlauspost(request.Body)
|
||||
GZipIoReader(request.Body, "dest") // $ Source
|
||||
GzipKlauspost(request.Body) // $ Source
|
||||
GzipKlauspostSafe(request.Body)
|
||||
PzipKlauspost(request.Body)
|
||||
PzipKlauspost(request.Body) // $ Source
|
||||
PzipKlauspostSafe(request.Body)
|
||||
Zstd_Klauspost(request.Body)
|
||||
Zstd_Klauspost(request.Body) // $ Source
|
||||
Zstd_KlauspostSafe(request.Body)
|
||||
Zstd_DataDog(request.Body)
|
||||
Zstd_DataDog(request.Body) // $ Source
|
||||
Zstd_DataDogSafe(request.Body)
|
||||
Xz(request.Body)
|
||||
Xz(request.Body) // $ Source
|
||||
XzSafe(request.Body)
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func ZipOpenReader(filename string) {
|
||||
for _, f := range zipReader.File {
|
||||
rc, _ := f.Open()
|
||||
for {
|
||||
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc"
|
||||
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert
|
||||
if result == 0 {
|
||||
_ = rc.Close()
|
||||
break
|
||||
@@ -144,7 +144,7 @@ func ZipOpenReader(filename string) {
|
||||
for _, f := range zipKlauspostReader.File {
|
||||
rc, _ := f.Open()
|
||||
for {
|
||||
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc"
|
||||
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert
|
||||
if result == 0 {
|
||||
_ = rc.Close()
|
||||
break
|
||||
@@ -161,7 +161,7 @@ func ZipNewReader(file io.Reader) {
|
||||
for _, file := range zipReader.File {
|
||||
fileWriter := bytes.NewBuffer([]byte{})
|
||||
fileReaderCloser, _ := file.Open()
|
||||
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser"
|
||||
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert
|
||||
fmt.Print(result)
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,7 @@ func ZipNewReaderKlauspost(file io.Reader) {
|
||||
fileWriter := bytes.NewBuffer([]byte{})
|
||||
// file.OpenRaw()
|
||||
fileReaderCloser, _ := file.Open()
|
||||
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser"
|
||||
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert
|
||||
fmt.Print(result)
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ func Bzip2Dsnet(file io.Reader) {
|
||||
|
||||
bzip2Reader, _ := bzip2Dsnet.NewReader(file, &bzip2Dsnet.ReaderConfig{})
|
||||
var out []byte = make([]byte, 70)
|
||||
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader"
|
||||
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert
|
||||
tarRead = tar.NewReader(bzip2Reader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -210,7 +210,7 @@ func Bzip2(file io.Reader) {
|
||||
|
||||
bzip2Reader := bzip2.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader"
|
||||
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert
|
||||
tarRead = tar.NewReader(bzip2Reader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -235,7 +235,7 @@ func Flate(file io.Reader) {
|
||||
|
||||
flateReader := flate.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader"
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
|
||||
tarRead = tar.NewReader(flateReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -260,7 +260,7 @@ func FlateKlauspost(file io.Reader) {
|
||||
|
||||
flateReader := flateKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader"
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
|
||||
tarRead = tar.NewReader(flateReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -285,7 +285,7 @@ func FlateDsnet(file io.Reader) {
|
||||
|
||||
flateReader, _ := flateDsnet.NewReader(file, &flateDsnet.ReaderConfig{})
|
||||
var out []byte = make([]byte, 70)
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader"
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
|
||||
tarRead = tar.NewReader(flateReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -310,7 +310,7 @@ func ZlibKlauspost(file io.Reader) {
|
||||
|
||||
zlibReader, _ := zlibKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
zlibReader.Read(out) // $ hasValueFlow="zlibReader"
|
||||
zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert
|
||||
tarRead = tar.NewReader(zlibReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -335,7 +335,7 @@ func Zlib(file io.Reader) {
|
||||
|
||||
zlibReader, _ := zlib.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
zlibReader.Read(out) // $ hasValueFlow="zlibReader"
|
||||
zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert
|
||||
tarRead = tar.NewReader(zlibReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -360,8 +360,8 @@ func Snappy(file io.Reader) {
|
||||
|
||||
snappyReader := snappy.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
snappyReader.Read(out) // $ hasValueFlow="snappyReader"
|
||||
snappyReader.ReadByte() // $ hasValueFlow="snappyReader"
|
||||
snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert
|
||||
snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert
|
||||
tarRead = tar.NewReader(snappyReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -386,10 +386,10 @@ func SnappyKlauspost(file io.Reader) {
|
||||
|
||||
snappyReader := snappyKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
snappyReader.Read(out) // $ hasValueFlow="snappyReader"
|
||||
snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert
|
||||
var buf bytes.Buffer
|
||||
snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader"
|
||||
snappyReader.ReadByte() // $ hasValueFlow="snappyReader"
|
||||
snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader" Alert
|
||||
snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert
|
||||
tarRead = tar.NewReader(snappyReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -414,10 +414,10 @@ func S2(file io.Reader) {
|
||||
|
||||
s2Reader := s2.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
s2Reader.Read(out) // $ hasValueFlow="s2Reader"
|
||||
s2Reader.ReadByte() // $ hasValueFlow="s2Reader"
|
||||
s2Reader.Read(out) // $ hasValueFlow="s2Reader" Alert
|
||||
s2Reader.ReadByte() // $ hasValueFlow="s2Reader" Alert
|
||||
var buf bytes.Buffer
|
||||
s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader"
|
||||
s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader" Alert
|
||||
tarRead = tar.NewReader(s2Reader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -442,14 +442,14 @@ func GZipIoReader(src io.Reader, dst string) {
|
||||
dstF, _ := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
defer dstF.Close()
|
||||
newSrc := io.Reader(gzipReader)
|
||||
_, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc"
|
||||
_, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc" Alert
|
||||
}
|
||||
func Gzip(file io.Reader) {
|
||||
var tarRead *tar.Reader
|
||||
|
||||
gzipReader, _ := gzip.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
gzipReader.Read(out) // $ hasValueFlow="gzipReader"
|
||||
gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert
|
||||
tarRead = tar.NewReader(gzipReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -474,9 +474,9 @@ func GzipKlauspost(file io.Reader) {
|
||||
|
||||
gzipReader, _ := gzipKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
gzipReader.Read(out) // $ hasValueFlow="gzipReader"
|
||||
gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert
|
||||
var buf bytes.Buffer
|
||||
gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader"
|
||||
gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader" Alert
|
||||
tarRead = tar.NewReader(gzipReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -501,9 +501,9 @@ func PzipKlauspost(file io.Reader) {
|
||||
|
||||
pgzipReader, _ := pgzipKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
pgzipReader.Read(out) // $ hasValueFlow="pgzipReader"
|
||||
pgzipReader.Read(out) // $ hasValueFlow="pgzipReader" Alert
|
||||
var buf bytes.Buffer
|
||||
pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader"
|
||||
pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader" Alert
|
||||
tarRead = tar.NewReader(pgzipReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -528,11 +528,11 @@ func Zstd_Klauspost(file io.Reader) {
|
||||
|
||||
zstdReader, _ := zstdKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
zstdReader.Read(out) // $ hasValueFlow="zstdReader"
|
||||
zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert
|
||||
var buf bytes.Buffer
|
||||
zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader"
|
||||
zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader" Alert
|
||||
var src []byte
|
||||
zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader"
|
||||
zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader" Alert
|
||||
tarRead = tar.NewReader(zstdReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -557,7 +557,7 @@ func Zstd_DataDog(file io.Reader) {
|
||||
|
||||
zstdReader := zstdDataDog.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
zstdReader.Read(out) // $ hasValueFlow="zstdReader"
|
||||
zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert
|
||||
tarRead = tar.NewReader(zstdReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -582,7 +582,7 @@ func Xz(file io.Reader) {
|
||||
|
||||
xzReader, _ := xz.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
xzReader.Read(out) // $ hasValueFlow="xzReader"
|
||||
xzReader.Read(out) // $ hasValueFlow="xzReader" Alert
|
||||
tarRead = tar.NewReader(xzReader)
|
||||
fmt.Println(io.SeekStart)
|
||||
|
||||
@@ -618,7 +618,7 @@ func TarDecompressor(tarRead *tar.Reader) {
|
||||
if cur.Typeflag != tar.TypeReg {
|
||||
continue
|
||||
}
|
||||
data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead"
|
||||
data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead" Alert
|
||||
files[cur.Name] = &fstest.MapFile{Data: data}
|
||||
}
|
||||
fmt.Print(files)
|
||||
@@ -626,7 +626,7 @@ func TarDecompressor(tarRead *tar.Reader) {
|
||||
|
||||
func TarDecompressor2(tarRead *tar.Reader) {
|
||||
var tarOut []byte = make([]byte, 70)
|
||||
tarRead.Read(tarOut) // $ hasValueFlow="tarRead"
|
||||
tarRead.Read(tarOut) // $ hasValueFlow="tarRead" Alert
|
||||
fmt.Println("do sth with output:", tarOut)
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/CWE-525/WebCacheDeception.ql
|
||||
query: experimental/CWE-525/WebCacheDeception.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -79,7 +79,7 @@ func badRoutingNet() {
|
||||
|
||||
http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))))
|
||||
|
||||
http.HandleFunc("/adminusers/", ShowAdminPageCache)
|
||||
http.HandleFunc("/adminusers/", ShowAdminPageCache) // $ Alert
|
||||
err := http.ListenAndServe(":1337", nil)
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
|
||||
@@ -12,12 +12,12 @@ func badRouting() {
|
||||
log.Println("We are logging in Golang!")
|
||||
|
||||
// GET /api/register
|
||||
app.Get("/api/*", func(c *fiber.Ctx) error {
|
||||
app.Get("/api/*", func(c *fiber.Ctx) error { // $ Alert
|
||||
msg := fmt.Sprintf("✋")
|
||||
return c.SendString(msg) // => ✋ register
|
||||
})
|
||||
|
||||
app.Post("/api/*", func(c *fiber.Ctx) error {
|
||||
app.Post("/api/*", func(c *fiber.Ctx) error { // $ Alert
|
||||
msg := fmt.Sprintf("✋")
|
||||
return c.SendString(msg) // => ✋ register
|
||||
})
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func badRoutingChi() {
|
||||
r := chi.NewRouter()
|
||||
r.Use(middleware.Logger)
|
||||
r.Get("/*", func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Get("/*", func(w http.ResponseWriter, r *http.Request) { // $ Alert
|
||||
w.Write([]byte("welcome"))
|
||||
})
|
||||
http.ListenAndServe(":3000", r)
|
||||
|
||||
@@ -18,7 +18,7 @@ func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
|
||||
func badHTTPRouter() {
|
||||
router := httprouter.New()
|
||||
router.GET("/test/*test", Index)
|
||||
router.GET("/test/*test", Index) // $ Alert
|
||||
router.GET("/hello/:name", Hello)
|
||||
|
||||
log.Fatal(http.ListenAndServe(":8082", router))
|
||||
|
||||
@@ -23,10 +23,10 @@ func good() (interface{}, error) {
|
||||
}
|
||||
|
||||
func bad() interface{} {
|
||||
name2 := os.Args[1:]
|
||||
name2 := os.Args[1:] // $ Source[go/dsn-injection-local]
|
||||
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
|
||||
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name2[0])
|
||||
db, _ := sql.Open("mysql", dbDSN)
|
||||
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection-local]
|
||||
return db
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ func good2(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func bad2(w http.ResponseWriter, req *http.Request) interface{} {
|
||||
name := req.FormValue("name")
|
||||
name := req.FormValue("name") // $ Source[go/dsn-injection]
|
||||
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
|
||||
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name)
|
||||
db, _ := sql.Open("mysql", dbDSN)
|
||||
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection]
|
||||
return db
|
||||
}
|
||||
|
||||
@@ -60,12 +60,12 @@ func (Config) Parse([]string) error { return nil }
|
||||
|
||||
func RegexFuncModelTest(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
cfg := NewConfig()
|
||||
err := cfg.Parse(os.Args[1:]) // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
|
||||
err := cfg.Parse(os.Args[1:]) // $ Source[go/dsn-injection-local] // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, cfg.dsn)
|
||||
db, _ := sql.Open("mysql", dbDSN)
|
||||
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection-local]
|
||||
return db, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
query: experimental/CWE-74/DsnInjection.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -8,14 +8,14 @@ edges
|
||||
| Dsn.go:28:102:28:109 | index expression | Dsn.go:28:11:28:110 | []type{args} [array] | provenance | |
|
||||
| Dsn.go:28:102:28:109 | index expression | Dsn.go:28:11:28:110 | call to Sprintf | provenance | FunctionModel |
|
||||
| Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | Dsn.go:67:102:67:104 | cfg [pointer] | provenance | |
|
||||
| Dsn.go:63:9:63:11 | implicit-deref cfg [postupdate] | Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | provenance | |
|
||||
| Dsn.go:63:9:63:11 | implicit-deref cfg [postupdate] | Dsn.go:67:102:67:108 | selection of dsn | provenance | |
|
||||
| Dsn.go:63:9:63:11 | implicit dereference [postupdate] | Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | provenance | |
|
||||
| Dsn.go:63:9:63:11 | implicit dereference [postupdate] | Dsn.go:67:102:67:108 | selection of dsn | provenance | |
|
||||
| Dsn.go:63:19:63:25 | selection of Args | Dsn.go:63:19:63:29 | slice expression | provenance | Src:MaD:1 |
|
||||
| Dsn.go:63:19:63:29 | slice expression | Dsn.go:63:9:63:11 | implicit-deref cfg [postupdate] | provenance | FunctionModel |
|
||||
| Dsn.go:63:19:63:29 | slice expression | Dsn.go:63:9:63:11 | implicit dereference [postupdate] | provenance | FunctionModel |
|
||||
| Dsn.go:67:11:67:109 | []type{args} [array] | Dsn.go:67:11:67:109 | call to Sprintf | provenance | MaD:2 |
|
||||
| Dsn.go:67:11:67:109 | call to Sprintf | Dsn.go:68:29:68:33 | dbDSN | provenance | |
|
||||
| Dsn.go:67:102:67:104 | cfg [pointer] | Dsn.go:67:102:67:104 | implicit-deref cfg | provenance | |
|
||||
| Dsn.go:67:102:67:104 | implicit-deref cfg | Dsn.go:67:102:67:108 | selection of dsn | provenance | |
|
||||
| Dsn.go:67:102:67:104 | cfg [pointer] | Dsn.go:67:102:67:104 | implicit dereference | provenance | |
|
||||
| Dsn.go:67:102:67:104 | implicit dereference | Dsn.go:67:102:67:108 | selection of dsn | provenance | |
|
||||
| Dsn.go:67:102:67:108 | selection of dsn | Dsn.go:67:11:67:109 | []type{args} [array] | provenance | |
|
||||
| Dsn.go:67:102:67:108 | selection of dsn | Dsn.go:67:11:67:109 | call to Sprintf | provenance | FunctionModel |
|
||||
models
|
||||
@@ -28,13 +28,13 @@ nodes
|
||||
| Dsn.go:28:102:28:109 | index expression | semmle.label | index expression |
|
||||
| Dsn.go:29:29:29:33 | dbDSN | semmle.label | dbDSN |
|
||||
| Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | semmle.label | cfg [postupdate] [pointer] |
|
||||
| Dsn.go:63:9:63:11 | implicit-deref cfg [postupdate] | semmle.label | implicit-deref cfg [postupdate] |
|
||||
| Dsn.go:63:9:63:11 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
|
||||
| Dsn.go:63:19:63:25 | selection of Args | semmle.label | selection of Args |
|
||||
| Dsn.go:63:19:63:29 | slice expression | semmle.label | slice expression |
|
||||
| Dsn.go:67:11:67:109 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| Dsn.go:67:11:67:109 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| Dsn.go:67:102:67:104 | cfg [pointer] | semmle.label | cfg [pointer] |
|
||||
| Dsn.go:67:102:67:104 | implicit-deref cfg | semmle.label | implicit-deref cfg |
|
||||
| Dsn.go:67:102:67:104 | implicit dereference | semmle.label | implicit dereference |
|
||||
| Dsn.go:67:102:67:108 | selection of dsn | semmle.label | selection of dsn |
|
||||
| Dsn.go:68:29:68:33 | dbDSN | semmle.label | dbDSN |
|
||||
subpaths
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
query: experimental/CWE-74/DsnInjectionLocal.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/CWE-807/SensitiveConditionBypass.ql
|
||||
query: experimental/CWE-807/SensitiveConditionBypass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -4,7 +4,7 @@ import "net/http"
|
||||
|
||||
func example(w http.ResponseWriter, r *http.Request) {
|
||||
test2 := "test"
|
||||
if r.Header.Get("X-Password") != test2 {
|
||||
if r.Header.Get("X-Password") != test2 { // $ Alert
|
||||
login()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const test = "localhost"
|
||||
|
||||
// Should alert as authkey is sensitive
|
||||
func ex1(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Origin") != test {
|
||||
if r.Header.Get("Origin") != test { // $ Alert
|
||||
authkey := "randomDatta"
|
||||
io.WriteString(w, authkey)
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func ex1(w http.ResponseWriter, r *http.Request) {
|
||||
// Should alert as authkey is sensitive
|
||||
func ex2(w http.ResponseWriter, r *http.Request) {
|
||||
test2 := "test"
|
||||
if r.Header.Get("Origin") != test2 {
|
||||
if r.Header.Get("Origin") != test2 { // $ Alert
|
||||
authkey := "randomDatta2"
|
||||
io.WriteString(w, authkey)
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func ex2(w http.ResponseWriter, r *http.Request) {
|
||||
// Should alert as login() is sensitive
|
||||
func ex3(w http.ResponseWriter, r *http.Request) {
|
||||
test2 := "test"
|
||||
if r.Header.Get("Origin") != test2 {
|
||||
if r.Header.Get("Origin") != test2 { // $ Alert
|
||||
login()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/CWE-840/ConditionalBypass.ql
|
||||
query: experimental/CWE-840/ConditionalBypass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
func exampleHandlerBad(w http.ResponseWriter, r *http.Request) {
|
||||
// BAD: the Origin and Host headers are user controlled
|
||||
if r.Header.Get("Origin") != "http://"+r.Host {
|
||||
if r.Header.Get("Origin") != "http://"+r.Host { // $ Alert
|
||||
//do something
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ import (
|
||||
|
||||
// BAD: taken from https://www.gorillatoolkit.org/pkg/websocket
|
||||
func ex1(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Origin") != "http://"+r.Host {
|
||||
if r.Header.Get("Origin") != "http://"+r.Host { // $ Alert
|
||||
//do something
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: both operands are from remote sources
|
||||
func ex2(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Origin") != "http://"+r.Header.Get("Header") {
|
||||
if r.Header.Get("Origin") != "http://"+r.Header.Get("Header") { // $ Alert
|
||||
//do something
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import "os"
|
||||
func openFiles(filenames []string) {
|
||||
for _, filename := range filenames {
|
||||
file, err := os.Open(filename)
|
||||
defer file.Close()
|
||||
defer file.Close() // $ Alert[go/examples/deferinloop]
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/InconsistentCode/DeferInLoop.ql
|
||||
query: experimental/InconsistentCode/DeferInLoop.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -4,6 +4,6 @@ import "gorm.io/gorm"
|
||||
|
||||
func getUserId(db *gorm.DB, name string) int64 {
|
||||
var user User
|
||||
db.Where("name = ?", name).First(&user)
|
||||
db.Where("name = ?", name).First(&user) // $ Alert[go/examples/gorm-error-not-checked]
|
||||
return user.Id
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/InconsistentCode/GORMErrorNotChecked.ql
|
||||
query: experimental/InconsistentCode/GORMErrorNotChecked.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -3,24 +3,24 @@ package main
|
||||
func test() {
|
||||
var xs []int
|
||||
for _ = range xs {
|
||||
defer test() // not ok
|
||||
defer test() // $ Alert[go/examples/deferinloop] // not ok
|
||||
}
|
||||
|
||||
for _ = range xs {
|
||||
if true {
|
||||
defer test() // not ok
|
||||
defer test() // $ Alert[go/examples/deferinloop] // not ok
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
defer test()
|
||||
defer test() // $ Alert[go/examples/deferinloop]
|
||||
}
|
||||
|
||||
for true {
|
||||
defer test() // not ok
|
||||
defer test() // $ Alert[go/examples/deferinloop] // not ok
|
||||
}
|
||||
|
||||
for false {
|
||||
defer test() // fine but caught
|
||||
defer test() // $ Alert[go/examples/deferinloop] // fine but caught
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
#select
|
||||
| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) |
|
||||
| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) |
|
||||
| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string |
|
||||
| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type |
|
||||
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 |
|
||||
| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 |
|
||||
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 |
|
||||
edges
|
||||
| WrongUsageOfUnsafe.go:17:24:17:48 | type conversion | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | provenance | |
|
||||
| WrongUsageOfUnsafe.go:34:24:34:51 | type conversion | WrongUsageOfUnsafe.go:34:13:34:52 | type conversion | provenance | |
|
||||
@@ -48,15 +60,3 @@ nodes
|
||||
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | semmle.label | type conversion |
|
||||
| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | semmle.label | type conversion |
|
||||
subpaths
|
||||
#select
|
||||
| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) |
|
||||
| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) |
|
||||
| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string |
|
||||
| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type |
|
||||
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 |
|
||||
| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 |
|
||||
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 |
|
||||
|
||||
@@ -74,7 +74,7 @@ func badIndexExpr() {
|
||||
// the address of the 3rd element of the `harmless` array,
|
||||
// and continue for 8 bytes, going out of the boundaries of
|
||||
// `harmless` and crossing into the memory occupied by `secret`.
|
||||
var leaking = (*[8]byte)(unsafe.Pointer(&harmless[2])) // BAD
|
||||
var leaking = (*[8]byte)(unsafe.Pointer(&harmless[2])) // $ Alert // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -108,7 +108,7 @@ func bad0() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we get the pointer to the first byte of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // $ Alert // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -126,7 +126,7 @@ func bad1() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -146,7 +146,7 @@ func bad2() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -163,7 +163,7 @@ func bad3() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // BAD
|
||||
var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
|
||||
fmt.Println(*leaking)
|
||||
fmt.Println([17]string((*leaking)))
|
||||
@@ -186,7 +186,7 @@ func bad4() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -208,7 +208,7 @@ func bad5() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // $ Alert // BAD
|
||||
|
||||
fmt.Println(string(leaking[:]))
|
||||
|
||||
@@ -224,7 +224,7 @@ func bad6() {
|
||||
secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'}
|
||||
|
||||
// Read before secret:
|
||||
var leaking = buffer_request(unsafe.Pointer(&harmless)) // BAD (see inside buffer_request func)
|
||||
var leaking = buffer_request(unsafe.Pointer(&harmless)) // $ Source // BAD (see inside buffer_request func)
|
||||
|
||||
fmt.Println((string)(leaking[:]))
|
||||
|
||||
@@ -240,7 +240,7 @@ func buffer_request(req unsafe.Pointer) [8 + 9]byte {
|
||||
// will be read, the read will also contain pieces of
|
||||
// data from `secret`.
|
||||
var buf [8 + 9]byte
|
||||
buf = *(*[8 + 9]byte)(req) // BAD (from above func)
|
||||
buf = *(*[8 + 9]byte)(req) // $ Alert // BAD (from above func)
|
||||
return buf
|
||||
}
|
||||
func bad7() {
|
||||
@@ -253,7 +253,7 @@ func bad7() {
|
||||
// (notice we read more than the length of harmless);
|
||||
// the leaking array will not contain letters,
|
||||
// but integers representing bytes from `secret`.
|
||||
var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // BAD
|
||||
var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
|
||||
fmt.Println(*leaking)
|
||||
|
||||
@@ -271,7 +271,7 @@ func bad8() {
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless);
|
||||
// the leaking data will contain some bits from `secret`.
|
||||
var leaking = (*int64)(unsafe.Pointer(&harmless)) // BAD
|
||||
var leaking = (*int64)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
|
||||
fmt.Println(*leaking)
|
||||
|
||||
@@ -289,7 +289,7 @@ func bad9() {
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless);
|
||||
// the leaking data will contain some bits from `secret`.
|
||||
var leaking = (*int)(unsafe.Pointer(&harmless)) // BAD
|
||||
var leaking = (*int)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
|
||||
fmt.Println(*leaking)
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Unsafe/WrongUsageOfUnsafe.ql
|
||||
query: experimental/Unsafe/WrongUsageOfUnsafe.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
| test.go:9:2:9:16 | extract:0 ... := ... | test.go:9:13:9:16 | <-... | 0 | file://:0:0:0:0 | bool |
|
||||
| test.go:9:2:9:16 | extract:1 ... := ... | test.go:9:13:9:16 | <-... | 1 | file://:0:0:0:0 | bool |
|
||||
| test.go:15:2:15:20 | extract:0 ... := ... | test.go:15:13:15:20 | index expression | 0 | file://:0:0:0:0 | string |
|
||||
| test.go:15:2:15:20 | extract:1 ... := ... | test.go:15:13:15:20 | index expression | 1 | file://:0:0:0:0 | bool |
|
||||
| test.go:21:2:21:22 | extract:0 ... := ... | test.go:21:13:21:22 | type assertion | 0 | file://:0:0:0:0 | string |
|
||||
| test.go:21:2:21:22 | extract:1 ... := ... | test.go:21:13:21:22 | type assertion | 1 | file://:0:0:0:0 | bool |
|
||||
| test.go:9:2:9:16 | ... := ...[0] | test.go:9:13:9:16 | <-... | 0 | file://:0:0:0:0 | bool |
|
||||
| test.go:9:2:9:16 | ... := ...[1] | test.go:9:13:9:16 | <-... | 1 | file://:0:0:0:0 | bool |
|
||||
| test.go:15:2:15:20 | ... := ...[0] | test.go:15:13:15:20 | index expression | 0 | file://:0:0:0:0 | string |
|
||||
| test.go:15:2:15:20 | ... := ...[1] | test.go:15:13:15:20 | index expression | 1 | file://:0:0:0:0 | bool |
|
||||
| test.go:21:2:21:22 | ... := ...[0] | test.go:21:13:21:22 | type assertion | 0 | file://:0:0:0:0 | string |
|
||||
| test.go:21:2:21:22 | ... := ...[1] | test.go:21:13:21:22 | type assertion | 1 | file://:0:0:0:0 | bool |
|
||||
| test.go:29:2:29:7 | call to f[0] | test.go:29:4:29:6 | call to g | 0 | file://:0:0:0:0 | int |
|
||||
| test.go:29:2:29:7 | call to f[1] | test.go:29:4:29:6 | call to g | 1 | file://:0:0:0:0 | int |
|
||||
| test.go:33:2:33:7 | call to f[0] | test.go:33:4:33:6 | call to v | 0 | file://:0:0:0:0 | int |
|
||||
|
||||
@@ -13,7 +13,7 @@ func logSomething(entry *logrus.Entry) {
|
||||
entry.Traceln(text) // $ logger=text
|
||||
}
|
||||
|
||||
func logrusCalls(selector int) {
|
||||
func logrusCalls() {
|
||||
err := errors.New("Error")
|
||||
var fields logrus.Fields = nil
|
||||
var fn logrus.LogFunction = nil
|
||||
@@ -27,15 +27,11 @@ func logrusCalls(selector int) {
|
||||
tmp = logrus.WithFields(fields) // $ logger=fields
|
||||
logSomething(tmp)
|
||||
|
||||
logrus.Error(text) // $ logger=text
|
||||
logrus.Infof(fmt, text) // $ logger=fmt logger=text
|
||||
if selector == 0 {
|
||||
logrus.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
} else if selector == 1 {
|
||||
logrus.Panicln(text) // $ logger=text
|
||||
} else if selector == 2 {
|
||||
logrus.FatalFn(fn) // $ logger=fn
|
||||
}
|
||||
logrus.Error(text) // $ logger=text
|
||||
logrus.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
logrus.Panicln(text) // $ logger=text
|
||||
logrus.Infof(fmt, text) // $ logger=fmt logger=text
|
||||
logrus.FatalFn(fn) // $ logger=fn
|
||||
|
||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||
logrus.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
|
||||
@@ -7,5 +7,5 @@ var v []byte
|
||||
|
||||
func main() {
|
||||
glogTest(len(v))
|
||||
stdlib(len(v))
|
||||
stdlib()
|
||||
}
|
||||
|
||||
@@ -4,69 +4,37 @@ import (
|
||||
"log"
|
||||
)
|
||||
|
||||
func stdlib(selector int) {
|
||||
func stdlib() {
|
||||
var logger log.Logger
|
||||
logger.SetPrefix("prefix: ")
|
||||
switch selector {
|
||||
case 0:
|
||||
logger.Fatal(text) // $ logger=text
|
||||
case 1:
|
||||
logger.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
case 2:
|
||||
logger.Fatalln(text) // $ logger=text
|
||||
case 3:
|
||||
logger.Panic(text) // $ logger=text
|
||||
case 4:
|
||||
logger.Panicf(fmt, text) // $ logger=fmt logger=text
|
||||
case 5:
|
||||
logger.Panicln(text) // $ logger=text
|
||||
case 6:
|
||||
logger.Print(text) // $ logger=text
|
||||
case 7:
|
||||
logger.Printf(fmt, text) // $ logger=fmt logger=text
|
||||
case 8:
|
||||
logger.Println(text) // $ logger=text
|
||||
}
|
||||
logger.Fatal(text) // $ logger=text
|
||||
logger.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
logger.Fatalln(text) // $ logger=text
|
||||
logger.Panic(text) // $ logger=text
|
||||
logger.Panicf(fmt, text) // $ logger=fmt logger=text
|
||||
logger.Panicln(text) // $ logger=text
|
||||
logger.Print(text) // $ logger=text
|
||||
logger.Printf(fmt, text) // $ logger=fmt logger=text
|
||||
logger.Println(text) // $ logger=text
|
||||
|
||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||
switch selector {
|
||||
case 9:
|
||||
logger.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
case 10:
|
||||
logger.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
case 11:
|
||||
logger.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
logger.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
logger.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
logger.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
|
||||
log.SetPrefix("prefix: ")
|
||||
switch selector {
|
||||
case 12:
|
||||
log.Fatal(text) // $ logger=text
|
||||
case 13:
|
||||
log.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
case 14:
|
||||
log.Fatalln(text) // $ logger=text
|
||||
case 15:
|
||||
log.Panic(text) // $ logger=text
|
||||
case 16:
|
||||
log.Panicf(fmt, text) // $ logger=fmt logger=text
|
||||
case 17:
|
||||
log.Panicln(text) // $ logger=text
|
||||
case 18:
|
||||
log.Print(text) // $ logger=text
|
||||
case 19:
|
||||
log.Printf(fmt, text) // $ logger=fmt logger=text
|
||||
case 20:
|
||||
log.Println(text) // $ logger=text
|
||||
}
|
||||
log.Fatal(text) // $ logger=text
|
||||
log.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
log.Fatalln(text) // $ logger=text
|
||||
log.Panic(text) // $ logger=text
|
||||
log.Panicf(fmt, text) // $ logger=fmt logger=text
|
||||
log.Panicln(text) // $ logger=text
|
||||
log.Print(text) // $ logger=text
|
||||
log.Printf(fmt, text) // $ logger=fmt logger=text
|
||||
log.Println(text) // $ logger=text
|
||||
|
||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||
switch selector {
|
||||
case 21:
|
||||
log.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
case 22:
|
||||
log.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
case 23:
|
||||
log.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
log.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
log.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
log.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,3 +18,4 @@
|
||||
| stmts7.go:10:6:10:15 | canRecover | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.canRecover |
|
||||
| stmts.go:10:6:10:10 | test5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test5 |
|
||||
| stmts.go:46:6:46:10 | test6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test6 |
|
||||
| stmts.go:112:6:112:10 | test9 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test9 |
|
||||
|
||||
@@ -4,9 +4,9 @@ invalidModelRow
|
||||
| test.go:40:8:40:15 | call to Src2 | qltest |
|
||||
| test.go:40:8:40:15 | call to Src2 | qltest-w-subtypes |
|
||||
| test.go:41:8:41:16 | call to Src2 | qltest-w-subtypes |
|
||||
| test.go:42:2:42:21 | extract:0 ... = ... | qltest |
|
||||
| test.go:42:2:42:21 | extract:1 ... = ... | qltest-w-subtypes |
|
||||
| test.go:43:2:43:22 | extract:1 ... = ... | qltest-w-subtypes |
|
||||
| test.go:42:2:42:21 | ... = ...[0] | qltest |
|
||||
| test.go:42:2:42:21 | ... = ...[1] | qltest-w-subtypes |
|
||||
| test.go:43:2:43:22 | ... = ...[1] | qltest-w-subtypes |
|
||||
| test.go:44:11:44:13 | arg [postupdate] | qltest-arg |
|
||||
| test.go:59:9:59:16 | call to Src1 | qltest |
|
||||
| test.go:102:46:102:53 | call to Src1 | qltest |
|
||||
@@ -22,4 +22,4 @@ invalidModelRow
|
||||
| test.go:187:24:187:31 | call to Src1 | qltest |
|
||||
| test.go:191:24:191:31 | call to Src1 | qltest |
|
||||
| test.go:209:10:209:28 | selection of SourceVariable | qltest |
|
||||
| test.go:216:37:218:1 | definition of src | qltest |
|
||||
| test.go:216:15:216:17 | definition of src | qltest |
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
invalidModelRow
|
||||
#select
|
||||
| test.go:17:23:17:25 | arg | test.go:17:10:17:26 | call to StepArgRes |
|
||||
| test.go:18:27:18:29 | arg | test.go:18:2:18:30 | extract:1 ... = ... |
|
||||
| test.go:18:27:18:29 | arg | test.go:18:2:18:30 | ... = ...[1] |
|
||||
| test.go:19:15:19:17 | arg | test.go:19:20:19:23 | arg1 [postupdate] |
|
||||
| test.go:21:16:21:18 | arg | test.go:21:2:21:2 | t [postupdate] |
|
||||
| test.go:22:10:22:10 | t | test.go:22:10:22:24 | call to StepQualRes |
|
||||
| test.go:23:2:23:2 | t | test.go:23:16:23:18 | arg [postupdate] |
|
||||
| test.go:24:32:24:34 | arg | test.go:24:10:24:35 | call to StepArgResNoQual |
|
||||
| test.go:61:25:61:27 | src | test.go:61:12:61:28 | call to StepArgRes |
|
||||
| test.go:64:29:64:31 | src | test.go:64:2:64:32 | extract:1 ... := ... |
|
||||
| test.go:64:29:64:31 | src | test.go:64:2:64:32 | ... := ...[1] |
|
||||
| test.go:68:15:68:17 | src | test.go:68:20:68:25 | taint3 [postupdate] |
|
||||
| test.go:76:21:76:23 | src | test.go:76:2:76:7 | taint4 [postupdate] |
|
||||
| test.go:79:13:79:25 | type assertion | test.go:79:12:79:40 | call to StepQualRes |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| main.go:6:2:6:5 | implicit-one increment statement | main.go:14:7:14:7 | 1 |
|
||||
| main.go:6:2:6:5 | 1 | main.go:14:7:14:7 | 1 |
|
||||
| main.go:10:2:10:2 | definition of x | main.go:10:7:10:7 | 0 |
|
||||
| main.go:10:7:10:7 | 0 | main.go:10:7:10:7 | 0 |
|
||||
| main.go:11:6:11:6 | definition of y | main.go:10:7:10:7 | 0 |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| tst.go:19:10:19:14 | index expression | tst.go:19:10:19:11 | xs | tst.go:19:13:19:13 | 1 |
|
||||
| tst.go:20:10:20:14 | index expression | tst.go:20:10:20:11 | implicit-deref ps | tst.go:20:13:20:13 | 1 |
|
||||
| tst.go:20:10:20:14 | index expression | tst.go:20:10:20:11 | implicit dereference | tst.go:20:13:20:13 | 1 |
|
||||
| tst.go:20:10:20:14 | index expression | tst.go:20:10:20:11 | ps | tst.go:20:13:20:13 | 1 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| tst.go:8:8:8:10 | selection of f | tst.go:8:8:8:8 | implicit-deref t | tst.go:4:2:4:2 | f |
|
||||
| tst.go:8:8:8:10 | selection of f | tst.go:8:8:8:8 | implicit dereference | tst.go:4:2:4:2 | f |
|
||||
| tst.go:8:8:8:10 | selection of f | tst.go:8:8:8:8 | t | tst.go:4:2:4:2 | f |
|
||||
| tst.go:13:9:13:11 | selection of f | tst.go:13:9:13:9 | t | tst.go:4:2:4:2 | f |
|
||||
| tst.go:17:8:17:10 | selection of f | tst.go:17:8:17:8 | x | tst.go:4:2:4:2 | f |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| tst.go:9:9:9:13 | selection of get | tst.go:9:9:9:9 | implicit-deref t | tst.go:12:12:12:14 | get |
|
||||
| tst.go:9:9:9:13 | selection of get | tst.go:9:9:9:9 | implicit dereference | tst.go:12:12:12:14 | get |
|
||||
| tst.go:9:9:9:13 | selection of get | tst.go:9:9:9:9 | t | tst.go:12:12:12:14 | get |
|
||||
| tst.go:18:2:18:7 | selection of bump | tst.go:18:2:18:2 | x | tst.go:7:13:7:16 | bump |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| tst.go:19:2:19:14 | assign:0 ... = ... | tst.go:19:2:19:3 | xs [postupdate] | tst.go:19:5:19:5 | 0 | tst.go:19:10:19:14 | index expression |
|
||||
| tst.go:20:2:20:14 | assign:0 ... = ... | tst.go:20:2:20:3 | implicit-deref ps [postupdate] | tst.go:20:5:20:5 | 0 | tst.go:20:10:20:14 | index expression |
|
||||
| tst.go:20:2:20:14 | assign:0 ... = ... | tst.go:20:2:20:3 | ps [postupdate] | tst.go:20:5:20:5 | 0 | tst.go:20:10:20:14 | index expression |
|
||||
| tst.go:19:2:19:6 | assignment to element | tst.go:19:2:19:3 | xs [postupdate] | tst.go:19:5:19:5 | 0 | tst.go:19:10:19:14 | index expression |
|
||||
| tst.go:20:2:20:6 | assignment to element | tst.go:20:2:20:3 | implicit dereference [postupdate] | tst.go:20:5:20:5 | 0 | tst.go:20:10:20:14 | index expression |
|
||||
| tst.go:20:2:20:6 | assignment to element | tst.go:20:2:20:3 | ps [postupdate] | tst.go:20:5:20:5 | 0 | tst.go:20:10:20:14 | index expression |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user