Compare commits

..

56 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
f658bc9b39 Update expected files for CaseElseBranch AST node change 2026-06-15 12:11:22 +00:00
copilot-swe-agent[bot]
8cb4b9b118 Add CaseElseBranch AST node for Ruby case else branches 2026-06-15 11:42:13 +00:00
Michael Nebel
ab4f170780 Merge pull request #21909 from michaelnebel/csharp/refactoroperations
C#: Refactor- and rename operation expressions.
2026-06-15 12:35:39 +02:00
Owen Mansel-Chan
14c72def96 Merge pull request #21983 from owen-mc/java/convert-to-inline-expectation-tests
Java: Improve inline expectations test comments
2026-06-15 10:31:56 +01:00
Michael Nebel
d0841d2283 C#: Address review comments. 2026-06-15 11:04:59 +02:00
Anders Schack-Mulligen
6934aa0e39 Merge pull request #21980 from aschackmull/cfg/unless-until
Cfg: Add support for unless and until statements
2026-06-15 09:58:03 +02:00
Owen Mansel-Chan
359e272577 Merge pull request #21979 from owen-mc/code-owners-rasmuswl
Remove @RasmusWL from CODEOWNERS
2026-06-14 23:50:05 +01:00
Owen Mansel-Chan
daefaff969 Merge pull request #21975 from github/dependabot/go_modules/go/extractor/extractor-dependencies-563a210b6d
Bump golang.org/x/tools from 0.45.0 to 0.46.0 in /go/extractor in the extractor-dependencies group
2026-06-12 22:04:57 +01:00
Owen Mansel-Chan
4bc083fd7f Remove confusing comments 2026-06-12 21:51:52 +01:00
Owen Mansel-Chan
89c1d66f90 Add SPURIOUS and MISSING alerts based on existing comments 2026-06-12 21:51:50 +01:00
Owen Mansel-Chan
b9670ef831 Merge pull request #21966 from owen-mc/java/convert-to-inline-expectation-tests
Java: convert all qlref tests to inline expectation tests using postprocessing
2026-06-12 21:48:49 +01:00
Michael Nebel
346d140c87 C#: Add change-note. 2026-06-12 15:33:49 +02:00
Michael Nebel
9f0feb467a C#: Add upgrade/downgrade scripts. 2026-06-12 15:26:16 +02:00
Anders Schack-Mulligen
ff61344afa Cfg: Add support for until-statements. 2026-06-12 13:55:05 +02:00
Anders Schack-Mulligen
fe8c029ac7 Cfg: Add support for unless-statements. 2026-06-12 13:50:41 +02:00
Michael Nebel
8d46bfcbd4 C#: Update some of the QL docs. 2026-06-12 12:41:27 +02:00
Michael Nebel
f0640d78d2 C#: Deprecate the operation module. 2026-06-12 12:41:24 +02:00
Michael Nebel
fb9e4a8c40 C#: Move logical operation class from Operation.qll to LogicalOperation.qll. 2026-06-12 12:41:22 +02:00
Michael Nebel
3c407f77a9 C#: Update the QL library implementation for logical operations. 2026-06-12 12:41:19 +02:00
Michael Nebel
9465a1d063 C#: Update DB scheme for logical assignments and expressions (and some other minor changes). 2026-06-12 12:41:16 +02:00
Michael Nebel
072c4837d2 C#: Move bitwise operation classes from Operation.qll to BitwiseOperation.qll. 2026-06-12 12:41:14 +02:00
Michael Nebel
ee040da575 C#: Update test expected output. 2026-06-12 12:41:11 +02:00
Michael Nebel
524330c188 C#: Update the QL library implementation for Bitwise operations. 2026-06-12 12:41:09 +02:00
Michael Nebel
7d54669696 C#: Update DB scheme for bitwise assignments and expressions (and some other minor changes). 2026-06-12 12:41:06 +02:00
Michael Nebel
951a26a01a C#: Move arithmetic like classes from Operation.qll to ArithmeticOperation.qll. 2026-06-12 12:41:03 +02:00
Michael Nebel
2bbcc1e88c C#: Update the QL library implementation for Arithmetic operations. 2026-06-12 12:41:01 +02:00
Michael Nebel
d101e45efc C#: Update DB scheme for arithmetic assignments and expressions (and some other minor changes). 2026-06-12 12:40:58 +02:00
Anders Schack-Mulligen
912dc9c0bd Merge pull request #21955 from aschackmull/cfg/try-body-index
Cfg: Fold getTryInit into indexed getBody.
2026-06-12 11:36:25 +02:00
Owen Mansel-Chan
eea406f622 Remove @RasmusWL from CODEOWNERS
He hasn't worked on CodeQL for a few years now. He
told me that he doesn't remember how these scripts
work.
2026-06-12 10:33:37 +02:00
Owen Mansel-Chan
de7afcaec3 Merge pull request #21976 from JarLob/patch-1
Update regex for GitHub hosted runner matching
2026-06-12 09:09:40 +01:00
Anders Schack-Mulligen
f3ec7087e3 Cfg: Fix type. 2026-06-12 10:02:48 +02:00
Jaroslav Lobačevski
bea5522473 rename change note 2026-06-12 07:52:34 +00:00
Jaroslav Lobačevski
eedef515f7 Updated regex. Added test and change note. 2026-06-12 07:50:02 +00:00
Jaroslav Lobačevski
9078b511c6 Update regex for GitHub hosted runner matching
Fixes false positives (of critical severity). New label naming conventions were introduced since the query was initially written.
2026-06-12 09:37:18 +03:00
dependabot[bot]
1ac079d066 Bump golang.org/x/tools
Bumps the extractor-dependencies group in /go/extractor with 1 update: [golang.org/x/tools](https://github.com/golang/tools).


Updates `golang.org/x/tools` from 0.45.0 to 0.46.0
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.45.0...v0.46.0)

---
updated-dependencies:
- dependency-name: golang.org/x/tools
  dependency-version: 0.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-12 03:03:31 +00:00
Owen Mansel-Chan
29b0c286a7 Fix 3 more tests 2026-06-11 23:40:14 +02:00
Asger F
ad18659373 Merge pull request #21796 from mattcosta7/patch-1
Add UseMemoDirective and UseNoMemoDirective classes
2026-06-11 23:01:29 +02:00
Owen Mansel-Chan
a4bf2b8f58 Fix 3 tests 2026-06-11 22:59:39 +02:00
Owen Mansel-Chan
a375e186ed Third pass 2026-06-11 21:53:22 +02:00
Matthew Costabile
923fe2dcb9 Merge branch 'main' into patch-1 2026-06-11 15:19:58 -04:00
Jeroen Ketema
642259cd51 Merge pull request #21968 from jketema/jketema/namequalifiers
C++: Fix `NameQualifyingElement` db inconsistency
2026-06-11 15:11:51 +02:00
Owen Mansel-Chan
0d984588f9 Merge pull request #21965 from owen-mc/go/convert-to-inline-expectation-tests
Go: convert all qlref tests to inline expectation tests using postprocessing
2026-06-11 13:27:06 +01:00
Owen Mansel-Chan
b4a9689341 Convert .qlref test to inline expectations 2026-06-11 07:15:54 +02:00
Owen Mansel-Chan
6a8e20a0c8 Fix pre-existing whitespace issues in go test files 2026-06-11 07:15:09 +02:00
Owen Mansel-Chan
4c411bbcb5 Convert hand-rolled inline expectations test 2026-06-11 07:13:48 +02:00
Jeroen Ketema
ef00aa2567 C++: Add upgrade and downgrade scripts 2026-06-10 14:38:15 +02:00
Jeroen Ketema
6d0968744b C++: Fix NameQualifyingElement db inconsistency 2026-06-10 14:35:36 +02:00
Jeroen Ketema
98f147556a C++: Add namequalifier test with inconsistency
While where the remove the file restriction in QL.
2026-06-10 14:27:56 +02:00
Owen Mansel-Chan
3693185b6b Second pass 2026-06-10 09:14:47 +02:00
Owen Mansel-Chan
1c1d26453d First pass converting qlref tests to inline expectation with postprocess 2026-06-10 07:46:42 +02:00
Anders Schack-Mulligen
01173bf383 Cfg: Fold getTryInit into indexed getBody. 2026-06-08 14:03:12 +02:00
Matthew Costabile
2884428b62 Merge branch 'main' into patch-1 2026-05-26 07:16:24 -04:00
Matthew Costabile
e10750b35e Merge branch 'main' into patch-1 2026-05-05 22:09:09 -04:00
Matthew Costabile
18550039f2 Update KnownDirective.expected 2026-05-05 11:06:40 -04:00
Matthew Costabile
0caa483925 change note and test 2026-05-05 13:20:39 +00:00
Matthew Costabile
640b17ec78 Add UseMemoDirective and UseNoMemoDirective classes 2026-05-05 07:41:36 -04:00
771 changed files with 21422 additions and 4574 deletions

View File

@@ -59,9 +59,5 @@ MODULE.bazel @github/codeql-ci-reviewers
/.github/workflows/rust.yml @github/codeql-rust /.github/workflows/rust.yml @github/codeql-rust
/.github/workflows/swift.yml @github/codeql-swift /.github/workflows/swift.yml @github/codeql-swift
# Misc
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL
/misc/scripts/generate-code-scanning-query-list.py @RasmusWL
# .devcontainer # .devcontainer
/.devcontainer/ @github/codeql-ci-reviewers /.devcontainer/ @github/codeql-ci-reviewers

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.

View File

@@ -2,10 +2,12 @@ import actions
bindingset[runner] bindingset[runner]
predicate isGithubHostedRunner(string runner) { predicate isGithubHostedRunner(string runner) {
// list of github hosted repos: https://github.com/actions/runner-images/blob/main/README.md#available-images // The list of github hosted repos:
runner // https://github.com/actions/runner-images/blob/main/README.md#available-images
.toLowerCase() // https://docs.github.com/en/enterprise-cloud@latest/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#standard-github-hosted-runners-for-public-repositories
.regexpMatch("^(ubuntu-([0-9.]+|latest)|macos-([0-9]+|latest)(-x?large)?|windows-([0-9.]+|latest))$") runner.toLowerCase().regexpMatch("^ubuntu-([0-9.]+|latest|slim)(-arm)?$") or
runner.toLowerCase().regexpMatch("^macos-([0-9]+|latest)(-x?large|-intel)?$") or
runner.toLowerCase().regexpMatch("^windows-([0-9.]+|latest)(-vs[0-9.]+)?(-arm)?$")
} }
bindingset[runner] bindingset[runner]

View File

@@ -0,0 +1,43 @@
name: test
on:
pull_request:
jobs:
test:
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- ubuntu-24.04
- ubuntu-24.04-arm
- ubuntu-22.04
- ubuntu-22.04-arm
- ubuntu-26.04
- ubuntu-26.04-arm
- ubuntu-slim
- macos-26
- macos-26-xlarge
- macos-26-intel
- macos-26-large
- macos-latest-large
- macos-15-large
- macos-15
- macos-15-intel
- macos-latest
- macos-15
- macos-15-xlarge
- macos-14-large
- macos-14
- macos-14-xlarge
- windows-2025-vs2026
- windows-latest
- windows-2025
- windows-2022
- windows-11
- windows-11-arm
- windows-11-vs2026-arm
runs-on: ${{ matrix.os }}
steps:
- run: cmd

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Fix NameQualifier inconsistency
compatibility: full

View File

@@ -1071,7 +1071,7 @@ class NullPointerType extends BuiltInType {
* const float fa[40]; * const float fa[40];
* ``` * ```
*/ */
class DerivedType extends Type, @derivedtype { class DerivedType extends Type, NameQualifyingElement, @derivedtype {
override string toString() { result = this.getName() } override string toString() { result = this.getName() }
override string getName() { derivedtypes(underlyingElement(this), result, _, _) } override string getName() { derivedtypes(underlyingElement(this), result, _, _) }

View File

@@ -1430,7 +1430,8 @@ specialnamequalifyingelements(
@namequalifyingelement = @namespace @namequalifyingelement = @namespace
| @specialnamequalifyingelement | @specialnamequalifyingelement
| @usertype | @usertype
| @decltype; | @decltype
| @derivedtype;
namequalifiers( namequalifiers(
unique int id: @namequalifier, unique int id: @namequalifier,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Fix NameQualifier inconsistency
compatibility: full

View File

@@ -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: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: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) | | name_qualifiers.cpp:34:7:34:8 | :: | name_qualifiers.cpp:34:9:34:12 | N1:: | file://:0:0:0:0 | (global namespace) |

View File

@@ -1,7 +1,5 @@
import cpp import cpp
from NameQualifier nq, Location l from NameQualifier nq, Location l
where where l = nq.getQualifiedElement().getLocation()
l = nq.getQualifiedElement().getLocation() and
l.getFile().getShortName() = "name_qualifiers"
select nq, nq.getQualifiedElement(), nq.getQualifyingElement() select nq, nq.getQualifiedElement(), nq.getQualifyingElement()

View File

@@ -1,8 +1,8 @@
// This file is present to test whether name-qualifying an enum constant leads to a database inconsistency. // 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 }; }; struct S { enum E { A }; };
static int f() { static void f() {
switch(0) { case S::A: break; } switch(0) { case S::A: break; }
} }

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Restructure and rename types related to operations.
compatibility: full

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* Renamed types related to *operation* expressions. The QL classes `BinaryArithmeticOperation`, `BinaryBitwiseOperation`, and `BinaryLogicalOperation` now include compound assignments; for example, `BinaryArithmeticOperation` now includes `a += b`.

View File

@@ -50,15 +50,15 @@ private predicate maybeUsedInElfHashFunction(Variable v, Operation xor, Operatio
| |
add instanceof AddOperation and add instanceof AddOperation and
e1.getAChild*() = add.getAnOperand() and e1.getAChild*() = add.getAnOperand() and
e1 instanceof BinaryBitwiseOperation and e1 instanceof BinaryBitwiseExpr and
e2 = e1.(BinaryBitwiseOperation).getLeftOperand() and e2 = e1.(BinaryBitwiseExpr).getLeftOperand() and
v = addAssign.getTargetVariable() and v = addAssign.getTargetVariable() and
addAssign.getAChild*() = add and addAssign.getAChild*() = add and
(xor instanceof BitwiseXorExpr or xor instanceof AssignXorExpr) and (xor instanceof BitwiseXorExpr or xor instanceof AssignXorExpr) and
addAssign.getControlFlowNode().getASuccessor*() = xor.getControlFlowNode() and addAssign.getControlFlowNode().getASuccessor*() = xor.getControlFlowNode() and
xorAssign.getAChild*() = xor and xorAssign.getAChild*() = xor and
v = xorAssign.getTargetVariable() and v = xorAssign.getTargetVariable() and
(notOp instanceof UnaryBitwiseOperation or notOp instanceof AssignBitwiseOperation) and (notOp instanceof UnaryBitwiseOperation or notOp instanceof AssignBitwiseExpr) and
xor.getControlFlowNode().getASuccessor*() = notOp.getControlFlowNode() and xor.getControlFlowNode().getASuccessor*() = notOp.getControlFlowNode() and
notAssign.getAChild*() = notOp and notAssign.getAChild*() = notOp and
v = notAssign.getTargetVariable() and v = notAssign.getTargetVariable() and

View File

@@ -290,7 +290,7 @@ module AssignableInternal {
newtype TAssignableDefinition = newtype TAssignableDefinition =
TAssignmentDefinition(Assignment a) { TAssignmentDefinition(Assignment a) {
not a.getLeftOperand() instanceof TupleExpr and not a.getLeftOperand() instanceof TupleExpr and
not a instanceof AssignCallOperation and not a instanceof AssignCallExpr and
not a instanceof AssignCoalesceExpr not a instanceof AssignCoalesceExpr
} or } or
TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { tupleAssignmentDefinition(ae, leaf) } or TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { tupleAssignmentDefinition(ae, leaf) } or
@@ -324,7 +324,7 @@ module AssignableInternal {
TAddressOfDefinition(AddressOfExpr aoe) or TAddressOfDefinition(AddressOfExpr aoe) or
TPatternDefinition(TopLevelPatternDecl tlpd) or TPatternDefinition(TopLevelPatternDecl tlpd) or
TAssignOperationDefinition(AssignOperation ao) { TAssignOperationDefinition(AssignOperation ao) {
ao instanceof AssignCallOperation and not ao instanceof CompoundAssignmentOperatorCall ao instanceof AssignCallExpr and not ao instanceof CompoundAssignmentOperatorCall
or or
ao instanceof AssignCoalesceExpr ao instanceof AssignCoalesceExpr
} }

View File

@@ -912,18 +912,17 @@ module Internal {
) )
or or
// In C#, `null + 1` has type `int?` with value `null` // In C#, `null + 1` has type `int?` with value `null`
exists(BinaryOperation bo, Expr o | result =
bo instanceof BinaryArithmeticOperation or any(BinaryArithmeticOperation bao |
bo instanceof AssignArithmeticOperation exists(Expr o |
| bao.getAnOperand() = e and
result = bo and bao.getAnOperand() = o and
bo.getAnOperand() = e and
bo.getAnOperand() = o and
// The other operand must be provably non-null in order // The other operand must be provably non-null in order
// for `only if` to hold // for `only if` to hold
nonNullValueImplied(o) and nonNullValueImplied(o) and
e != o e != o
) )
)
} }
/** /**
@@ -934,10 +933,10 @@ module Internal {
any(QualifiableExpr qe | any(QualifiableExpr qe |
qe.isConditional() and qe.isConditional() and
result = qe.getQualifier() result = qe.getQualifier()
) or )
or
// In C#, `null + 1` has type `int?` with value `null` // In C#, `null + 1` has type `int?` with value `null`
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand()) or e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand())
e = any(AssignArithmeticOperation aao | result = aao.getAnOperand())
} }
deprecated predicate isGuard(Expr e, GuardValue val) { deprecated predicate isGuard(Expr e, GuardValue val) {

View File

@@ -172,6 +172,10 @@ module Ast implements AstSig<Location> {
class DoStmt = CS::DoStmt; class DoStmt = CS::DoStmt;
class UntilStmt extends LoopStmt {
UntilStmt() { none() }
}
final private class FinalForStmt = CS::ForStmt; final private class FinalForStmt = CS::ForStmt;
class ForStmt extends FinalForStmt { class ForStmt extends FinalForStmt {
@@ -203,7 +207,7 @@ module Ast implements AstSig<Location> {
final private class FinalTryStmt = CS::TryStmt; final private class FinalTryStmt = CS::TryStmt;
class TryStmt extends FinalTryStmt { class TryStmt extends FinalTryStmt {
Stmt getBody() { result = this.getBlock() } AstNode getBody(int index) { index = 0 and result = this.getBlock() }
CatchClause getCatch(int index) { result = this.getCatchClause(index) } CatchClause getCatch(int index) { result = this.getCatchClause(index) }

View File

@@ -124,9 +124,7 @@ private module Internal {
TDispatchDynamicOperatorCall(DynamicOperatorCall doc) or TDispatchDynamicOperatorCall(DynamicOperatorCall doc) or
TDispatchDynamicMemberAccess(DynamicMemberAccess dma) or TDispatchDynamicMemberAccess(DynamicMemberAccess dma) or
TDispatchDynamicElementAccess(DynamicElementAccess dea) or TDispatchDynamicElementAccess(DynamicElementAccess dea) or
TDispatchDynamicEventAccess( TDispatchDynamicEventAccess(AssignArithmeticExpr aao, DynamicMemberAccess dma, string name) {
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
) {
isPotentialEventCall(aao, dma, name) isPotentialEventCall(aao, dma, name)
} or } or
TDispatchDynamicObjectCreation(DynamicObjectCreation doc) or TDispatchDynamicObjectCreation(DynamicObjectCreation doc) or
@@ -230,7 +228,7 @@ private module Internal {
* accessor. * accessor.
*/ */
private predicate isPotentialEventCall( private predicate isPotentialEventCall(
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name AssignArithmeticExpr aao, DynamicMemberAccess dma, string name
) { ) {
aao instanceof DynamicOperatorCall and aao instanceof DynamicOperatorCall and
dma = aao.getLeftOperand() and dma = aao.getLeftOperand() and
@@ -1397,9 +1395,7 @@ private module Internal {
private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall, private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall,
TDispatchDynamicEventAccess TDispatchDynamicEventAccess
{ {
override AssignArithmeticOperation getCall() { override AssignArithmeticExpr getCall() { this = TDispatchDynamicEventAccess(result, _, _) }
this = TDispatchDynamicEventAccess(result, _, _)
}
override string getName() { this = TDispatchDynamicEventAccess(_, _, result) } override string getName() { this = TDispatchDynamicEventAccess(_, _, result) }

View File

@@ -11,19 +11,27 @@ import Expr
* (`UnaryArithmeticOperation`) or a binary arithmetic operation * (`UnaryArithmeticOperation`) or a binary arithmetic operation
* (`BinaryArithmeticOperation`). * (`BinaryArithmeticOperation`).
*/ */
class ArithmeticOperation extends Operation, @arith_op_expr { class ArithmeticOperation extends Operation, @arith_operation {
override string getOperator() { none() } override string getOperator() { none() }
} }
/** /**
* A unary arithmetic operation. Either a unary minus operation * A binary arithmetic operation. Either a binary arithmetic expression (`BinaryArithmeticExpr`) or
* (`UnaryMinusExpr`), a unary plus operation (`UnaryPlusExpr`), * an arithmetic assignment expression (`AssignArithmeticExpr`).
* or a mutator operation (`MutatorOperation`).
*/ */
class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_arith_op_expr { } class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_operation {
override string getOperator() { none() }
}
/** /**
* A unary minus operation, for example `-x`. * A unary arithmetic operation. Either a unary minus expression
* (`UnaryMinusExpr`), a unary plus expression (`UnaryPlusExpr`),
* or a mutator operation (`MutatorOperation`).
*/
class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_arith_operation { }
/**
* A unary minus expression, for example `-x`.
*/ */
class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr { class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
override string getOperator() { result = "-" } override string getOperator() { result = "-" }
@@ -32,7 +40,7 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
} }
/** /**
* A unary plus operation, for example `+x`. * A unary plus expression, for example `+x`.
*/ */
class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr { class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
override string getOperator() { result = "+" } override string getOperator() { result = "+" }
@@ -44,40 +52,40 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
* A mutator operation. Either an increment operation (`IncrementOperation`) * A mutator operation. Either an increment operation (`IncrementOperation`)
* or a decrement operation (`DecrementOperation`). * or a decrement operation (`DecrementOperation`).
*/ */
class MutatorOperation extends UnaryArithmeticOperation, @mut_op_expr { } class MutatorOperation extends UnaryArithmeticOperation, @mut_operation { }
/** /**
* An increment operation. Either a postfix increment operation * An increment operation. Either a postfix increment expression
* (`PostIncrExpr`) or a prefix increment operation (`PreIncrExpr`). * (`PostIncrExpr`) or a prefix increment expression (`PreIncrExpr`).
*/ */
class IncrementOperation extends MutatorOperation, @incr_op_expr { class IncrementOperation extends MutatorOperation, @incr_operation {
override string getOperator() { result = "++" } override string getOperator() { result = "++" }
} }
/** /**
* A decrement operation. Either a postfix decrement operation * A decrement operation. Either a postfix decrement expression
* (`PostDecrExpr`) or a prefix decrement operation (`PreDecrExpr`). * (`PostDecrExpr`) or a prefix decrement expression (`PreDecrExpr`).
*/ */
class DecrementOperation extends MutatorOperation, @decr_op_expr { class DecrementOperation extends MutatorOperation, @decr_operation {
override string getOperator() { result = "--" } override string getOperator() { result = "--" }
} }
/** /**
* A prefix increment operation, for example `++x`. * A prefix increment expression, for example `++x`.
*/ */
class PreIncrExpr extends IncrementOperation, @pre_incr_expr { class PreIncrExpr extends IncrementOperation, @pre_incr_expr {
override string getAPrimaryQlClass() { result = "PreIncrExpr" } override string getAPrimaryQlClass() { result = "PreIncrExpr" }
} }
/** /**
* A prefix decrement operation, for example `--x`. * A prefix decrement expression, for example `--x`.
*/ */
class PreDecrExpr extends DecrementOperation, @pre_decr_expr { class PreDecrExpr extends DecrementOperation, @pre_decr_expr {
override string getAPrimaryQlClass() { result = "PreDecrExpr" } override string getAPrimaryQlClass() { result = "PreDecrExpr" }
} }
/** /**
* A postfix increment operation, for example `x++`. * A postfix increment expression, for example `x++`.
*/ */
class PostIncrExpr extends IncrementOperation, @post_incr_expr { class PostIncrExpr extends IncrementOperation, @post_incr_expr {
override string toString() { result = "..." + this.getOperator() } override string toString() { result = "..." + this.getOperator() }
@@ -86,7 +94,7 @@ class PostIncrExpr extends IncrementOperation, @post_incr_expr {
} }
/** /**
* A postfix decrement operation, for example `x--`. * A postfix decrement expression, for example `x--`.
*/ */
class PostDecrExpr extends DecrementOperation, @post_decr_expr { class PostDecrExpr extends DecrementOperation, @post_decr_expr {
override string toString() { result = "..." + this.getOperator() } override string toString() { result = "..." + this.getOperator() }
@@ -95,55 +103,84 @@ class PostDecrExpr extends DecrementOperation, @post_decr_expr {
} }
/** /**
* A binary arithmetic operation. Either an addition operation * An addition operation, either `x + y` or `x += y`.
* (`AddExpr`), a subtraction operation (`SubExpr`), a multiplication
* operation (`MulExpr`), a division operation (`DivExpr`), or a
* remainder operation (`RemExpr`).
*/ */
class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_op_expr { class AddOperation extends BinaryArithmeticOperation, @add_operation { }
override string getOperator() { none() }
/**
* A subtraction operation, either `x - y` or `x -= y`.
*/
class SubOperation extends BinaryArithmeticOperation, @sub_operation { }
/**
* A multiplication operation, either `x * y` or `x *= y`.
*/
class MulOperation extends BinaryArithmeticOperation, @mul_operation { }
/**
* A division operation, either `x / y` or `x /= y`.
*/
class DivOperation extends BinaryArithmeticOperation, @div_operation {
/** Gets the numerator of this division operation. */
Expr getNumerator() { result = this.getLeftOperand() }
/** Gets the denominator of this division operation. */
Expr getDenominator() { result = this.getRightOperand() }
} }
/** /**
* An addition operation, for example `x + y`. * A remainder operation, either `x % y` or `x %= y`.
*/ */
class AddExpr extends BinaryArithmeticOperation, AddOperation, @add_expr { class RemOperation extends BinaryArithmeticOperation, @rem_operation { }
/**
* A binary arithmetic expression. Either an addition expression
* (`AddExpr`), a subtraction expression (`SubExpr`), a multiplication
* expression (`MulExpr`), a division expression (`DivExpr`), or a
* remainder expression (`RemExpr`).
*/
class BinaryArithmeticExpr extends BinaryArithmeticOperation, @bin_arith_expr { }
/**
* An addition expression, for example `x + y`.
*/
class AddExpr extends BinaryArithmeticExpr, AddOperation, @add_expr {
override string getOperator() { result = "+" } override string getOperator() { result = "+" }
override string getAPrimaryQlClass() { result = "AddExpr" } override string getAPrimaryQlClass() { result = "AddExpr" }
} }
/** /**
* A subtraction operation, for example `x - y`. * A subtraction expression, for example `x - y`.
*/ */
class SubExpr extends BinaryArithmeticOperation, SubOperation, @sub_expr { class SubExpr extends BinaryArithmeticExpr, SubOperation, @sub_expr {
override string getOperator() { result = "-" } override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "SubExpr" } override string getAPrimaryQlClass() { result = "SubExpr" }
} }
/** /**
* A multiplication operation, for example `x * y`. * A multiplication expression, for example `x * y`.
*/ */
class MulExpr extends BinaryArithmeticOperation, MulOperation, @mul_expr { class MulExpr extends BinaryArithmeticExpr, MulOperation, @mul_expr {
override string getOperator() { result = "*" } override string getOperator() { result = "*" }
override string getAPrimaryQlClass() { result = "MulExpr" } override string getAPrimaryQlClass() { result = "MulExpr" }
} }
/** /**
* A division operation, for example `x / y`. * A division expression, for example `x / y`.
*/ */
class DivExpr extends BinaryArithmeticOperation, DivOperation, @div_expr { class DivExpr extends BinaryArithmeticExpr, DivOperation, @div_expr {
override string getOperator() { result = "/" } override string getOperator() { result = "/" }
override string getAPrimaryQlClass() { result = "DivExpr" } override string getAPrimaryQlClass() { result = "DivExpr" }
} }
/** /**
* A remainder operation, for example `x % y`. * A remainder expression, for example `x % y`.
*/ */
class RemExpr extends BinaryArithmeticOperation, RemOperation, @rem_expr { class RemExpr extends BinaryArithmeticExpr, RemOperation, @rem_expr {
override string getOperator() { result = "%" } override string getOperator() { result = "%" }
override string getAPrimaryQlClass() { result = "RemExpr" } override string getAPrimaryQlClass() { result = "RemExpr" }

View File

@@ -72,9 +72,9 @@ class AssignExpr extends Assignment, @simple_assign_expr {
} }
/** /**
* An assignment operation. Either an arithmetic assignment operation * An assignment operation. Either an arithmetic assignment expression
* (`AssignArithmeticOperation`), a bitwise assignment operation * (`AssignArithmeticExpr`), a bitwise assignment expression
* (`AssignBitwiseOperation`), an event assignment (`AddOrRemoveEventExpr`), or * (`AssignBitwiseExpr`), an event assignment (`AddOrRemoveEventExpr`), or
* a null-coalescing assignment (`AssignCoalesceExpr`). * a null-coalescing assignment (`AssignCoalesceExpr`).
*/ */
class AssignOperation extends Assignment, @assign_op_expr { class AssignOperation extends Assignment, @assign_op_expr {
@@ -94,134 +94,147 @@ class AssignOperation extends Assignment, @assign_op_expr {
} }
/** /**
* A compound assignment operation that invokes an operator. * A compound assignment expression that invokes an operator.
* *
* (1) `x += y` invokes the compound assignment operator `+=` (if it exists). * (1) `x += y` invokes the compound assignment operator `+=` (if it exists).
* (2) `x += y` invokes the operator `+` and assigns `x + y` to `x`. * (2) `x += y` invokes the operator `+` and assigns `x + y` to `x`.
* *
* Either an arithmetic assignment operation (`AssignArithmeticOperation`) or a bitwise * Either an arithmetic assignment expression (`AssignArithmeticExpr`) or a bitwise
* assignment operation (`AssignBitwiseOperation`). * assignment expression (`AssignBitwiseExpr`).
*/ */
class AssignCallOperation extends AssignOperation, OperatorCall, QualifiableExpr, class AssignCallExpr extends AssignOperation, OperatorCall, QualifiableExpr, @assign_op_call_expr {
@assign_op_call_expr
{
override string toString() { result = AssignOperation.super.toString() } override string toString() { result = AssignOperation.super.toString() }
} }
/** /**
* An arithmetic assignment operation. Either an addition assignment operation * DEPRECATED: Use `AssignCallExpr` instead.
* (`AssignAddExpr`), a subtraction assignment operation (`AssignSubExpr`), a
* multiplication assignment operation (`AssignMulExpr`), a division assignment
* operation (`AssignDivExpr`), or a remainder assignment operation
* (`AssignRemExpr`).
*/ */
class AssignArithmeticOperation extends AssignCallOperation, @assign_arith_expr { } deprecated class AssignCallOperation = AssignCallExpr;
/** /**
* An addition assignment operation, for example `x += y`. * An arithmetic assignment expression. Either an addition assignment expression
* (`AssignAddExpr`), a subtraction assignment expression (`AssignSubExpr`), a
* multiplication assignment expression (`AssignMulExpr`), a division assignment
* expression (`AssignDivExpr`), or a remainder assignment expression
* (`AssignRemExpr`).
*/ */
class AssignAddExpr extends AssignArithmeticOperation, AddOperation, @assign_add_expr { class AssignArithmeticExpr extends AssignCallExpr, @assign_arith_expr { }
/**
* DEPRECATED: Use `AssignArithmeticExpr` instead.
*/
deprecated class AssignArithmeticOperation = AssignArithmeticExpr;
/**
* An addition assignment expression, for example `x += y`.
*/
class AssignAddExpr extends AssignArithmeticExpr, AddOperation, @assign_add_expr {
override string getOperator() { result = "+=" } override string getOperator() { result = "+=" }
override string getAPrimaryQlClass() { result = "AssignAddExpr" } override string getAPrimaryQlClass() { result = "AssignAddExpr" }
} }
/** /**
* A subtraction assignment operation, for example `x -= y`. * A subtraction assignment expression, for example `x -= y`.
*/ */
class AssignSubExpr extends AssignArithmeticOperation, SubOperation, @assign_sub_expr { class AssignSubExpr extends AssignArithmeticExpr, SubOperation, @assign_sub_expr {
override string getOperator() { result = "-=" } override string getOperator() { result = "-=" }
override string getAPrimaryQlClass() { result = "AssignSubExpr" } override string getAPrimaryQlClass() { result = "AssignSubExpr" }
} }
/** /**
* An multiplication assignment operation, for example `x *= y`. * A multiplication assignment expression, for example `x *= y`.
*/ */
class AssignMulExpr extends AssignArithmeticOperation, MulOperation, @assign_mul_expr { class AssignMulExpr extends AssignArithmeticExpr, MulOperation, @assign_mul_expr {
override string getOperator() { result = "*=" } override string getOperator() { result = "*=" }
override string getAPrimaryQlClass() { result = "AssignMulExpr" } override string getAPrimaryQlClass() { result = "AssignMulExpr" }
} }
/** /**
* An division assignment operation, for example `x /= y`. * A division assignment expression, for example `x /= y`.
*/ */
class AssignDivExpr extends AssignArithmeticOperation, DivOperation, @assign_div_expr { class AssignDivExpr extends AssignArithmeticExpr, DivOperation, @assign_div_expr {
override string getOperator() { result = "/=" } override string getOperator() { result = "/=" }
override string getAPrimaryQlClass() { result = "AssignDivExpr" } override string getAPrimaryQlClass() { result = "AssignDivExpr" }
} }
/** /**
* A remainder assignment operation, for example `x %= y`. * A remainder assignment expression, for example `x %= y`.
*/ */
class AssignRemExpr extends AssignArithmeticOperation, RemOperation, @assign_rem_expr { class AssignRemExpr extends AssignArithmeticExpr, RemOperation, @assign_rem_expr {
override string getOperator() { result = "%=" } override string getOperator() { result = "%=" }
override string getAPrimaryQlClass() { result = "AssignRemExpr" } override string getAPrimaryQlClass() { result = "AssignRemExpr" }
} }
/** /**
* A bitwise assignment operation. Either a bitwise-and assignment * A bitwise assignment expression. Either a bitwise-and assignment
* operation (`AssignAndExpr`), a bitwise-or assignment * expression (`AssignAndExpr`), a bitwise-or assignment
* operation (`AssignOrExpr`), a bitwise exclusive-or assignment * expression (`AssignOrExpr`), a bitwise exclusive-or assignment
* operation (`AssignXorExpr`), a left-shift assignment * expression (`AssignXorExpr`), a left-shift assignment
* operation (`AssignLeftShiftExpr`), or a right-shift assignment * expression (`AssignLeftShiftExpr`), or a right-shift assignment
* operation (`AssignRightShiftExpr`), or an unsigned right-shift assignment * expression (`AssignRightShiftExpr`), or an unsigned right-shift assignment
* operation (`AssignUnsignedRightShiftExpr`). * expression (`AssignUnsignedRightShiftExpr`).
*/ */
class AssignBitwiseOperation extends AssignCallOperation, @assign_bitwise_expr { } class AssignBitwiseExpr extends AssignCallExpr, @assign_bitwise_expr { }
/** /**
* A bitwise-and assignment operation, for example `x &= y`. * DEPRECATED: Use `AssignBitwiseExpr` instead.
*/ */
class AssignAndExpr extends AssignBitwiseOperation, BitwiseAndOperation, @assign_and_expr { deprecated class AssignBitwiseOperation = AssignBitwiseExpr;
/**
* A bitwise-and assignment expression, for example `x &= y`.
*/
class AssignAndExpr extends AssignBitwiseExpr, BitwiseAndOperation, @assign_and_expr {
override string getOperator() { result = "&=" } override string getOperator() { result = "&=" }
override string getAPrimaryQlClass() { result = "AssignAndExpr" } override string getAPrimaryQlClass() { result = "AssignAndExpr" }
} }
/** /**
* A bitwise-or assignment operation, for example `x |= y`. * A bitwise-or assignment expression, for example `x |= y`.
*/ */
class AssignOrExpr extends AssignBitwiseOperation, BitwiseOrOperation, @assign_or_expr { class AssignOrExpr extends AssignBitwiseExpr, BitwiseOrOperation, @assign_or_expr {
override string getOperator() { result = "|=" } override string getOperator() { result = "|=" }
override string getAPrimaryQlClass() { result = "AssignOrExpr" } override string getAPrimaryQlClass() { result = "AssignOrExpr" }
} }
/** /**
* A bitwise exclusive-or assignment operation, for example `x ^= y`. * A bitwise exclusive-or assignment expression, for example `x ^= y`.
*/ */
class AssignXorExpr extends AssignBitwiseOperation, BitwiseXorOperation, @assign_xor_expr { class AssignXorExpr extends AssignBitwiseExpr, BitwiseXorOperation, @assign_xor_expr {
override string getOperator() { result = "^=" } override string getOperator() { result = "^=" }
override string getAPrimaryQlClass() { result = "AssignXorExpr" } override string getAPrimaryQlClass() { result = "AssignXorExpr" }
} }
/** /**
* A left-shift assignment operation, for example `x <<= y`. * A left-shift assignment expression, for example `x <<= y`.
*/ */
class AssignLeftShiftExpr extends AssignBitwiseOperation, LeftShiftOperation, @assign_lshift_expr { class AssignLeftShiftExpr extends AssignBitwiseExpr, LeftShiftOperation, @assign_lshift_expr {
override string getOperator() { result = "<<=" } override string getOperator() { result = "<<=" }
override string getAPrimaryQlClass() { result = "AssignLeftShiftExpr" } override string getAPrimaryQlClass() { result = "AssignLeftShiftExpr" }
} }
/** /**
* A right-shift assignment operation, for example `x >>= y`. * A right-shift assignment expression, for example `x >>= y`.
*/ */
class AssignRightShiftExpr extends AssignBitwiseOperation, RightShiftOperation, @assign_rshift_expr { class AssignRightShiftExpr extends AssignBitwiseExpr, RightShiftOperation, @assign_rshift_expr {
override string getOperator() { result = ">>=" } override string getOperator() { result = ">>=" }
override string getAPrimaryQlClass() { result = "AssignRightShiftExpr" } override string getAPrimaryQlClass() { result = "AssignRightShiftExpr" }
} }
/** /**
* An unsigned right-shift assignment operation, for example `x >>>= y`. * An unsigned right-shift assignment expression, for example `x >>>= y`.
*/ */
class AssignUnsignedRightShiftExpr extends AssignBitwiseOperation, UnsignedRightShiftOperation, class AssignUnsignedRightShiftExpr extends AssignBitwiseExpr, UnsignedRightShiftOperation,
@assign_urshift_expr @assign_urshift_expr
{ {
override string getOperator() { result = ">>>=" } override string getOperator() { result = ">>>=" }
@@ -297,10 +310,10 @@ class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
} }
/** /**
* A null-coalescing assignment operation, for example `x ??= y`. * A null-coalescing assignment expression, for example `x ??= y`.
*/ */
class AssignCoalesceExpr extends AssignOperation, NullCoalescingOperation, @assign_coalesce_expr { class AssignCoalesceExpr extends AssignOperation, NullCoalescingOperation, @assign_coalesce_expr {
override string toString() { result = "... ??= ..." } override string getOperator() { result = "??=" }
override string getAPrimaryQlClass() { result = "AssignCoalesceExpr" } override string getAPrimaryQlClass() { result = "AssignCoalesceExpr" }
} }

View File

@@ -10,16 +10,16 @@ import Expr
* A bitwise operation. Either a unary bitwise operation (`UnaryBitwiseOperation`) * A bitwise operation. Either a unary bitwise operation (`UnaryBitwiseOperation`)
* or a binary bitwise operation (`BinaryBitwiseOperation`). * or a binary bitwise operation (`BinaryBitwiseOperation`).
*/ */
class BitwiseOperation extends Operation, @bit_expr { } class BitwiseOperation extends Operation, @bit_operation { }
/** /**
* A unary bitwise operation, that is, a bitwise complement operation * A unary bitwise operation, that is, a bitwise complement operation
* (`ComplementExpr`). * (`ComplementExpr`).
*/ */
class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_op_expr { } class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_operation { }
/** /**
* A bitwise complement operation, for example `~x`. * A bitwise complement expression, for example `~x`.
*/ */
class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr { class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
override string getOperator() { result = "~" } override string getOperator() { result = "~" }
@@ -28,67 +28,101 @@ class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
} }
/** /**
* A binary bitwise operation. Either a bitwise-and operation * A binary bitwise operation. Either a binary bitwise expression (`BinaryBitwiseExpr`) or
* (`BitwiseAndExpr`), a bitwise-or operation (`BitwiseOrExpr`), * a bitwise assignment expression (`AssignBitwiseExpr`).
* a bitwise exclusive-or operation (`BitwiseXorExpr`), a left-shift
* operation (`LeftShiftExpr`), a right-shift operation (`RightShiftExpr`),
* or an unsigned right-shift operation (`UnsignedRightShiftExpr`).
*/ */
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_op_expr { class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_operation {
override string getOperator() { none() } override string getOperator() { none() }
} }
/** /**
* A left-shift operation, for example `x << y`. * A bitwise-and operation, either `x & y` or `x &= y`.
*/ */
class LeftShiftExpr extends BinaryBitwiseOperation, LeftShiftOperation, @lshift_expr { class BitwiseAndOperation extends BinaryBitwiseOperation, @and_operation { }
/**
* A bitwise-or operation, either `x | y` or `x |= y`.
*/
class BitwiseOrOperation extends BinaryBitwiseOperation, @or_operation { }
/**
* A bitwise exclusive-or operation, either `x ^ y` or `x ^= y`.
*/
class BitwiseXorOperation extends BinaryBitwiseOperation, @xor_operation { }
/**
* A left-shift operation, either `x << y` or `x <<= y`.
*/
class LeftShiftOperation extends BinaryBitwiseOperation, @lshift_operation { }
/**
* A right-shift operation, either `x >> y` or `x >>= y`.
*/
class RightShiftOperation extends BinaryBitwiseOperation, @rshift_operation { }
/**
* An unsigned right-shift operation, either `x >>> y` or `x >>>= y`.
*/
class UnsignedRightShiftOperation extends BinaryBitwiseOperation, @urshift_operation { }
/**
* A binary bitwise expression. Either a bitwise-and expression
* (`BitwiseAndExpr`), a bitwise-or expression (`BitwiseOrExpr`),
* a bitwise exclusive-or expression (`BitwiseXorExpr`), a left-shift
* expression (`LeftShiftExpr`), a right-shift expression (`RightShiftExpr`),
* or an unsigned right-shift expression (`UnsignedRightShiftExpr`).
*/
class BinaryBitwiseExpr extends BinaryBitwiseOperation, @bin_bit_expr { }
/**
* A left-shift expression, for example `x << y`.
*/
class LeftShiftExpr extends BinaryBitwiseExpr, LeftShiftOperation, @lshift_expr {
override string getOperator() { result = "<<" } override string getOperator() { result = "<<" }
override string getAPrimaryQlClass() { result = "LeftShiftExpr" } override string getAPrimaryQlClass() { result = "LeftShiftExpr" }
} }
/** /**
* A right-shift operation, for example `x >> y`. * A right-shift expression, for example `x >> y`.
*/ */
class RightShiftExpr extends BinaryBitwiseOperation, RightShiftOperation, @rshift_expr { class RightShiftExpr extends BinaryBitwiseExpr, RightShiftOperation, @rshift_expr {
override string getOperator() { result = ">>" } override string getOperator() { result = ">>" }
override string getAPrimaryQlClass() { result = "RightShiftExpr" } override string getAPrimaryQlClass() { result = "RightShiftExpr" }
} }
/** /**
* An unsigned right-shift operation, for example `x >>> y`. * An unsigned right-shift expression, for example `x >>> y`.
*/ */
class UnsignedRightShiftExpr extends BinaryBitwiseOperation, UnsignedRightShiftOperation, class UnsignedRightShiftExpr extends BinaryBitwiseExpr, UnsignedRightShiftOperation, @urshift_expr {
@urshift_expr
{
override string getOperator() { result = ">>>" } override string getOperator() { result = ">>>" }
override string getAPrimaryQlClass() { result = "UnsignedRightShiftExpr" } override string getAPrimaryQlClass() { result = "UnsignedRightShiftExpr" }
} }
/** /**
* A bitwise-and operation, for example `x & y`. * A bitwise-and expression, for example `x & y`.
*/ */
class BitwiseAndExpr extends BinaryBitwiseOperation, BitwiseAndOperation, @bit_and_expr { class BitwiseAndExpr extends BinaryBitwiseExpr, BitwiseAndOperation, @bit_and_expr {
override string getOperator() { result = "&" } override string getOperator() { result = "&" }
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" } override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
} }
/** /**
* A bitwise-or operation, for example `x | y`. * A bitwise-or expression, for example `x | y`.
*/ */
class BitwiseOrExpr extends BinaryBitwiseOperation, BitwiseOrOperation, @bit_or_expr { class BitwiseOrExpr extends BinaryBitwiseExpr, BitwiseOrOperation, @bit_or_expr {
override string getOperator() { result = "|" } override string getOperator() { result = "|" }
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" } override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
} }
/** /**
* A bitwise exclusive-or operation, for example `x ^ y`. * A bitwise exclusive-or expression, for example `x ^ y`.
*/ */
class BitwiseXorExpr extends BinaryBitwiseOperation, BitwiseXorOperation, @bit_xor_expr { class BitwiseXorExpr extends BinaryBitwiseExpr, BitwiseXorOperation, @bit_xor_expr {
override string getOperator() { result = "^" } override string getOperator() { result = "^" }
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" } override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }

View File

@@ -609,7 +609,7 @@ class InstanceMutatorOperatorCall extends MutatorOperatorCall {
* } * }
* ``` * ```
*/ */
class CompoundAssignmentOperatorCall extends AssignCallOperation { class CompoundAssignmentOperatorCall extends AssignCallExpr {
CompoundAssignmentOperatorCall() { this.getTarget() instanceof CompoundAssignmentOperator } CompoundAssignmentOperatorCall() { this.getTarget() instanceof CompoundAssignmentOperator }
override Expr getArgument(int i) { result = this.getChildExpr(i + 1) and i >= 0 } override Expr getArgument(int i) { result = this.getChildExpr(i + 1) and i >= 0 }

View File

@@ -14,7 +14,6 @@ import Creation
import Dynamic import Dynamic
import Literal import Literal
import LogicalOperation import LogicalOperation
import Operation
import semmle.code.csharp.controlflow.ControlFlowElement import semmle.code.csharp.controlflow.ControlFlowElement
import semmle.code.csharp.Location import semmle.code.csharp.Location
import semmle.code.csharp.Stmt import semmle.code.csharp.Stmt
@@ -212,7 +211,7 @@ class LocalConstantDeclExpr extends LocalVariableDeclExpr {
* (`UnaryOperation`), a binary operation (`BinaryOperation`), or a * (`UnaryOperation`), a binary operation (`BinaryOperation`), or a
* ternary operation (`TernaryOperation`). * ternary operation (`TernaryOperation`).
*/ */
class Operation extends Expr, @op_expr { class Operation extends Expr, @operation_expr {
/** Gets the name of the operator in this operation. */ /** Gets the name of the operator in this operation. */
string getOperator() { none() } string getOperator() { none() }
@@ -227,7 +226,7 @@ class Operation extends Expr, @op_expr {
* indirection operation (`PointerIndirectionExpr`), an address-of operation * indirection operation (`PointerIndirectionExpr`), an address-of operation
* (`AddressOfExpr`), or a unary logical operation (`UnaryLogicalOperation`). * (`AddressOfExpr`), or a unary logical operation (`UnaryLogicalOperation`).
*/ */
class UnaryOperation extends Operation, @un_op { class UnaryOperation extends Operation, @un_operation {
/** Gets the operand of this unary operation. */ /** Gets the operand of this unary operation. */
Expr getOperand() { result = this.getChild(0) } Expr getOperand() { result = this.getChild(0) }
@@ -241,7 +240,7 @@ class UnaryOperation extends Operation, @un_op {
* a binary logical operation (`BinaryLogicalOperation`), or an * a binary logical operation (`BinaryLogicalOperation`), or an
* assignment (`Assignment`). * assignment (`Assignment`).
*/ */
class BinaryOperation extends Operation, @bin_op { class BinaryOperation extends Operation, @bin_operation {
/** Gets the left operand of this binary operation. */ /** Gets the left operand of this binary operation. */
Expr getLeftOperand() { result = this.getChild(0) } Expr getLeftOperand() { result = this.getChild(0) }
@@ -264,7 +263,7 @@ class BinaryOperation extends Operation, @bin_op {
* A ternary operation, that is, a ternary conditional operation * A ternary operation, that is, a ternary conditional operation
* (`ConditionalExpr`). * (`ConditionalExpr`).
*/ */
class TernaryOperation extends Operation, @ternary_op { } class TernaryOperation extends Operation, @ternary_operation { }
/** /**
* A parenthesized expression, for example `(2 + 3)` in * A parenthesized expression, for example `(2 + 3)` in

View File

@@ -11,14 +11,14 @@ import Expr
* a binary logical operation (`BinaryLogicalOperation`), or a ternary logical * a binary logical operation (`BinaryLogicalOperation`), or a ternary logical
* operation (`TernaryLogicalOperation`). * operation (`TernaryLogicalOperation`).
*/ */
class LogicalOperation extends Operation, @log_expr { class LogicalOperation extends Operation, @log_operation {
override string getOperator() { none() } override string getOperator() { none() }
} }
/** /**
* A unary logical operation, that is, a logical 'not' (`LogicalNotExpr`). * A unary logical operation, that is, a logical 'not' (`LogicalNotExpr`).
*/ */
class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_op_expr { } class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_operation { }
/** /**
* A logical 'not', for example `!String.IsNullOrEmpty(s)`. * A logical 'not', for example `!String.IsNullOrEmpty(s)`.
@@ -31,10 +31,10 @@ class LogicalNotExpr extends UnaryLogicalOperation, @log_not_expr {
/** /**
* A binary logical operation. Either a logical 'and' (`LogicalAndExpr`), * A binary logical operation. Either a logical 'and' (`LogicalAndExpr`),
* a logical 'or' (`LogicalAndExpr`), or a null-coalescing operation * a logical 'or' (`LogicalOrExpr`), or a null-coalescing operation
* (`NullCoalescingExpr`). * (`NullCoalescingOperation`).
*/ */
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_op_expr { class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_operation {
override string getOperator() { none() } override string getOperator() { none() }
} }
@@ -57,7 +57,12 @@ class LogicalOrExpr extends BinaryLogicalOperation, @log_or_expr {
} }
/** /**
* A null-coalescing operation, for example `s ?? ""` on line 2 in * A null-coalescing operation, either `x ?? y` or `x ??= y`.
*/
class NullCoalescingOperation extends BinaryLogicalOperation, @null_coalescing_operation { }
/**
* A null-coalescing expression, for example `s ?? ""` on line 2 in
* *
* ```csharp * ```csharp
* string NonNullOrEmpty(string s) { * string NonNullOrEmpty(string s) {
@@ -65,9 +70,7 @@ class LogicalOrExpr extends BinaryLogicalOperation, @log_or_expr {
* } * }
* ``` * ```
*/ */
class NullCoalescingExpr extends BinaryLogicalOperation, NullCoalescingOperation, class NullCoalescingExpr extends NullCoalescingOperation, @null_coalescing_expr {
@null_coalescing_expr
{
override string getOperator() { result = "??" } override string getOperator() { result = "??" }
override string getAPrimaryQlClass() { result = "NullCoalescingExpr" } override string getAPrimaryQlClass() { result = "NullCoalescingExpr" }
@@ -77,7 +80,7 @@ class NullCoalescingExpr extends BinaryLogicalOperation, NullCoalescingOperation
* A ternary logical operation, that is, a ternary conditional expression * A ternary logical operation, that is, a ternary conditional expression
* (`ConditionalExpr`). * (`ConditionalExpr`).
*/ */
class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_op_expr { } class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_operation { }
/** /**
* A conditional expression, for example `s != null ? s.Length : -1` * A conditional expression, for example `s != null ? s.Length : -1`

View File

@@ -1,71 +1,6 @@
/** /**
* Provides classes for operations that also have compound assignment forms. * Provides classes for operations that also have compound assignment forms.
*/ */
deprecated module;
import Expr import Expr
/**
* An addition operation, either `x + y` or `x += y`.
*/
class AddOperation extends BinaryOperation, @add_operation { }
/**
* A subtraction operation, either `x - y` or `x -= y`.
*/
class SubOperation extends BinaryOperation, @sub_operation { }
/**
* A multiplication operation, either `x * y` or `x *= y`.
*/
class MulOperation extends BinaryOperation, @mul_operation { }
/**
* A division operation, either `x / y` or `x /= y`.
*/
class DivOperation extends BinaryOperation, @div_operation {
/** Gets the numerator of this division operation. */
Expr getNumerator() { result = this.getLeftOperand() }
/** Gets the denominator of this division operation. */
Expr getDenominator() { result = this.getRightOperand() }
}
/**
* A remainder operation, either `x % y` or `x %= y`.
*/
class RemOperation extends BinaryOperation, @rem_operation { }
/**
* A bitwise-and operation, either `x & y` or `x &= y`.
*/
class BitwiseAndOperation extends BinaryOperation, @and_operation { }
/**
* A bitwise-or operation, either `x | y` or `x |= y`.
*/
class BitwiseOrOperation extends BinaryOperation, @or_operation { }
/**
* A bitwise exclusive-or operation, either `x ^ y` or `x ^= y`.
*/
class BitwiseXorOperation extends BinaryOperation, @xor_operation { }
/**
* A left-shift operation, either `x << y` or `x <<= y`.
*/
class LeftShiftOperation extends BinaryOperation, @lshift_operation { }
/**
* A right-shift operation, either `x >> y` or `x >>= y`.
*/
class RightShiftOperation extends BinaryOperation, @rshift_operation { }
/**
* An unsigned right-shift operation, either `x >>> y` or `x >>>= y`.
*/
class UnsignedRightShiftOperation extends BinaryOperation, @urshift_operation { }
/**
* A null-coalescing operation, either `x ?? y` or `x ??= y`.
*/
class NullCoalescingOperation extends BinaryOperation, @null_coalescing_operation { }

View File

@@ -1254,32 +1254,38 @@ case @expr.kind of
@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; @delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; @bin_arith_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
@incr_op_expr = @pre_incr_expr | @post_incr_expr; @bin_arith_operation = @mul_operation | @div_operation | @rem_operation | @add_operation | @sub_operation;
@decr_op_expr = @pre_decr_expr | @post_decr_expr;
@mut_op_expr = @incr_op_expr | @decr_op_expr;
@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
@ternary_log_op_expr = @conditional_expr; @incr_operation = @pre_incr_expr | @post_incr_expr;
@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; @decr_operation = @pre_decr_expr | @post_decr_expr;
@un_log_op_expr = @log_not_expr; @mut_operation = @incr_operation | @decr_operation;
@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; @un_arith_operation = @plus_expr | @minus_expr | @mut_operation;
@arith_operation = @bin_arith_operation | @un_arith_operation;
@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr @ternary_log_operation = @conditional_expr;
@bin_log_operation = @log_and_expr | @log_or_expr | @null_coalescing_operation;
@un_log_operation = @log_not_expr;
@log_operation = @un_log_operation | @bin_log_operation | @ternary_log_operation;
@bin_bit_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
| @rshift_expr | @urshift_expr; | @rshift_expr | @urshift_expr;
@un_bit_op_expr = @bit_not_expr; @bin_bit_operation = @and_operation | @or_operation | @xor_operation | @lshift_operation
@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; | @rshift_operation | @urshift_operation;
@un_bit_expr = @bit_not_expr;
@un_bit_operation = @un_bit_expr;
@bit_expr = @un_bit_expr | @bin_bit_expr;
@bit_operation = @un_bit_operation | @bin_bit_operation;
@equality_op_expr = @eq_expr | @ne_expr; @equality_op_expr = @eq_expr | @ne_expr;
@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; @rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
@comp_expr = @equality_op_expr | @rel_op_expr; @comp_expr = @equality_op_expr | @rel_op_expr;
@op_expr = @un_op | @bin_op | @ternary_op; @operation_expr = @un_operation | @bin_operation | @ternary_operation;
@ternary_op = @ternary_log_op_expr; @ternary_operation = @ternary_log_operation;
@bin_op = @assign_expr | @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; @bin_operation = @assign_expr | @bin_arith_operation | @bin_log_operation | @bin_bit_operation | @comp_expr;
@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr @un_operation = @un_arith_operation | @un_log_operation | @un_bit_operation | @sizeof_expr
| @pointer_indirection_expr | @address_of_expr; | @pointer_indirection_expr | @address_of_expr;
@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; @anonymous_function_expr = @lambda_expr | @anonymous_method_expr;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Restructure and rename types related to operations.
compatibility: full

View File

@@ -1,6 +1,7 @@
binarybitwise binarybitwise
| Operators.cs:7:18:7:25 | ... >>> ... | Operators.cs:7:18:7:19 | access to local variable x1 | Operators.cs:7:25:7:25 | 2 | >>> | UnsignedRightShiftExpr | | Operators.cs:7:18:7:25 | ... >>> ... | Operators.cs:7:18:7:19 | access to local variable x1 | Operators.cs:7:25:7:25 | 2 | >>> | UnsignedRightShiftExpr |
| Operators.cs:10:18:10:25 | ... >>> ... | Operators.cs:10:18:10:19 | access to local variable y1 | Operators.cs:10:25:10:25 | 3 | >>> | UnsignedRightShiftExpr | | Operators.cs:10:18:10:25 | ... >>> ... | Operators.cs:10:18:10:19 | access to local variable y1 | Operators.cs:10:25:10:25 | 3 | >>> | UnsignedRightShiftExpr |
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
assignbitwise assignbitwise
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr | | Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
userdefined userdefined

View File

@@ -11,7 +11,7 @@ query predicate binarybitwise(
} }
query predicate assignbitwise( query predicate assignbitwise(
AssignBitwiseOperation op, Expr left, Expr right, string name, string qlclass AssignBitwiseExpr op, Expr left, Expr right, string name, string qlclass
) { ) {
op.getFile().getStem() = "Operators" and op.getFile().getStem() = "Operators" and
left = op.getLeftOperand() and left = op.getLeftOperand() and

View File

@@ -10,7 +10,7 @@ toolchain go1.26.4
// bazel mod tidy // bazel mod tidy
require ( require (
golang.org/x/mod v0.37.0 golang.org/x/mod v0.37.0
golang.org/x/tools v0.45.0 golang.org/x/tools v0.46.0
) )
require github.com/stretchr/testify v1.11.1 require github.com/stretchr/testify v1.11.1
@@ -18,6 +18,6 @@ require github.com/stretchr/testify v1.11.1
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@@ -8,10 +8,10 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= 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/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.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk=
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@@ -1,4 +1,4 @@
/* /**
* @name Web Cache Deception * @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. * @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 * @kind problem

View File

@@ -54,31 +54,31 @@ func main() {}
// bad is an example of a bad implementation // bad is an example of a bad implementation
func (ld *Ldap) bad(req *http.Request) { func (ld *Ldap) bad(req *http.Request) {
// ... // ...
untrusted := req.UserAgent() untrusted := req.UserAgent() // $ Source
goldap.NewSearchRequest( goldap.NewSearchRequest(
untrusted, // BAD: untrusted dn untrusted, // $ Alert // BAD: untrusted dn
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter "(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute []string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
nil, nil,
) )
goldapv3.NewSearchRequest( goldapv3.NewSearchRequest(
untrusted, // BAD: untrusted dn untrusted, // $ Alert // BAD: untrusted dn
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter "(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute []string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
nil, nil,
) )
gopkgldapv2.NewSearchRequest( gopkgldapv2.NewSearchRequest(
untrusted, // BAD: untrusted dn untrusted, // $ Alert // BAD: untrusted dn
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter "(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute []string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
nil, nil,
) )
client := &ldapclient.LDAPClient{} client := &ldapclient.LDAPClient{}
client.Authenticate(untrusted, "123456") // BAD: untrusted filter client.Authenticate(untrusted, "123456") // $ Alert // BAD: untrusted filter
client.GetGroupsOfUser(untrusted) // BAD: untrusted filter client.GetGroupsOfUser(untrusted) // $ Alert // BAD: untrusted filter
// ... // ...
} }

View File

@@ -1,2 +1,4 @@
query: experimental/CWE-090/LDAPInjection.ql query: experimental/CWE-090/LDAPInjection.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1,4 @@
query: experimental/CWE-203/Timing.ql query: experimental/CWE-203/Timing.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -12,9 +12,9 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
secret := "MySuperSecretPasscode" secret := "MySuperSecretPasscode"
secretHeader := "X-Secret" secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader) headerSecret := req.Header.Get(secretHeader) // $ Source
secretStr := string(secret) 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, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
} }
return nil, nil return nil, nil
@@ -25,9 +25,9 @@ func bad2(w http.ResponseWriter, req *http.Request) (interface{}, error) {
secret := "MySuperSecretPasscode" secret := "MySuperSecretPasscode"
secretHeader := "X-Secret" secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader) headerSecret := req.Header.Get(secretHeader) // $ Source
secretStr := string(secret) 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, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
} }
return nil, nil return nil, nil
@@ -38,8 +38,8 @@ func bad4(w http.ResponseWriter, req *http.Request) (interface{}, error) {
secret := "MySuperSecretPasscode" secret := "MySuperSecretPasscode"
secretHeader := "X-Secret" secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader) headerSecret := req.Header.Get(secretHeader) // $ Source
if len(secret) != 0 && headerSecret != "SecretStringLiteral" { if len(secret) != 0 && headerSecret != "SecretStringLiteral" { // $ Alert
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret) return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
} }
return nil, nil return nil, nil

View File

@@ -1 +1,2 @@
experimental/CWE-285/PamAuthBypass.ql query: experimental/CWE-285/PamAuthBypass.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -9,7 +9,7 @@ import (
func bad() error { func bad() error {
t, _ := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) { t, _ := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) {
return "", nil return "", nil
}) }) // $ Alert
return t.Authenticate(0) return t.Authenticate(0)
} }

View File

@@ -15,7 +15,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
ldapServer := "ldap.example.com" ldapServer := "ldap.example.com"
ldapPort := 389 ldapPort := 389
bindDN := "cn=admin,dc=example,dc=com" 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 // Connect to the LDAP server
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) 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() defer l.Close()
// BAD: user input is not sanetized // BAD: user input is not sanetized
err = l.Bind(bindDN, bindPassword) err = l.Bind(bindDN, bindPassword) // $ Alert
if err != nil { if err != nil {
return fmt.Errorf("LDAP bind failed: %v", err), err return fmt.Errorf("LDAP bind failed: %v", err), err
} }
@@ -84,7 +84,7 @@ func bad2(req *http.Request) {
ldapPort := 389 ldapPort := 389
bindDN := "cn=admin,dc=example,dc=com" bindDN := "cn=admin,dc=example,dc=com"
// BAD : empty password // BAD : empty password
bindPassword := "" bindPassword := "" // $ Source
// Connect to the LDAP server // Connect to the LDAP server
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
@@ -94,7 +94,7 @@ func bad2(req *http.Request) {
defer l.Close() defer l.Close()
// BAD : bindPassword is empty // BAD : bindPassword is empty
err = l.Bind(bindDN, bindPassword) err = l.Bind(bindDN, bindPassword) // $ Alert
if err != nil { if err != nil {
log.Fatalf("LDAP bind failed: %v", err) log.Fatalf("LDAP bind failed: %v", err)
} }

View File

@@ -1,2 +1,4 @@
query: experimental/CWE-287/ImproperLdapAuth.ql query: experimental/CWE-287/ImproperLdapAuth.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -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 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: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 | | | 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:19:22:19:34 | "AllYourBase" | semmle.label | "AllYourBase" |
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | semmle.label | JwtKey1 | | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | semmle.label | JwtKey1 |
subpaths 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 |

View File

@@ -1 +1,2 @@
experimental/CWE-321-V2/HardCodedKeys.ql query: experimental/CWE-321-V2/HardCodedKeys.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -10,7 +10,7 @@ import (
) )
// NOT OK // NOT OK
var JwtKey = []byte("AllYourBase") var JwtKey = []byte("AllYourBase") // $ Source
func main2(r *http.Request) { func main2(r *http.Request) {
signedToken := r.URL.Query().Get("signedToken") signedToken := r.URL.Query().Get("signedToken")
@@ -21,7 +21,7 @@ func verifyJWT(signedToken string) {
fmt.Println("verifying JWT") fmt.Println("verifying JWT")
DecodedToken, _ := jwt.ParseSigned(signedToken) DecodedToken, _ := jwt.ParseSigned(signedToken)
out := CustomerInfo{} out := CustomerInfo{}
if err := DecodedToken.Claims(JwtKey, &out); err != nil { if err := DecodedToken.Claims(JwtKey, &out); err != nil { // $ Alert
panic(err) panic(err)
} }
fmt.Printf("%v\n", out) fmt.Printf("%v\n", out)

View File

@@ -16,7 +16,7 @@ type CustomerInfo struct {
} }
// BAD constant key // BAD constant key
var JwtKey1 = []byte("AllYourBase") var JwtKey1 = []byte("AllYourBase") // $ Source
func main1(r *http.Request) { func main1(r *http.Request) {
signedToken := r.URL.Query().Get("signedToken") signedToken := r.URL.Query().Get("signedToken")
@@ -24,7 +24,7 @@ func main1(r *http.Request) {
} }
func LoadJwtKey(token *jwt.Token) (interface{}, error) { func LoadJwtKey(token *jwt.Token) (interface{}, error) {
return JwtKey1, nil return JwtKey1, nil // $ Alert
} }
func verifyJWT_golangjwt(signedToken string) { func verifyJWT_golangjwt(signedToken string) {

View File

@@ -7,37 +7,37 @@ import (
) )
func myHandler1(w http.ResponseWriter, r *http.Request) { 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) value, _ := strconv.Atoi(param1)
out := 1337 / value out := 1337 / value // $ Alert
fmt.Println(out) fmt.Println(out)
} }
func myHandler2(w http.ResponseWriter, r *http.Request) { 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]) value := int(param1[0])
out := 1337 / value out := 1337 / value // $ Alert
fmt.Println(out) fmt.Println(out)
} }
func myHandler3(w http.ResponseWriter, r *http.Request) { 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) value, _ := strconv.ParseInt(param1, 10, 64)
out := 1337 / value out := 1337 / value // $ Alert
fmt.Println(out) fmt.Println(out)
} }
func myHandler4(w http.ResponseWriter, r *http.Request) { 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) value, _ := strconv.ParseFloat(param1, 32)
out := 1337 / value out := 1337 / value // $ Alert
fmt.Println(out) fmt.Println(out)
} }
func myHandler5(w http.ResponseWriter, r *http.Request) { 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) value, _ := strconv.ParseUint(param1, 10, 64)
out := 1337 / value out := 1337 / value // $ Alert
fmt.Println(out) fmt.Println(out)
} }
@@ -51,10 +51,10 @@ func myHandler6(w http.ResponseWriter, r *http.Request) {
} }
func myHandler7(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]) value := int(param1[0])
if value >= 0 { if value >= 0 {
out := 1337 / value out := 1337 / value // $ Alert
fmt.Println(out) fmt.Println(out)
} }
} }

View File

@@ -1,2 +1,4 @@
query: experimental/CWE-369/DivideByZero.ql query: experimental/CWE-369/DivideByZero.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -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 edges
| DatabaseCallInLoop.go:7:2:11:2 | range statement | 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 |
| test.go:10:1:12:1 | function declaration | test.go:11:2:11:13 | call to Take | | 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: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: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 | | 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 |

View File

@@ -6,8 +6,8 @@ func getUsers(db *gorm.DB, names []string) []User {
res := make([]User, 0, len(names)) res := make([]User, 0, len(names))
for _, name := range names { for _, name := range names {
var user User var user User
db.Where("name = ?", name).First(&user) db.Where("name = ?", name).First(&user) // $ Alert
res = append(res, user) res = append(res, user)
} } // $ Source
return res return res
} }

View File

@@ -1 +1,2 @@
experimental/CWE-400/DatabaseCallInLoop.ql query: experimental/CWE-400/DatabaseCallInLoop.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -8,7 +8,7 @@ type User struct {
} }
func runQuery(db *gorm.DB) { func runQuery(db *gorm.DB) {
db.Take(nil) db.Take(nil) // $ Alert
} }
func runRunQuery(db *gorm.DB) { func runRunQuery(db *gorm.DB) {
@@ -19,9 +19,9 @@ func main() {
var db *gorm.DB var db *gorm.DB
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
runQuery(db) runQuery(db)
} } // $ Source
for i := 10; i > 0; i-- { for i := 10; i > 0; i-- {
runRunQuery(db) runRunQuery(db)
} } // $ Source
} }

View File

@@ -1,2 +1,4 @@
query: experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql query: experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -56,41 +56,41 @@ func main() {
func DecompressHandler(w http.ResponseWriter, request *http.Request) { func DecompressHandler(w http.ResponseWriter, request *http.Request) {
GZipOpenReaderSafe(request.PostFormValue("test")) GZipOpenReaderSafe(request.PostFormValue("test"))
ZipOpenReaderSafe(request.PostFormValue("test")) ZipOpenReaderSafe(request.PostFormValue("test"))
ZipOpenReader(request.FormValue("filepath")) ZipOpenReader(request.FormValue("filepath")) // $ Source
ZipNewReader(request.Body) ZipNewReader(request.Body) // $ Source
ZipNewReaderKlauspost(request.Body) ZipNewReaderKlauspost(request.Body) // $ Source
Bzip2Dsnet(request.Body) Bzip2Dsnet(request.Body) // $ Source
Bzip2DsnetSafe(request.Body) Bzip2DsnetSafe(request.Body)
Bzip2(request.Body) Bzip2(request.Body) // $ Source
Bzip2Safe(request.Body) Bzip2Safe(request.Body)
Flate(request.Body) Flate(request.Body) // $ Source
FlateSafe(request.Body) FlateSafe(request.Body)
FlateKlauspost(request.Body) FlateKlauspost(request.Body) // $ Source
FlateKlauspostSafe(request.Body) FlateKlauspostSafe(request.Body)
FlateDsnet(request.Body) FlateDsnet(request.Body) // $ Source
FlateDsnetSafe(request.Body) FlateDsnetSafe(request.Body)
ZlibKlauspost(request.Body) ZlibKlauspost(request.Body) // $ Source
ZlibKlauspostSafe(request.Body) ZlibKlauspostSafe(request.Body)
Zlib(request.Body) Zlib(request.Body) // $ Source
ZlibSafe(request.Body) ZlibSafe(request.Body)
Snappy(request.Body) Snappy(request.Body) // $ Source
SnappySafe(request.Body) SnappySafe(request.Body)
SnappyKlauspost(request.Body) SnappyKlauspost(request.Body) // $ Source
SnappyKlauspostSafe(request.Body) SnappyKlauspostSafe(request.Body)
S2(request.Body) S2(request.Body) // $ Source
S2Safe(request.Body) S2Safe(request.Body)
Gzip(request.Body) Gzip(request.Body) // $ Source
GzipSafe(request.Body) GzipSafe(request.Body)
GZipIoReader(request.Body, "dest") GZipIoReader(request.Body, "dest") // $ Source
GzipKlauspost(request.Body) GzipKlauspost(request.Body) // $ Source
GzipKlauspostSafe(request.Body) GzipKlauspostSafe(request.Body)
PzipKlauspost(request.Body) PzipKlauspost(request.Body) // $ Source
PzipKlauspostSafe(request.Body) PzipKlauspostSafe(request.Body)
Zstd_Klauspost(request.Body) Zstd_Klauspost(request.Body) // $ Source
Zstd_KlauspostSafe(request.Body) Zstd_KlauspostSafe(request.Body)
Zstd_DataDog(request.Body) Zstd_DataDog(request.Body) // $ Source
Zstd_DataDogSafe(request.Body) Zstd_DataDogSafe(request.Body)
Xz(request.Body) Xz(request.Body) // $ Source
XzSafe(request.Body) XzSafe(request.Body)
} }
@@ -131,7 +131,7 @@ func ZipOpenReader(filename string) {
for _, f := range zipReader.File { for _, f := range zipReader.File {
rc, _ := f.Open() rc, _ := f.Open()
for { for {
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert
if result == 0 { if result == 0 {
_ = rc.Close() _ = rc.Close()
break break
@@ -144,7 +144,7 @@ func ZipOpenReader(filename string) {
for _, f := range zipKlauspostReader.File { for _, f := range zipKlauspostReader.File {
rc, _ := f.Open() rc, _ := f.Open()
for { for {
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert
if result == 0 { if result == 0 {
_ = rc.Close() _ = rc.Close()
break break
@@ -161,7 +161,7 @@ func ZipNewReader(file io.Reader) {
for _, file := range zipReader.File { for _, file := range zipReader.File {
fileWriter := bytes.NewBuffer([]byte{}) fileWriter := bytes.NewBuffer([]byte{})
fileReaderCloser, _ := file.Open() fileReaderCloser, _ := file.Open()
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert
fmt.Print(result) fmt.Print(result)
} }
} }
@@ -173,7 +173,7 @@ func ZipNewReaderKlauspost(file io.Reader) {
fileWriter := bytes.NewBuffer([]byte{}) fileWriter := bytes.NewBuffer([]byte{})
// file.OpenRaw() // file.OpenRaw()
fileReaderCloser, _ := file.Open() fileReaderCloser, _ := file.Open()
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert
fmt.Print(result) fmt.Print(result)
} }
} }
@@ -183,7 +183,7 @@ func Bzip2Dsnet(file io.Reader) {
bzip2Reader, _ := bzip2Dsnet.NewReader(file, &bzip2Dsnet.ReaderConfig{}) bzip2Reader, _ := bzip2Dsnet.NewReader(file, &bzip2Dsnet.ReaderConfig{})
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert
tarRead = tar.NewReader(bzip2Reader) tarRead = tar.NewReader(bzip2Reader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -210,7 +210,7 @@ func Bzip2(file io.Reader) {
bzip2Reader := bzip2.NewReader(file) bzip2Reader := bzip2.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert
tarRead = tar.NewReader(bzip2Reader) tarRead = tar.NewReader(bzip2Reader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -235,7 +235,7 @@ func Flate(file io.Reader) {
flateReader := flate.NewReader(file) flateReader := flate.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
flateReader.Read(out) // $ hasValueFlow="flateReader" flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
tarRead = tar.NewReader(flateReader) tarRead = tar.NewReader(flateReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -260,7 +260,7 @@ func FlateKlauspost(file io.Reader) {
flateReader := flateKlauspost.NewReader(file) flateReader := flateKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
flateReader.Read(out) // $ hasValueFlow="flateReader" flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
tarRead = tar.NewReader(flateReader) tarRead = tar.NewReader(flateReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -285,7 +285,7 @@ func FlateDsnet(file io.Reader) {
flateReader, _ := flateDsnet.NewReader(file, &flateDsnet.ReaderConfig{}) flateReader, _ := flateDsnet.NewReader(file, &flateDsnet.ReaderConfig{})
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
flateReader.Read(out) // $ hasValueFlow="flateReader" flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
tarRead = tar.NewReader(flateReader) tarRead = tar.NewReader(flateReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -310,7 +310,7 @@ func ZlibKlauspost(file io.Reader) {
zlibReader, _ := zlibKlauspost.NewReader(file) zlibReader, _ := zlibKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
zlibReader.Read(out) // $ hasValueFlow="zlibReader" zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert
tarRead = tar.NewReader(zlibReader) tarRead = tar.NewReader(zlibReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -335,7 +335,7 @@ func Zlib(file io.Reader) {
zlibReader, _ := zlib.NewReader(file) zlibReader, _ := zlib.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
zlibReader.Read(out) // $ hasValueFlow="zlibReader" zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert
tarRead = tar.NewReader(zlibReader) tarRead = tar.NewReader(zlibReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -360,8 +360,8 @@ func Snappy(file io.Reader) {
snappyReader := snappy.NewReader(file) snappyReader := snappy.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
snappyReader.Read(out) // $ hasValueFlow="snappyReader" snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert
snappyReader.ReadByte() // $ hasValueFlow="snappyReader" snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert
tarRead = tar.NewReader(snappyReader) tarRead = tar.NewReader(snappyReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -386,10 +386,10 @@ func SnappyKlauspost(file io.Reader) {
snappyReader := snappyKlauspost.NewReader(file) snappyReader := snappyKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
snappyReader.Read(out) // $ hasValueFlow="snappyReader" snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert
var buf bytes.Buffer var buf bytes.Buffer
snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader" snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader" Alert
snappyReader.ReadByte() // $ hasValueFlow="snappyReader" snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert
tarRead = tar.NewReader(snappyReader) tarRead = tar.NewReader(snappyReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -414,10 +414,10 @@ func S2(file io.Reader) {
s2Reader := s2.NewReader(file) s2Reader := s2.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
s2Reader.Read(out) // $ hasValueFlow="s2Reader" s2Reader.Read(out) // $ hasValueFlow="s2Reader" Alert
s2Reader.ReadByte() // $ hasValueFlow="s2Reader" s2Reader.ReadByte() // $ hasValueFlow="s2Reader" Alert
var buf bytes.Buffer var buf bytes.Buffer
s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader" s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader" Alert
tarRead = tar.NewReader(s2Reader) tarRead = tar.NewReader(s2Reader)
TarDecompressor(tarRead) 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) dstF, _ := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
defer dstF.Close() defer dstF.Close()
newSrc := io.Reader(gzipReader) newSrc := io.Reader(gzipReader)
_, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc" _, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc" Alert
} }
func Gzip(file io.Reader) { func Gzip(file io.Reader) {
var tarRead *tar.Reader var tarRead *tar.Reader
gzipReader, _ := gzip.NewReader(file) gzipReader, _ := gzip.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
gzipReader.Read(out) // $ hasValueFlow="gzipReader" gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert
tarRead = tar.NewReader(gzipReader) tarRead = tar.NewReader(gzipReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -474,9 +474,9 @@ func GzipKlauspost(file io.Reader) {
gzipReader, _ := gzipKlauspost.NewReader(file) gzipReader, _ := gzipKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
gzipReader.Read(out) // $ hasValueFlow="gzipReader" gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert
var buf bytes.Buffer var buf bytes.Buffer
gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader" gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader" Alert
tarRead = tar.NewReader(gzipReader) tarRead = tar.NewReader(gzipReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -501,9 +501,9 @@ func PzipKlauspost(file io.Reader) {
pgzipReader, _ := pgzipKlauspost.NewReader(file) pgzipReader, _ := pgzipKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
pgzipReader.Read(out) // $ hasValueFlow="pgzipReader" pgzipReader.Read(out) // $ hasValueFlow="pgzipReader" Alert
var buf bytes.Buffer var buf bytes.Buffer
pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader" pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader" Alert
tarRead = tar.NewReader(pgzipReader) tarRead = tar.NewReader(pgzipReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -528,11 +528,11 @@ func Zstd_Klauspost(file io.Reader) {
zstdReader, _ := zstdKlauspost.NewReader(file) zstdReader, _ := zstdKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
zstdReader.Read(out) // $ hasValueFlow="zstdReader" zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert
var buf bytes.Buffer var buf bytes.Buffer
zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader" zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader" Alert
var src []byte var src []byte
zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader" zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader" Alert
tarRead = tar.NewReader(zstdReader) tarRead = tar.NewReader(zstdReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -557,7 +557,7 @@ func Zstd_DataDog(file io.Reader) {
zstdReader := zstdDataDog.NewReader(file) zstdReader := zstdDataDog.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
zstdReader.Read(out) // $ hasValueFlow="zstdReader" zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert
tarRead = tar.NewReader(zstdReader) tarRead = tar.NewReader(zstdReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -582,7 +582,7 @@ func Xz(file io.Reader) {
xzReader, _ := xz.NewReader(file) xzReader, _ := xz.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
xzReader.Read(out) // $ hasValueFlow="xzReader" xzReader.Read(out) // $ hasValueFlow="xzReader" Alert
tarRead = tar.NewReader(xzReader) tarRead = tar.NewReader(xzReader)
fmt.Println(io.SeekStart) fmt.Println(io.SeekStart)
@@ -618,7 +618,7 @@ func TarDecompressor(tarRead *tar.Reader) {
if cur.Typeflag != tar.TypeReg { if cur.Typeflag != tar.TypeReg {
continue continue
} }
data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead" data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead" Alert
files[cur.Name] = &fstest.MapFile{Data: data} files[cur.Name] = &fstest.MapFile{Data: data}
} }
fmt.Print(files) fmt.Print(files)
@@ -626,7 +626,7 @@ func TarDecompressor(tarRead *tar.Reader) {
func TarDecompressor2(tarRead *tar.Reader) { func TarDecompressor2(tarRead *tar.Reader) {
var tarOut []byte = make([]byte, 70) var tarOut []byte = make([]byte, 70)
tarRead.Read(tarOut) // $ hasValueFlow="tarRead" tarRead.Read(tarOut) // $ hasValueFlow="tarRead" Alert
fmt.Println("do sth with output:", tarOut) fmt.Println("do sth with output:", tarOut)
} }

View File

@@ -1 +1,2 @@
experimental/CWE-525/WebCacheDeception.ql query: experimental/CWE-525/WebCacheDeception.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -79,7 +79,7 @@ func badRoutingNet() {
http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/")))) 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) err := http.ListenAndServe(":1337", nil)
if err != nil { if err != nil {
log.Fatal("ListenAndServe: ", err) log.Fatal("ListenAndServe: ", err)

View File

@@ -12,12 +12,12 @@ func badRouting() {
log.Println("We are logging in Golang!") log.Println("We are logging in Golang!")
// GET /api/register // GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error { app.Get("/api/*", func(c *fiber.Ctx) error { // $ Alert
msg := fmt.Sprintf("✋") msg := fmt.Sprintf("✋")
return c.SendString(msg) // => ✋ register 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("✋") msg := fmt.Sprintf("✋")
return c.SendString(msg) // => ✋ register return c.SendString(msg) // => ✋ register
}) })

View File

@@ -10,7 +10,7 @@ import (
func badRoutingChi() { func badRoutingChi() {
r := chi.NewRouter() r := chi.NewRouter()
r.Use(middleware.Logger) 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")) w.Write([]byte("welcome"))
}) })
http.ListenAndServe(":3000", r) http.ListenAndServe(":3000", r)

View File

@@ -18,7 +18,7 @@ func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
func badHTTPRouter() { func badHTTPRouter() {
router := httprouter.New() router := httprouter.New()
router.GET("/test/*test", Index) router.GET("/test/*test", Index) // $ Alert
router.GET("/hello/:name", Hello) router.GET("/hello/:name", Hello)
log.Fatal(http.ListenAndServe(":8082", router)) log.Fatal(http.ListenAndServe(":8082", router))

View File

@@ -23,10 +23,10 @@ func good() (interface{}, error) {
} }
func bad() interface{} { 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. // 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]) 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 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{} { 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. // 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) 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 return db
} }
@@ -60,12 +60,12 @@ func (Config) Parse([]string) error { return nil }
func RegexFuncModelTest(w http.ResponseWriter, req *http.Request) (interface{}, error) { func RegexFuncModelTest(w http.ResponseWriter, req *http.Request) (interface{}, error) {
cfg := NewConfig() 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 { if err != nil {
return nil, err return nil, err
} }
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, cfg.dsn) 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 return db, nil
} }

View File

@@ -1,2 +1,4 @@
query: experimental/CWE-74/DsnInjection.ql query: experimental/CWE-74/DsnInjection.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1,4 @@
query: experimental/CWE-74/DsnInjectionLocal.ql query: experimental/CWE-74/DsnInjectionLocal.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1 +1,2 @@
experimental/CWE-807/SensitiveConditionBypass.ql query: experimental/CWE-807/SensitiveConditionBypass.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -4,7 +4,7 @@ import "net/http"
func example(w http.ResponseWriter, r *http.Request) { func example(w http.ResponseWriter, r *http.Request) {
test2 := "test" test2 := "test"
if r.Header.Get("X-Password") != test2 { if r.Header.Get("X-Password") != test2 { // $ Alert
login() login()
} }
} }

View File

@@ -13,7 +13,7 @@ const test = "localhost"
// Should alert as authkey is sensitive // Should alert as authkey is sensitive
func ex1(w http.ResponseWriter, r *http.Request) { func ex1(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Origin") != test { if r.Header.Get("Origin") != test { // $ Alert
authkey := "randomDatta" authkey := "randomDatta"
io.WriteString(w, authkey) io.WriteString(w, authkey)
} }
@@ -22,7 +22,7 @@ func ex1(w http.ResponseWriter, r *http.Request) {
// Should alert as authkey is sensitive // Should alert as authkey is sensitive
func ex2(w http.ResponseWriter, r *http.Request) { func ex2(w http.ResponseWriter, r *http.Request) {
test2 := "test" test2 := "test"
if r.Header.Get("Origin") != test2 { if r.Header.Get("Origin") != test2 { // $ Alert
authkey := "randomDatta2" authkey := "randomDatta2"
io.WriteString(w, authkey) io.WriteString(w, authkey)
} }
@@ -31,7 +31,7 @@ func ex2(w http.ResponseWriter, r *http.Request) {
// Should alert as login() is sensitive // Should alert as login() is sensitive
func ex3(w http.ResponseWriter, r *http.Request) { func ex3(w http.ResponseWriter, r *http.Request) {
test2 := "test" test2 := "test"
if r.Header.Get("Origin") != test2 { if r.Header.Get("Origin") != test2 { // $ Alert
login() login()
} }
} }

View File

@@ -1 +1,2 @@
experimental/CWE-840/ConditionalBypass.ql query: experimental/CWE-840/ConditionalBypass.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -6,7 +6,7 @@ import (
func exampleHandlerBad(w http.ResponseWriter, r *http.Request) { func exampleHandlerBad(w http.ResponseWriter, r *http.Request) {
// BAD: the Origin and Host headers are user controlled // 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 //do something
} }
} }

View File

@@ -6,14 +6,14 @@ import (
// BAD: taken from https://www.gorillatoolkit.org/pkg/websocket // BAD: taken from https://www.gorillatoolkit.org/pkg/websocket
func ex1(w http.ResponseWriter, r *http.Request) { 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 //do something
} }
} }
// BAD: both operands are from remote sources // BAD: both operands are from remote sources
func ex2(w http.ResponseWriter, r *http.Request) { 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 //do something
} }
} }

View File

@@ -5,7 +5,7 @@ import "os"
func openFiles(filenames []string) { func openFiles(filenames []string) {
for _, filename := range filenames { for _, filename := range filenames {
file, err := os.Open(filename) file, err := os.Open(filename)
defer file.Close() defer file.Close() // $ Alert[go/examples/deferinloop]
if err != nil { if err != nil {
// handle error // handle error
} }

View File

@@ -1 +1,2 @@
experimental/InconsistentCode/DeferInLoop.ql query: experimental/InconsistentCode/DeferInLoop.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -4,6 +4,6 @@ import "gorm.io/gorm"
func getUserId(db *gorm.DB, name string) int64 { func getUserId(db *gorm.DB, name string) int64 {
var user User 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 return user.Id
} }

View File

@@ -1 +1,2 @@
experimental/InconsistentCode/GORMErrorNotChecked.ql query: experimental/InconsistentCode/GORMErrorNotChecked.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -3,24 +3,24 @@ package main
func test() { func test() {
var xs []int var xs []int
for _ = range xs { for _ = range xs {
defer test() // not ok defer test() // $ Alert[go/examples/deferinloop] // not ok
} }
for _ = range xs { for _ = range xs {
if true { if true {
defer test() // not ok defer test() // $ Alert[go/examples/deferinloop] // not ok
} }
} }
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
defer test() defer test() // $ Alert[go/examples/deferinloop]
} }
for true { for true {
defer test() // not ok defer test() // $ Alert[go/examples/deferinloop] // not ok
} }
for false { for false {
defer test() // fine but caught defer test() // $ Alert[go/examples/deferinloop] // fine but caught
} }
} }

View File

@@ -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 edges
| WrongUsageOfUnsafe.go:17:24:17:48 | type conversion | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | provenance | | | 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 | | | 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:16:292:48 | type conversion | semmle.label | type conversion |
| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | semmle.label | type conversion |
subpaths 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 |

View File

@@ -74,7 +74,7 @@ func badIndexExpr() {
// the address of the 3rd element of the `harmless` array, // the address of the 3rd element of the `harmless` array,
// and continue for 8 bytes, going out of the boundaries of // and continue for 8 bytes, going out of the boundaries of
// `harmless` and crossing into the memory occupied by `secret`. // `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)[:])) fmt.Println(string((*leaking)[:]))
@@ -108,7 +108,7 @@ func bad0() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we get the pointer to the first byte of harmless) // (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)[:])) fmt.Println(string((*leaking)[:]))
@@ -126,7 +126,7 @@ func bad1() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (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)[:])) fmt.Println(string((*leaking)[:]))
@@ -146,7 +146,7 @@ func bad2() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (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)[:])) fmt.Println(string((*leaking)[:]))
@@ -163,7 +163,7 @@ func bad3() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (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(*leaking)
fmt.Println([17]string((*leaking))) fmt.Println([17]string((*leaking)))
@@ -186,7 +186,7 @@ func bad4() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (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)[:])) fmt.Println(string((*leaking)[:]))
@@ -208,7 +208,7 @@ func bad5() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (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[:])) fmt.Println(string(leaking[:]))
@@ -224,7 +224,7 @@ func bad6() {
secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'}
// Read before secret: // 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[:])) 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 // will be read, the read will also contain pieces of
// data from `secret`. // data from `secret`.
var buf [8 + 9]byte 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 return buf
} }
func bad7() { func bad7() {
@@ -253,7 +253,7 @@ func bad7() {
// (notice we read more than the length of harmless); // (notice we read more than the length of harmless);
// the leaking array will not contain letters, // the leaking array will not contain letters,
// but integers representing bytes from `secret`. // 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) fmt.Println(*leaking)
@@ -271,7 +271,7 @@ func bad8() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless); // (notice we read more than the length of harmless);
// the leaking data will contain some bits from `secret`. // 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) fmt.Println(*leaking)
@@ -289,7 +289,7 @@ func bad9() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless); // (notice we read more than the length of harmless);
// the leaking data will contain some bits from `secret`. // 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) fmt.Println(*leaking)

View File

@@ -1 +1,2 @@
experimental/Unsafe/WrongUsageOfUnsafe.ql query: experimental/Unsafe/WrongUsageOfUnsafe.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1,4 @@
query: Security/CWE-089/SqlInjection.ql query: Security/CWE-089/SqlInjection.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1,4 @@
query: Security/CWE-079/StoredXss.ql query: Security/CWE-079/StoredXss.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -8,61 +8,61 @@ import (
// BAD: using untrusted data in SQL queries // BAD: using untrusted data in SQL queries
func testDbMethods(bdb *orm.DB, untrustedSource *http.Request) { func testDbMethods(bdb *orm.DB, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
bdb.Exec(untrusted) // $ querystring=untrusted bdb.Exec(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
bdb.ExecContext(nil, untrusted) // $ querystring=untrusted bdb.ExecContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection]
bdb.Prepare(untrusted) // $ querystring=untrusted bdb.Prepare(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
bdb.PrepareContext(nil, untrusted) // $ querystring=untrusted bdb.PrepareContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection]
bdb.Query(untrusted) // $ querystring=untrusted bdb.Query(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
bdb.QueryContext(nil, untrusted) // $ querystring=untrusted bdb.QueryContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection]
bdb.QueryRow(untrusted) // $ querystring=untrusted bdb.QueryRow(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
bdb.QueryRowContext(nil, untrusted) // $ querystring=untrusted bdb.QueryRowContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection]
} }
// BAD: using untrusted data to build SQL queries (QueryBuilder does not sanitize its arguments) // BAD: using untrusted data to build SQL queries (QueryBuilder does not sanitize its arguments)
func testQueryBuilderMethods(qb orm.QueryBuilder, untrustedSource *http.Request) { func testQueryBuilderMethods(qb orm.QueryBuilder, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
untrusted2 := untrustedSource.UserAgent() untrusted2 := untrustedSource.UserAgent() // $ Source[go/sql-injection]
qb.Select(untrusted) // $ querystring=untrusted qb.Select(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.From(untrusted) // $ querystring=untrusted qb.From(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.InnerJoin(untrusted) // $ querystring=untrusted qb.InnerJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.LeftJoin(untrusted) // $ querystring=untrusted qb.LeftJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.RightJoin(untrusted) // $ querystring=untrusted qb.RightJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.On(untrusted) // $ querystring=untrusted qb.On(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.Where(untrusted) // $ querystring=untrusted qb.Where(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.And(untrusted) // $ querystring=untrusted qb.And(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.Or(untrusted) // $ querystring=untrusted qb.Or(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.In(untrusted) // $ querystring=untrusted qb.In(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.OrderBy(untrusted) // $ querystring=untrusted qb.OrderBy(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.GroupBy(untrusted) // $ querystring=untrusted qb.GroupBy(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.Having(untrusted) // $ querystring=untrusted qb.Having(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.Update(untrusted) // $ querystring=untrusted qb.Update(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.Set(untrusted) // $ querystring=untrusted qb.Set(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.Delete(untrusted) // $ querystring=untrusted qb.Delete(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.InsertInto(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 qb.InsertInto(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 Alert[go/sql-injection]
qb.Values(untrusted) // $ querystring=untrusted qb.Values(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
qb.Subquery(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 qb.Subquery(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 Alert[go/sql-injection]
} }
func testOrmerRaw(ormer orm.Ormer, untrustedSource *http.Request) { func testOrmerRaw(ormer orm.Ormer, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
untrusted2 := untrustedSource.UserAgent() untrusted2 := untrustedSource.UserAgent()
ormer.Raw(untrusted, untrusted2) // $ querystring=untrusted // BAD: using an untrusted string as a query ormer.Raw(untrusted, untrusted2) // $ querystring=untrusted Alert[go/sql-injection] // BAD: using an untrusted string as a query
ormer.Raw("FROM ? SELECT ?", untrusted, untrusted2) // $ querystring="FROM ? SELECT ?" // GOOD: untrusted string used in argument context ormer.Raw("FROM ? SELECT ?", untrusted, untrusted2) // $ querystring="FROM ? SELECT ?" // GOOD: untrusted string used in argument context
} }
func testFilterRaw(querySeter orm.QuerySeter, untrustedSource *http.Request) { func testFilterRaw(querySeter orm.QuerySeter, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
querySeter.FilterRaw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name querySeter.FilterRaw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name
querySeter.FilterRaw("safe", untrusted) // $ querystring=untrusted // BAD: untrusted used as a SQL fragment querySeter.FilterRaw("safe", untrusted) // $ querystring=untrusted Alert[go/sql-injection] // BAD: untrusted used as a SQL fragment
} }
func testConditionRaw(cond orm.Condition, untrustedSource *http.Request) { func testConditionRaw(cond orm.Condition, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
cond.Raw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name cond.Raw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name
cond.Raw("safe", untrusted) // $ querystring=untrusted // BAD: untrusted used as a SQL fragment cond.Raw("safe", untrusted) // $ querystring=untrusted Alert[go/sql-injection] // BAD: untrusted used as a SQL fragment
} }
type SubStruct struct { type SubStruct struct {
@@ -77,90 +77,90 @@ type MyStruct struct {
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
func testOrmerReads(ormer orm.Ormer, sink http.ResponseWriter) { func testOrmerReads(ormer orm.Ormer, sink http.ResponseWriter) {
obj := MyStruct{} obj := MyStruct{}
ormer.Read(&obj) ormer.Read(&obj) // $ Source[go/stored-xss]
sink.Write([]byte(obj.field)) sink.Write([]byte(obj.field)) // $ Alert[go/stored-xss]
sink.Write([]byte(obj.substructs[0].field)) sink.Write([]byte(obj.substructs[0].field)) // $ Alert[go/stored-xss]
obj2 := MyStruct{} obj2 := MyStruct{}
ormer.ReadForUpdate(&obj2) ormer.ReadForUpdate(&obj2) // $ Source[go/stored-xss]
sink.Write([]byte(obj2.field)) sink.Write([]byte(obj2.field)) // $ Alert[go/stored-xss]
obj3 := MyStruct{} obj3 := MyStruct{}
ormer.ReadOrCreate(&obj3, "arg") ormer.ReadOrCreate(&obj3, "arg") // $ Source[go/stored-xss]
sink.Write([]byte(obj3.field)) sink.Write([]byte(obj3.field)) // $ Alert[go/stored-xss]
} }
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
func testFieldReads(textField *orm.TextField, jsonField *orm.JSONField, jsonbField *orm.JsonbField, sink http.ResponseWriter) { func testFieldReads(textField *orm.TextField, jsonField *orm.JSONField, jsonbField *orm.JsonbField, sink http.ResponseWriter) {
sink.Write([]byte(textField.Value())) sink.Write([]byte(textField.Value())) // $ Alert[go/stored-xss]
sink.Write([]byte(textField.RawValue().(string))) sink.Write([]byte(textField.RawValue().(string))) // $ Alert[go/stored-xss]
sink.Write([]byte(textField.String())) sink.Write([]byte(textField.String())) // $ Alert[go/stored-xss]
sink.Write([]byte(jsonField.Value())) sink.Write([]byte(jsonField.Value())) // $ Alert[go/stored-xss]
sink.Write([]byte(jsonField.RawValue().(string))) sink.Write([]byte(jsonField.RawValue().(string))) // $ Alert[go/stored-xss]
sink.Write([]byte(jsonField.String())) sink.Write([]byte(jsonField.String())) // $ Alert[go/stored-xss]
sink.Write([]byte(jsonbField.Value())) sink.Write([]byte(jsonbField.Value())) // $ Alert[go/stored-xss]
sink.Write([]byte(jsonbField.RawValue().(string))) sink.Write([]byte(jsonbField.RawValue().(string))) // $ Alert[go/stored-xss]
sink.Write([]byte(jsonbField.String())) sink.Write([]byte(jsonbField.String())) // $ Alert[go/stored-xss]
} }
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
func testQuerySeterReads(qs orm.QuerySeter, sink http.ResponseWriter) { func testQuerySeterReads(qs orm.QuerySeter, sink http.ResponseWriter) {
var objs []*MyStruct var objs []*MyStruct
qs.All(&objs) qs.All(&objs) // $ Source[go/stored-xss]
sink.Write([]byte(objs[0].field)) sink.Write([]byte(objs[0].field)) // $ Alert[go/stored-xss]
var obj MyStruct var obj MyStruct
qs.One(&obj) qs.One(&obj) // $ Source[go/stored-xss]
sink.Write([]byte(obj.field)) sink.Write([]byte(obj.field)) // $ Alert[go/stored-xss]
var allMaps []orm.Params var allMaps []orm.Params
qs.Values(&allMaps) qs.Values(&allMaps) // $ Source[go/stored-xss]
sink.Write([]byte(allMaps[0]["field"].(string))) sink.Write([]byte(allMaps[0]["field"].(string))) // $ Alert[go/stored-xss]
var allLists []orm.ParamsList var allLists []orm.ParamsList
qs.ValuesList(&allLists) qs.ValuesList(&allLists) // $ Source[go/stored-xss]
sink.Write([]byte(allLists[0][0].(string))) sink.Write([]byte(allLists[0][0].(string))) // $ Alert[go/stored-xss]
var oneList orm.ParamsList var oneList orm.ParamsList
qs.ValuesFlat(&oneList, "colname") qs.ValuesFlat(&oneList, "colname") // $ Source[go/stored-xss]
sink.Write([]byte(oneList[0].(string))) sink.Write([]byte(oneList[0].(string))) // $ Alert[go/stored-xss]
var oneRowMap orm.Params var oneRowMap orm.Params
qs.RowsToMap(&oneRowMap, "key", "value") qs.RowsToMap(&oneRowMap, "key", "value") // $ Source[go/stored-xss]
sink.Write([]byte(oneRowMap["field"].(string))) sink.Write([]byte(oneRowMap["field"].(string))) // $ Alert[go/stored-xss]
var oneRowStruct MyStruct var oneRowStruct MyStruct
qs.RowsToStruct(&oneRowStruct, "key", "value") qs.RowsToStruct(&oneRowStruct, "key", "value") // $ Source[go/stored-xss]
sink.Write([]byte(oneRowStruct.field)) sink.Write([]byte(oneRowStruct.field)) // $ Alert[go/stored-xss]
} }
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
func testRawSeterReads(rs orm.RawSeter, sink http.ResponseWriter) { func testRawSeterReads(rs orm.RawSeter, sink http.ResponseWriter) {
var allMaps []orm.Params var allMaps []orm.Params
rs.Values(&allMaps) rs.Values(&allMaps) // $ Source[go/stored-xss]
sink.Write([]byte(allMaps[0]["field"].(string))) sink.Write([]byte(allMaps[0]["field"].(string))) // $ Alert[go/stored-xss]
var allLists []orm.ParamsList var allLists []orm.ParamsList
rs.ValuesList(&allLists) rs.ValuesList(&allLists) // $ Source[go/stored-xss]
sink.Write([]byte(allLists[0][0].(string))) sink.Write([]byte(allLists[0][0].(string))) // $ Alert[go/stored-xss]
var oneList orm.ParamsList var oneList orm.ParamsList
rs.ValuesFlat(&oneList, "colname") rs.ValuesFlat(&oneList, "colname") // $ Source[go/stored-xss]
sink.Write([]byte(oneList[0].(string))) sink.Write([]byte(oneList[0].(string))) // $ Alert[go/stored-xss]
var oneRowMap orm.Params var oneRowMap orm.Params
rs.RowsToMap(&oneRowMap, "key", "value") rs.RowsToMap(&oneRowMap, "key", "value") // $ Source[go/stored-xss]
sink.Write([]byte(oneRowMap["field"].(string))) sink.Write([]byte(oneRowMap["field"].(string))) // $ Alert[go/stored-xss]
var oneRowStruct MyStruct var oneRowStruct MyStruct
rs.RowsToStruct(&oneRowStruct, "key", "value") rs.RowsToStruct(&oneRowStruct, "key", "value") // $ Source[go/stored-xss]
sink.Write([]byte(oneRowStruct.field)) sink.Write([]byte(oneRowStruct.field)) // $ Alert[go/stored-xss]
var strField string var strField string
rs.QueryRow(&strField) rs.QueryRow(&strField) // $ Source[go/stored-xss]
sink.Write([]byte(strField)) sink.Write([]byte(strField)) // $ Alert[go/stored-xss]
var strFields []string var strFields []string
rs.QueryRows(&strFields) rs.QueryRows(&strFields) // $ Source[go/stored-xss]
sink.Write([]byte(strFields[0])) sink.Write([]byte(strFields[0])) // $ Alert[go/stored-xss]
} }

View File

@@ -1,2 +1,4 @@
query: Security/CWE-079/ReflectedXss.ql query: Security/CWE-079/ReflectedXss.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -10,7 +10,7 @@ var hidden string
func hideUserData(next http.Handler) http.Handler { func hideUserData(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hidden = r.URL.Path hidden = r.URL.Path // $ Source
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
}) })
} }
@@ -18,10 +18,10 @@ func hideUserData(next http.Handler) http.Handler {
func main() { func main() {
r := chi.NewRouter() r := chi.NewRouter()
r.With(hideUserData).Get("/", func(w http.ResponseWriter, r *http.Request) { r.With(hideUserData).Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(hidden)) w.Write([]byte(hidden)) // $ Alert
w.Write([]byte(chi.URLParam(r, "someParam"))) w.Write([]byte(chi.URLParam(r, "someParam"))) // $ Alert
w.Write([]byte(chi.URLParamFromCtx(r.Context(), "someKey"))) w.Write([]byte(chi.URLParamFromCtx(r.Context(), "someKey"))) // $ Alert
w.Write([]byte(chi.RouteContext(r.Context()).URLParam("someOtherKey"))) w.Write([]byte(chi.RouteContext(r.Context()).URLParam("someOtherKey"))) // $ Alert
}) })
http.ListenAndServe(":3000", r) http.ListenAndServe(":3000", r)
} }

View File

@@ -1,2 +1,4 @@
query: Security/CWE-601/OpenUrlRedirect.ql query: Security/CWE-601/OpenUrlRedirect.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1,4 @@
query: Security/CWE-079/ReflectedXss.ql query: Security/CWE-079/ReflectedXss.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1,4 @@
query: Security/CWE-022/TaintedPath.ql query: Security/CWE-022/TaintedPath.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -12,81 +12,81 @@ import (
// All are XSS vulnerabilities, except as specifically noted. // All are XSS vulnerabilities, except as specifically noted.
func testParam(ctx echo.Context) error { func testParam(ctx echo.Context) error {
param := ctx.Param("someParam") param := ctx.Param("someParam") // $ Source[go/reflected-xss]
ctx.HTML(200, param) ctx.HTML(200, param) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testParamValues(ctx echo.Context) error { func testParamValues(ctx echo.Context) error {
param := ctx.ParamValues()[0] param := ctx.ParamValues()[0] // $ Source[go/reflected-xss]
ctx.HTML(200, param) ctx.HTML(200, param) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testQueryParam(ctx echo.Context) error { func testQueryParam(ctx echo.Context) error {
param := ctx.QueryParam("someParam") param := ctx.QueryParam("someParam") // $ Source[go/reflected-xss]
ctx.HTML(200, param) ctx.HTML(200, param) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testQueryParams(ctx echo.Context) error { func testQueryParams(ctx echo.Context) error {
param := ctx.QueryParams()["someParam"][0] param := ctx.QueryParams()["someParam"][0] // $ Source[go/reflected-xss]
ctx.HTML(200, param) ctx.HTML(200, param) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testQueryString(ctx echo.Context) error { func testQueryString(ctx echo.Context) error {
qstr := ctx.QueryString() qstr := ctx.QueryString() // $ Source[go/reflected-xss]
ctx.HTML(200, qstr) ctx.HTML(200, qstr) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testFormValue(ctx echo.Context) error { func testFormValue(ctx echo.Context) error {
val := ctx.FormValue("someField") val := ctx.FormValue("someField") // $ Source[go/reflected-xss]
ctx.HTML(200, val) ctx.HTML(200, val) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testFormParams(ctx echo.Context) error { func testFormParams(ctx echo.Context) error {
params, _ := ctx.FormParams() params, _ := ctx.FormParams() // $ Source[go/reflected-xss]
ctx.HTML(200, params["someField"][0]) ctx.HTML(200, params["someField"][0]) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testFormFile(ctx echo.Context) error { func testFormFile(ctx echo.Context) error {
fileHeader, _ := ctx.FormFile("someFilename") fileHeader, _ := ctx.FormFile("someFilename") // $ Source[go/reflected-xss]
file, _ := fileHeader.Open() file, _ := fileHeader.Open()
buffer := make([]byte, 100) buffer := make([]byte, 100)
file.Read(buffer) file.Read(buffer)
ctx.HTMLBlob(200, buffer) ctx.HTMLBlob(200, buffer) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testMultipartFormValue(ctx echo.Context) error { func testMultipartFormValue(ctx echo.Context) error {
form, _ := ctx.MultipartForm() form, _ := ctx.MultipartForm() // $ Source[go/reflected-xss]
ctx.HTML(200, form.Value["someField"][0]) ctx.HTML(200, form.Value["someField"][0]) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testMultipartFormFile(ctx echo.Context) error { func testMultipartFormFile(ctx echo.Context) error {
form, _ := ctx.MultipartForm() form, _ := ctx.MultipartForm() // $ Source[go/reflected-xss]
fileHeader := form.File["someFilename"][0] fileHeader := form.File["someFilename"][0]
file, _ := fileHeader.Open() file, _ := fileHeader.Open()
buffer := make([]byte, 100) buffer := make([]byte, 100)
file.Read(buffer) file.Read(buffer)
ctx.HTMLBlob(200, buffer) ctx.HTMLBlob(200, buffer) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testCookie(ctx echo.Context) error { func testCookie(ctx echo.Context) error {
val, _ := ctx.Cookie("someKey") val, _ := ctx.Cookie("someKey") // $ Source[go/reflected-xss]
ctx.HTML(200, val.Value) ctx.HTML(200, val.Value) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testCookies(ctx echo.Context) error { func testCookies(ctx echo.Context) error {
cookies := ctx.Cookies() cookies := ctx.Cookies() // $ Source[go/reflected-xss]
ctx.HTML(200, cookies[0].Value) ctx.HTML(200, cookies[0].Value) // $ Alert[go/reflected-xss]
return nil return nil
} }
@@ -96,8 +96,8 @@ type myStruct struct {
func testBind(ctx echo.Context) error { func testBind(ctx echo.Context) error {
data := myStruct{} data := myStruct{}
ctx.Bind(&data) ctx.Bind(&data) // $ Source[go/reflected-xss]
ctx.HTML(200, data.s) ctx.HTML(200, data.s) // $ Alert[go/reflected-xss]
return nil return nil
} }
@@ -110,8 +110,8 @@ func testGetSetEmpty(ctx echo.Context) error {
} }
func testGetSet(ctx echo.Context) error { func testGetSet(ctx echo.Context) error {
ctx.Set("someKey", ctx.Param("someParam")) ctx.Set("someKey", ctx.Param("someParam")) // $ Source[go/reflected-xss]
ctx.HTML(200, ctx.Get("someKey").(string)) // BAD, the context is tainted ctx.HTML(200, ctx.Get("someKey").(string)) // $ Alert[go/reflected-xss] // BAD, the context is tainted
return nil return nil
} }
@@ -121,20 +121,20 @@ func testGetSet(ctx echo.Context) error {
// All are XSS vulnerabilities, except as specifically noted. // All are XSS vulnerabilities, except as specifically noted.
func testHTML(ctx echo.Context) error { func testHTML(ctx echo.Context) error {
param := ctx.Param("someParam") param := ctx.Param("someParam") // $ Source[go/reflected-xss]
ctx.HTML(200, param) ctx.HTML(200, param) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testHTMLBlob(ctx echo.Context) error { func testHTMLBlob(ctx echo.Context) error {
param := ctx.Param("someParam") param := ctx.Param("someParam") // $ Source[go/reflected-xss]
ctx.HTMLBlob(200, []byte(param)) ctx.HTMLBlob(200, []byte(param)) // $ Alert[go/reflected-xss]
return nil return nil
} }
func testBlob(ctx echo.Context) error { func testBlob(ctx echo.Context) error {
param := ctx.Param("someParam") param := ctx.Param("someParam") // $ Source[go/reflected-xss]
ctx.Blob(200, "text/html", []byte(param)) // BAD, the content-type is HTML ctx.Blob(200, "text/html", []byte(param)) // $ Alert[go/reflected-xss] // BAD, the content-type is HTML
return nil return nil
} }
@@ -145,9 +145,9 @@ func testBlobSafe(ctx echo.Context) error {
} }
func testStream(ctx echo.Context) error { func testStream(ctx echo.Context) error {
param := ctx.Param("someParam") param := ctx.Param("someParam") // $ Source[go/reflected-xss]
reader := strings.NewReader(param) reader := strings.NewReader(param)
ctx.Stream(200, "text/html", reader) // BAD, the content-type is HTML ctx.Stream(200, "text/html", reader) // $ Alert[go/reflected-xss] // BAD, the content-type is HTML
return nil return nil
} }
@@ -161,28 +161,28 @@ func testStreamSafe(ctx echo.Context) error {
// Section: testing output methods defined on Response (XSS vulnerability) // Section: testing output methods defined on Response (XSS vulnerability)
func testResponseWrite(ctx echo.Context) error { func testResponseWrite(ctx echo.Context) error {
param := ctx.Param("someParam") param := ctx.Param("someParam") // $ Source[go/reflected-xss]
ctx.Response().Write([]byte(param)) ctx.Response().Write([]byte(param)) // $ Alert[go/reflected-xss]
return nil return nil
} }
// Section: test detecting an open redirect using the Context.Redirect function: // Section: test detecting an open redirect using the Context.Redirect function:
func testRedirect(ctx echo.Context) error { func testRedirect(ctx echo.Context) error {
param := ctx.Param("someParam") param := ctx.Param("someParam") // $ Source[go/unvalidated-url-redirection]
ctx.Redirect(301, param) ctx.Redirect(301, param) // $ Alert[go/unvalidated-url-redirection]
return nil return nil
} }
func testLocalRedirects(ctx echo.Context) error { func testLocalRedirects(ctx echo.Context) error {
param := ctx.Param("someParam") param := ctx.Param("someParam") // $ Source[go/unvalidated-url-redirection]
param2 := param param2 := param
param3 := param param3 := param
// Gratuitous copy because sanitization of uses propagates to subsequent uses // Gratuitous copy because sanitization of uses propagates to subsequent uses
// GOOD: local redirects are unproblematic // GOOD: local redirects are unproblematic
ctx.Redirect(301, "/local"+param) ctx.Redirect(301, "/local"+param)
// BAD: this could be a non-local redirect // BAD: this could be a non-local redirect
ctx.Redirect(301, "/"+param2) ctx.Redirect(301, "/"+param2) // $ Alert[go/unvalidated-url-redirection]
// GOOD: localhost redirects are unproblematic // GOOD: localhost redirects are unproblematic
ctx.Redirect(301, "//localhost/"+param3) ctx.Redirect(301, "//localhost/"+param3)
return nil return nil
@@ -221,12 +221,12 @@ func testNonExploitableFields(ctx echo.Context) error {
func fsOpsTest() { func fsOpsTest() {
e := echo.New() e := echo.New()
e.GET("/", func(c echo.Context) error { e.GET("/", func(c echo.Context) error {
filepath := c.QueryParam("filePath") filepath := c.QueryParam("filePath") // $ Source[go/path-injection]
return c.File(filepath) // $ FileSystemAccess=filepath return c.File(filepath) // $ FileSystemAccess=filepath Alert[go/path-injection]
}) })
e.GET("/attachment", func(c echo.Context) error { e.GET("/attachment", func(c echo.Context) error {
filepath := c.QueryParam("filePath") filepath := c.QueryParam("filePath") // $ Source[go/path-injection]
return c.Attachment(filepath, "file name in response") // $ FileSystemAccess=filepath return c.Attachment(filepath, "file name in response") // $ FileSystemAccess=filepath Alert[go/path-injection]
}) })
_ = e.Start(":1323") _ = e.Start(":1323")
} }

View File

@@ -1,8 +1,8 @@
#select
| main.go:21:28:21:31 | name | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | definition of req | user-provided value |
edges edges
| main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | provenance | | | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | provenance | |
nodes nodes
| main.go:18:46:18:48 | definition of req | semmle.label | definition of req | | main.go:18:46:18:48 | definition of req | semmle.label | definition of req |
| main.go:21:28:21:31 | name | semmle.label | name | | main.go:21:28:21:31 | name | semmle.label | name |
subpaths subpaths
#select
| main.go:21:28:21:31 | name | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | definition of req | user-provided value |

View File

@@ -1 +1,2 @@
Security/CWE-117/LogInjection.ql query: Security/CWE-117/LogInjection.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -15,10 +15,10 @@ import (
type Greeter struct{} type Greeter struct{}
func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="definition of req" func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="definition of req" Source
// var access // var access
name := req.Name name := req.Name
fmt.Println("Name :: %s", name) fmt.Println("Name :: %s", name) // $ Alert
return nil return nil
} }

View File

@@ -1,28 +1,28 @@
reverseRead reverseRead
| EndToEnd.go:30:35:30:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:31:35:31:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:30:35:30:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:31:35:31:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:36:18:36:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:37:18:37:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:36:18:36:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:37:18:37:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:44:18:44:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:45:18:45:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:44:18:44:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:45:18:45:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:51:20:51:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:52:20:52:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:51:20:51:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:52:20:52:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:58:18:58:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:59:18:59:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:58:18:58:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:59:18:59:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:64:26:64:26 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:65:26:65:26 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:64:26:64:33 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:65:26:65:33 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:69:22:69:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:70:22:70:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:69:22:69:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:70:22:70:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:74:22:74:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:75:22:75:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:74:22:74:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:75:22:75:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:79:35:79:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:80:35:80:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:79:35:79:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:80:35:80:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:84:22:84:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:85:22:85:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:84:22:84:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:85:22:85:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:89:21:89:21 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:90:21:90:21 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:89:21:89:28 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:90:21:90:28 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:94:20:94:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:95:20:95:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:94:20:94:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:95:20:95:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| Revel.go:26:7:26:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | Revel.go:26:7:26:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| Revel.go:27:7:27:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | Revel.go:27:7:27:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| Revel.go:27:7:27:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | Revel.go:27:7:27:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |

View File

@@ -3,10 +3,11 @@ package main
import ( import (
"bytes" "bytes"
"errors" "errors"
staticControllers "github.com/revel/modules/static/app/controllers"
"github.com/revel/revel"
"os" "os"
"time" "time"
staticControllers "github.com/revel/modules/static/app/controllers"
"github.com/revel/revel"
) )
// Use typical inheritence pattern, per github.com/revel/examples/booking: // Use typical inheritence pattern, per github.com/revel/examples/booking:
@@ -33,8 +34,8 @@ func (c MyRoute) Handler1() revel.Result {
func (c MyRoute) Handler2() revel.Result { func (c MyRoute) Handler2() revel.Result {
// BAD: the RenderBinary function copies an `io.Reader` to the user's browser. // BAD: the RenderBinary function copies an `io.Reader` to the user's browser.
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.WriteString(c.Params.Form.Get("someField")) buf.WriteString(c.Params.Form.Get("someField")) // $ Source[go/reflected-xss]
return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $ responsebody='buf' return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $ responsebody='buf' Alert[go/reflected-xss]
} }
func (c MyRoute) Handler3() revel.Result { func (c MyRoute) Handler3() revel.Result {
@@ -55,18 +56,18 @@ func (c MyRoute) Handler4() revel.Result {
func (c MyRoute) Handler5() revel.Result { func (c MyRoute) Handler5() revel.Result {
// BAD: returning an arbitrary file (but this is detected at the os.Open call, not // BAD: returning an arbitrary file (but this is detected at the os.Open call, not
// due to modelling Revel) // due to modelling Revel)
f, _ := os.Open(c.Params.Form.Get("someField")) f, _ := os.Open(c.Params.Form.Get("someField")) // $ Alert[go/path-injection]
return c.RenderFile(f, revel.Inline) return c.RenderFile(f, revel.Inline)
} }
func (c MyRoute) Handler6() revel.Result { func (c MyRoute) Handler6() revel.Result {
// BAD: returning an arbitrary file (detected as a user-controlled file-op, not XSS) // BAD: returning an arbitrary file (detected as a user-controlled file-op, not XSS)
return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline) return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline) // $ Alert[go/path-injection]
} }
func (c MyRoute) Handler7() revel.Result { func (c MyRoute) Handler7() revel.Result {
// BAD: straightforward XSS // BAD: straightforward XSS
return c.RenderHTML(c.Params.Form.Get("someField")) // $ responsebody='call to Get' return c.RenderHTML(c.Params.Form.Get("someField")) // $ responsebody='call to Get' Alert[go/reflected-xss]
} }
func (c MyRoute) Handler8() revel.Result { func (c MyRoute) Handler8() revel.Result {
@@ -91,5 +92,5 @@ func (c MyRoute) Handler11() revel.Result {
func (c MyRoute) Handler12() revel.Result { func (c MyRoute) Handler12() revel.Result {
// BAD: open redirect // BAD: open redirect
return c.Redirect(c.Params.Form.Get("someField")) return c.Redirect(c.Params.Form.Get("someField")) // $ Alert[go/unvalidated-url-redirection]
} }

View File

@@ -1,19 +1,19 @@
#select #select
| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value | | EndToEnd.go:95:20:95:49 | call to Get | EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:95:20:95:27 | selection of Params | user-provided value |
edges edges
| EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | provenance | Config | | EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | provenance | Config |
| EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Config | | EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Config |
| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Src:MaD:2 Config | | EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Src:MaD:2 Config |
| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Src:MaD:2 Config | | EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Src:MaD:2 Config |
| EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Config | | EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Config |
| EndToEnd.go:94:20:94:32 | selection of Form | EndToEnd.go:94:20:94:49 | call to Get | provenance | Config Sink:MaD:1 | | EndToEnd.go:95:20:95:32 | selection of Form | EndToEnd.go:95:20:95:49 | call to Get | provenance | Config Sink:MaD:1 |
models models
| 1 | Sink: group:revel; Controller; true; Redirect; ; ; Argument[0]; url-redirection; manual | | 1 | Sink: group:revel; Controller; true; Redirect; ; ; Argument[0]; url-redirection; manual |
| 2 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual | | 2 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual |
nodes nodes
| EndToEnd.go:94:20:94:27 | implicit dereference | semmle.label | implicit dereference | | EndToEnd.go:95:20:95:27 | implicit dereference | semmle.label | implicit dereference |
| EndToEnd.go:94:20:94:27 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:95:20:95:27 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] | | EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] |
| EndToEnd.go:94:20:94:32 | selection of Form | semmle.label | selection of Form | | EndToEnd.go:95:20:95:32 | selection of Form | semmle.label | selection of Form |
| EndToEnd.go:94:20:94:49 | call to Get | semmle.label | call to Get | | EndToEnd.go:95:20:95:49 | call to Get | semmle.label | call to Get |
subpaths subpaths

View File

@@ -1,2 +1,4 @@
query: Security/CWE-601/OpenUrlRedirect.ql query: Security/CWE-601/OpenUrlRedirect.ql
postprocess: utils/test/PrettyPrintModels.ql postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,16 +1,16 @@
#select #select
| EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | | EndToEnd.go:38:24:38:26 | buf | EndToEnd.go:37:18:37:25 | selection of Params | EndToEnd.go:38:24:38:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:37:18:37:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
| EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | | EndToEnd.go:70:22:70:51 | call to Get | EndToEnd.go:70:22:70:29 | selection of Params | EndToEnd.go:70:22:70:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:70:22:70:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
| Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template | | Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template |
| examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | | examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | |
| examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | | examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | |
edges edges
| EndToEnd.go:36:2:36:4 | buf [postupdate] | EndToEnd.go:37:24:37:26 | buf | provenance | | | EndToEnd.go:37:2:37:4 | buf [postupdate] | EndToEnd.go:38:24:38:26 | buf | provenance | |
| EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:36:18:36:30 | selection of Form | provenance | Src:MaD:1 | | EndToEnd.go:37:18:37:25 | selection of Params | EndToEnd.go:37:18:37:30 | selection of Form | provenance | Src:MaD:1 |
| EndToEnd.go:36:18:36:30 | selection of Form | EndToEnd.go:36:18:36:47 | call to Get | provenance | MaD:4 | | EndToEnd.go:37:18:37:30 | selection of Form | EndToEnd.go:37:18:37:47 | call to Get | provenance | MaD:4 |
| EndToEnd.go:36:18:36:47 | call to Get | EndToEnd.go:36:2:36:4 | buf [postupdate] | provenance | MaD:3 | | EndToEnd.go:37:18:37:47 | call to Get | EndToEnd.go:37:2:37:4 | buf [postupdate] | provenance | MaD:3 |
| EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:34 | selection of Form | provenance | Src:MaD:1 | | EndToEnd.go:70:22:70:29 | selection of Params | EndToEnd.go:70:22:70:34 | selection of Form | provenance | Src:MaD:1 |
| EndToEnd.go:69:22:69:34 | selection of Form | EndToEnd.go:69:22:69:51 | call to Get | provenance | MaD:4 | | EndToEnd.go:70:22:70:34 | selection of Form | EndToEnd.go:70:22:70:51 | call to Get | provenance | MaD:4 |
| Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | provenance | Src:MaD:1 | | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | provenance | Src:MaD:1 |
| examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | provenance | Src:MaD:2 | | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | provenance | Src:MaD:2 |
| examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | provenance | Src:MaD:2 | | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | provenance | Src:MaD:2 |
@@ -20,14 +20,14 @@ models
| 3 | Summary: io; StringWriter; true; WriteString; ; ; Argument[0]; Argument[receiver]; taint; manual | | 3 | Summary: io; StringWriter; true; WriteString; ; ; Argument[0]; Argument[receiver]; taint; manual |
| 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | | 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual |
nodes nodes
| EndToEnd.go:36:2:36:4 | buf [postupdate] | semmle.label | buf [postupdate] | | EndToEnd.go:37:2:37:4 | buf [postupdate] | semmle.label | buf [postupdate] |
| EndToEnd.go:36:18:36:25 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:37:18:37:25 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:36:18:36:30 | selection of Form | semmle.label | selection of Form | | EndToEnd.go:37:18:37:30 | selection of Form | semmle.label | selection of Form |
| EndToEnd.go:36:18:36:47 | call to Get | semmle.label | call to Get | | EndToEnd.go:37:18:37:47 | call to Get | semmle.label | call to Get |
| EndToEnd.go:37:24:37:26 | buf | semmle.label | buf | | EndToEnd.go:38:24:38:26 | buf | semmle.label | buf |
| EndToEnd.go:69:22:69:29 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:70:22:70:29 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:69:22:69:34 | selection of Form | semmle.label | selection of Form | | EndToEnd.go:70:22:70:34 | selection of Form | semmle.label | selection of Form |
| EndToEnd.go:69:22:69:51 | call to Get | semmle.label | call to Get | | EndToEnd.go:70:22:70:51 | call to Get | semmle.label | call to Get |
| Revel.go:70:22:70:29 | selection of Params | semmle.label | selection of Params | | Revel.go:70:22:70:29 | selection of Params | semmle.label | selection of Params |
| Revel.go:70:22:70:35 | selection of Query | semmle.label | selection of Query | | Revel.go:70:22:70:35 | selection of Query | semmle.label | selection of Query |
| examples/booking/app/init.go:36:44:36:48 | selection of URL | semmle.label | selection of URL | | examples/booking/app/init.go:36:44:36:48 | selection of URL | semmle.label | selection of URL |

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